* vm.c (VM_COLLECT_USAGE_DETAILS): make new VM usage analysis
hooks (old macro name is COLLECT_USAGE_ANALYSIS). This feature is only for VM developers. (I'm not sure I can use `VM developers' (the plural form) in this sentence). If VM_COLLECT_USAGE_DETAILS is not 0, VM enables the following usage collection features: (1) insntruction: collect intruction usages. (2) operand: collect operand usages. (3) register: collect register usages. The results are stored in RubyVM::USAGE_ANALYSIS_INSN for (1, 2), RubyVM::USAGE_ANALYSIS_INSN_BIGRAM for (1) and RubyVM::USAGE_ANALYSIS_REGS for (3). You can stop collecting usages with RubyVM::USAGE_ANALYSIS_INSN_STOP(), RubyVM::USAGE_ANALYSIS_OPERAND_STOP(), RubyVM::USAGE_ANALYSIS_REGISTER_STOP() for (1), (2), (3) respectively. You can also change the hook functions by setting C level global variables `ruby_vm_collect_usage_func_(insn|operand|register)' for (1), (2), (3) respectively. See codes for more details. * tool/instruction.rb: fix macro names. * iseq.c (insn_operand_intern): make it export (used in vm.c). fix to skip several processes if not needed (pointer is 0). * vm_dump.c: move codes for collection features to vm.c. * vm_exec.h: rename macro and function names. * vm_insnhelper.h: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37085 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b1ad79774d
commit
23dc0dbc4a
37
ChangeLog
37
ChangeLog
@ -1,3 +1,40 @@
|
||||
Thu Oct 4 21:15:26 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm.c (VM_COLLECT_USAGE_DETAILS): make new VM usage analysis
|
||||
hooks (old macro name is COLLECT_USAGE_ANALYSIS).
|
||||
This feature is only for VM developers. (I'm not sure I can use
|
||||
`VM developers' (the plural form) in this sentence).
|
||||
If VM_COLLECT_USAGE_DETAILS is not 0, VM enables the following
|
||||
usage collection features:
|
||||
(1) insntruction: collect intruction usages.
|
||||
(2) operand: collect operand usages.
|
||||
(3) register: collect register usages.
|
||||
The results are stored in
|
||||
RubyVM::USAGE_ANALYSIS_INSN for (1, 2),
|
||||
RubyVM::USAGE_ANALYSIS_INSN_BIGRAM for (1) and
|
||||
RubyVM::USAGE_ANALYSIS_REGS for (3).
|
||||
You can stop collecting usages with
|
||||
RubyVM::USAGE_ANALYSIS_INSN_STOP(),
|
||||
RubyVM::USAGE_ANALYSIS_OPERAND_STOP(),
|
||||
RubyVM::USAGE_ANALYSIS_REGISTER_STOP()
|
||||
for (1), (2), (3) respectively.
|
||||
You can also change the hook functions by setting
|
||||
C level global variables
|
||||
`ruby_vm_collect_usage_func_(insn|operand|register)'
|
||||
for (1), (2), (3) respectively.
|
||||
See codes for more details.
|
||||
|
||||
* tool/instruction.rb: fix macro names.
|
||||
|
||||
* iseq.c (insn_operand_intern): make it export (used in vm.c).
|
||||
fix to skip several processes if not needed (pointer is 0).
|
||||
|
||||
* vm_dump.c: move codes for collection features to vm.c.
|
||||
|
||||
* vm_exec.h: rename macro and function names.
|
||||
|
||||
* vm_insnhelper.h: ditto.
|
||||
|
||||
Thu Oct 4 18:59:14 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* test/ruby/test_settracefunc.rb (test_tracepoint):
|
||||
|
23
iseq.c
23
iseq.c
@ -963,7 +963,7 @@ id_to_name(ID id, VALUE default_value)
|
||||
return str;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
VALUE
|
||||
insn_operand_intern(rb_iseq_t *iseq,
|
||||
VALUE insn, int op_no, VALUE op,
|
||||
int len, size_t pos, VALUE *pnop, VALUE child)
|
||||
@ -991,13 +991,18 @@ insn_operand_intern(rb_iseq_t *iseq,
|
||||
}
|
||||
case TS_DINDEX:{
|
||||
if (insn == BIN(getdynamic) || insn == BIN(setdynamic)) {
|
||||
rb_iseq_t *diseq = iseq;
|
||||
VALUE level = *pnop, i;
|
||||
if (pnop) {
|
||||
rb_iseq_t *diseq = iseq;
|
||||
VALUE level = *pnop, i;
|
||||
|
||||
for (i = 0; i < level; i++) {
|
||||
diseq = diseq->parent_iseq;
|
||||
for (i = 0; i < level; i++) {
|
||||
diseq = diseq->parent_iseq;
|
||||
}
|
||||
ret = id_to_name(diseq->local_table[diseq->local_size - op], INT2FIX('*'));
|
||||
}
|
||||
else {
|
||||
ret = rb_sprintf("%"PRIuVALUE, op);
|
||||
}
|
||||
ret = id_to_name(diseq->local_table[diseq->local_size - op], INT2FIX('*'));
|
||||
}
|
||||
else {
|
||||
ret = rb_inspect(INT2FIX(op));
|
||||
@ -1011,7 +1016,9 @@ insn_operand_intern(rb_iseq_t *iseq,
|
||||
op = obj_resurrect(op);
|
||||
ret = rb_inspect(op);
|
||||
if (CLASS_OF(op) == rb_cISeq) {
|
||||
rb_ary_push(child, op);
|
||||
if (child) {
|
||||
rb_ary_push(child, op);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1049,7 +1056,7 @@ insn_operand_intern(rb_iseq_t *iseq,
|
||||
break;
|
||||
|
||||
default:
|
||||
rb_bug("rb_iseq_disasm: unknown operand type: %c", type);
|
||||
rb_bug("insn_operand_intern: unknown operand type: %c", type);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -791,9 +791,9 @@ class RubyVM
|
||||
end
|
||||
|
||||
def make_header_analysis insn
|
||||
commit " USAGE_ANALYSIS_INSN(BIN(#{insn.name}));"
|
||||
commit " COLLECT_USAGE_INSN(BIN(#{insn.name}));"
|
||||
insn.opes.each_with_index{|op, i|
|
||||
commit " USAGE_ANALYSIS_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});"
|
||||
commit " COLLECT_USAGE_OPERAND(BIN(#{insn.name}), #{i}, #{op[1]});"
|
||||
}
|
||||
end
|
||||
|
||||
|
222
vm.c
222
vm.c
@ -61,6 +61,16 @@ rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp)
|
||||
return VM_CF_BLOCK_PTR(cfp);
|
||||
}
|
||||
|
||||
#ifndef VM_COLLECT_USAGE_DETAILS
|
||||
#define VM_COLLECT_USAGE_DETAILS 0
|
||||
#endif
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
static void vm_collect_usage_operand(int insn, int n, VALUE op);
|
||||
static void vm_collect_usage_register(int reg, int isset);
|
||||
static void vm_collect_usage_insn(int insn);
|
||||
#endif
|
||||
|
||||
static VALUE
|
||||
vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
|
||||
int argc, const VALUE *argv, const rb_block_t *blockptr);
|
||||
@ -91,10 +101,6 @@ rb_event_flag_t ruby_vm_event_flags;
|
||||
|
||||
static void thread_free(void *ptr);
|
||||
|
||||
void vm_analysis_operand(int insn, int n, VALUE op);
|
||||
void vm_analysis_register(int reg, int isset);
|
||||
void vm_analysis_insn(int insn);
|
||||
|
||||
void
|
||||
rb_vm_change_state(void)
|
||||
{
|
||||
@ -2070,6 +2076,12 @@ nsdr(void)
|
||||
return ary;
|
||||
}
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
static VALUE usage_analysis_insn_stop(VALUE self);
|
||||
static VALUE usage_analysis_operand_stop(VALUE self);
|
||||
static VALUE usage_analysis_register_stop(VALUE self);
|
||||
#endif
|
||||
|
||||
void
|
||||
Init_VM(void)
|
||||
{
|
||||
@ -2109,10 +2121,18 @@ Init_VM(void)
|
||||
rb_cThread = rb_define_class("Thread", rb_cObject);
|
||||
rb_undef_alloc_func(rb_cThread);
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
/* ::RubyVM::USAGE_ANALYSIS_* */
|
||||
rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_INSN", rb_hash_new());
|
||||
rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_REGS", rb_hash_new());
|
||||
rb_define_const(rb_cRubyVM, "USAGE_ANALYSIS_INSN_BIGRAM", rb_hash_new());
|
||||
|
||||
rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_INSN_STOP", usage_analysis_insn_stop, 0);
|
||||
rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_OPERAND_STOP", usage_analysis_operand_stop, 0);
|
||||
rb_define_singleton_method(rb_cRubyVM, "USAGE_ANALYSIS_REGISTER_STOP", usage_analysis_register_stop, 0);
|
||||
#endif
|
||||
|
||||
/* ::RubyVM::OPTS, which shows vm build options */
|
||||
rb_define_const(rb_cRubyVM, "OPTS", opts = rb_ary_new());
|
||||
|
||||
#if OPT_DIRECT_THREADED_CODE
|
||||
@ -2281,3 +2301,197 @@ rb_ruby_debug_ptr(void)
|
||||
{
|
||||
return ruby_vm_debug_ptr(GET_VM());
|
||||
}
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
|
||||
/* uh = {
|
||||
* insn(Fixnum) => ihash(Hash)
|
||||
* }
|
||||
* ihash = {
|
||||
* -1(Fixnum) => count, # insn usage
|
||||
* 0(Fixnum) => ophash, # operand usage
|
||||
* }
|
||||
* ophash = {
|
||||
* val(interned string) => count(Fixnum)
|
||||
* }
|
||||
*/
|
||||
static void
|
||||
vm_analysis_insn(int insn)
|
||||
{
|
||||
ID usage_hash;
|
||||
ID bigram_hash;
|
||||
static int prev_insn = -1;
|
||||
|
||||
VALUE uh;
|
||||
VALUE ihash;
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
|
||||
CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
|
||||
ihash = rb_hash_new();
|
||||
rb_hash_aset(uh, INT2FIX(insn), ihash);
|
||||
}
|
||||
if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
|
||||
|
||||
/* calc bigram */
|
||||
if (prev_insn != -1) {
|
||||
VALUE bi;
|
||||
VALUE ary[2];
|
||||
VALUE cv;
|
||||
|
||||
ary[0] = INT2FIX(prev_insn);
|
||||
ary[1] = INT2FIX(insn);
|
||||
bi = rb_ary_new4(2, &ary[0]);
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, bigram_hash);
|
||||
if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(uh, bi, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
prev_insn = insn;
|
||||
}
|
||||
|
||||
/* iseq.c */
|
||||
VALUE insn_operand_intern(rb_iseq_t *iseq,
|
||||
VALUE insn, int op_no, VALUE op,
|
||||
int len, size_t pos, VALUE *pnop, VALUE child);
|
||||
|
||||
static void
|
||||
vm_analysis_operand(int insn, int n, VALUE op)
|
||||
{
|
||||
ID usage_hash;
|
||||
|
||||
VALUE uh;
|
||||
VALUE ihash;
|
||||
VALUE ophash;
|
||||
VALUE valstr;
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
|
||||
ihash = rb_hash_new();
|
||||
rb_hash_aset(uh, INT2FIX(insn), ihash);
|
||||
}
|
||||
if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
|
||||
ophash = rb_hash_new();
|
||||
rb_hash_aset(ihash, INT2FIX(n), ophash);
|
||||
}
|
||||
/* intern */
|
||||
valstr = insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
|
||||
|
||||
/* set count */
|
||||
if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
vm_analysis_register(int reg, int isset)
|
||||
{
|
||||
ID usage_hash;
|
||||
VALUE uh;
|
||||
VALUE valstr;
|
||||
static const char regstrs[][5] = {
|
||||
"pc", /* 0 */
|
||||
"sp", /* 1 */
|
||||
"ep", /* 2 */
|
||||
"cfp", /* 3 */
|
||||
"self", /* 4 */
|
||||
"iseq", /* 5 */
|
||||
};
|
||||
static const char getsetstr[][4] = {
|
||||
"get",
|
||||
"set",
|
||||
};
|
||||
static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
|
||||
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
|
||||
if (syms[0] == 0) {
|
||||
char buff[0x10];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(regstrs) / sizeof(regstrs[0])); i++) {
|
||||
int j;
|
||||
for (j = 0; j < 2; j++) {
|
||||
snprintf(buff, 0x10, "%d %s %-4s", i, getsetstr[j], regstrs[i]);
|
||||
syms[i][j] = ID2SYM(rb_intern(buff));
|
||||
}
|
||||
}
|
||||
}
|
||||
valstr = syms[reg][isset];
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
|
||||
void (*ruby_vm_collect_usage_func_insn)(int insn) = vm_analysis_insn;
|
||||
void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = vm_analysis_operand;
|
||||
void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = vm_analysis_register;
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
usage_analysis_insn_stop(VALUE self)
|
||||
{
|
||||
ruby_vm_collect_usage_func_insn = 0;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
usage_analysis_operand_stop(VALUE self)
|
||||
{
|
||||
ruby_vm_collect_usage_func_operand = 0;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* :nodoc: */
|
||||
static VALUE
|
||||
usage_analysis_register_stop(VALUE self)
|
||||
{
|
||||
ruby_vm_collect_usage_func_register = 0;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* @param insn instruction number */
|
||||
static void
|
||||
vm_collect_usage_insn(int insn)
|
||||
{
|
||||
if (ruby_vm_collect_usage_func_insn)
|
||||
(*ruby_vm_collect_usage_func_insn)(insn);
|
||||
}
|
||||
|
||||
/* @param insn instruction number
|
||||
* @param n n-th operand
|
||||
* @param op operand value
|
||||
*/
|
||||
static void
|
||||
vm_collect_usage_operand(int insn, int n, VALUE op)
|
||||
{
|
||||
if (ruby_vm_collect_usage_func_operand)
|
||||
(*ruby_vm_collect_usage_func_operand)(insn, n, op);
|
||||
}
|
||||
|
||||
/* @param reg register id. see code of vm_analysis_register() */
|
||||
/* @param iseset 0: read, 1: write */
|
||||
static void
|
||||
vm_collect_usage_register(int reg, int isset)
|
||||
{
|
||||
if (ruby_vm_collect_usage_func_register)
|
||||
(*ruby_vm_collect_usage_func_register)(reg, isset);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
139
vm_dump.c
139
vm_dump.c
@ -395,145 +395,6 @@ rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COLLECT_USAGE_ANALYSIS
|
||||
/* uh = {
|
||||
* insn(Fixnum) => ihash(Hash)
|
||||
* }
|
||||
* ihash = {
|
||||
* -1(Fixnum) => count, # insn usage
|
||||
* 0(Fixnum) => ophash, # operand usage
|
||||
* }
|
||||
* ophash = {
|
||||
* val(interned string) => count(Fixnum)
|
||||
* }
|
||||
*/
|
||||
void
|
||||
vm_analysis_insn(int insn)
|
||||
{
|
||||
ID usage_hash;
|
||||
ID bigram_hash;
|
||||
static int prev_insn = -1;
|
||||
|
||||
VALUE uh;
|
||||
VALUE ihash;
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
|
||||
CONST_ID(bigram_hash, "USAGE_ANALYSIS_INSN_BIGRAM");
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
|
||||
ihash = rb_hash_new();
|
||||
rb_hash_aset(uh, INT2FIX(insn), ihash);
|
||||
}
|
||||
if ((cv = rb_hash_aref(ihash, INT2FIX(-1))) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(ihash, INT2FIX(-1), INT2FIX(FIX2INT(cv) + 1));
|
||||
|
||||
/* calc bigram */
|
||||
if (prev_insn != -1) {
|
||||
VALUE bi;
|
||||
VALUE ary[2];
|
||||
VALUE cv;
|
||||
|
||||
ary[0] = INT2FIX(prev_insn);
|
||||
ary[1] = INT2FIX(insn);
|
||||
bi = rb_ary_new4(2, &ary[0]);
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, bigram_hash);
|
||||
if ((cv = rb_hash_aref(uh, bi)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(uh, bi, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
prev_insn = insn;
|
||||
}
|
||||
|
||||
/* from disasm.c */
|
||||
extern VALUE insn_operand_intern(int insn, int op_no, VALUE op,
|
||||
int len, int pos, VALUE child);
|
||||
|
||||
void
|
||||
vm_analysis_operand(int insn, int n, VALUE op)
|
||||
{
|
||||
ID usage_hash;
|
||||
|
||||
VALUE uh;
|
||||
VALUE ihash;
|
||||
VALUE ophash;
|
||||
VALUE valstr;
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_INSN");
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((ihash = rb_hash_aref(uh, INT2FIX(insn))) == Qnil) {
|
||||
ihash = rb_hash_new();
|
||||
rb_hash_aset(uh, INT2FIX(insn), ihash);
|
||||
}
|
||||
if ((ophash = rb_hash_aref(ihash, INT2FIX(n))) == Qnil) {
|
||||
ophash = rb_hash_new();
|
||||
rb_hash_aset(ihash, INT2FIX(n), ophash);
|
||||
}
|
||||
/* intern */
|
||||
valstr = insn_operand_intern(insn, n, op, 0, 0, 0);
|
||||
|
||||
/* set count */
|
||||
if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(ophash, valstr, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
|
||||
void
|
||||
vm_analysis_register(int reg, int isset)
|
||||
{
|
||||
ID usage_hash;
|
||||
VALUE uh;
|
||||
VALUE rhash;
|
||||
VALUE valstr;
|
||||
static const char regstrs[][5] = {
|
||||
"pc", /* 0 */
|
||||
"sp", /* 1 */
|
||||
"ep", /* 2 */
|
||||
"cfp", /* 3 */
|
||||
"self", /* 4 */
|
||||
"iseq", /* 5 */
|
||||
};
|
||||
static const char getsetstr[][4] = {
|
||||
"get",
|
||||
"set",
|
||||
};
|
||||
static VALUE syms[sizeof(regstrs) / sizeof(regstrs[0])][2];
|
||||
|
||||
VALUE cv;
|
||||
|
||||
CONST_ID(usage_hash, "USAGE_ANALYSIS_REGS");
|
||||
if (syms[0] == 0) {
|
||||
char buff[0x10];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(regstrs) / sizeof(regstrs[0]); i++) {
|
||||
int j;
|
||||
for (j = 0; j < 2; j++) {
|
||||
snfprintf(stderr, buff, 0x10, "%d %s %-4s", i, getsetstr[j],
|
||||
regstrs[i]);
|
||||
syms[i][j] = ID2SYM(rb_intern(buff));
|
||||
}
|
||||
}
|
||||
}
|
||||
valstr = syms[reg][isset];
|
||||
|
||||
uh = rb_const_get(rb_cRubyVM, usage_hash);
|
||||
if ((cv = rb_hash_aref(uh, valstr)) == Qnil) {
|
||||
cv = INT2FIX(0);
|
||||
}
|
||||
rb_hash_aset(uh, valstr, INT2FIX(FIX2INT(cv) + 1));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
VALUE
|
||||
rb_vmdebug_thread_dump_state(VALUE self)
|
||||
{
|
||||
|
10
vm_exec.h
10
vm_exec.h
@ -18,16 +18,6 @@ typedef unsigned long dindex_t;
|
||||
typedef rb_num_t GENTRY;
|
||||
typedef rb_iseq_t *ISEQ;
|
||||
|
||||
#ifdef COLLECT_USAGE_ANALYSIS
|
||||
#define USAGE_ANALYSIS_INSN(insn) vm_analysis_insn(insn)
|
||||
#define USAGE_ANALYSIS_OPERAND(insn, n, op) vm_analysis_operand((insn), (n), (VALUE)(op))
|
||||
#define USAGE_ANALYSIS_REGISTER(reg, s) vm_analysis_register((reg), (s))
|
||||
#else
|
||||
#define USAGE_ANALYSIS_INSN(insn) /* none */
|
||||
#define USAGE_ANALYSIS_OPERAND(insn, n, op) /* none */
|
||||
#define USAGE_ANALYSIS_REGISTER(reg, s) /* none */
|
||||
#endif
|
||||
|
||||
#ifdef __GCC__
|
||||
/* TODO: machine dependent prefetch instruction */
|
||||
#define PREFETCH(pc)
|
||||
|
@ -62,6 +62,15 @@ enum {
|
||||
extern char ruby_vm_redefined_flag[BOP_LAST_];
|
||||
extern VALUE ruby_vm_const_missing_count;
|
||||
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
#define COLLECT_USAGE_INSN(insn) vm_collect_usage_insn(insn)
|
||||
#define COLLECT_USAGE_OPERAND(insn, n, op) vm_collect_usage_operand((insn), (n), ((VALUE)(op)))
|
||||
#define COLLECT_USAGE_REGISTER(reg, s) vm_collect_usage_register((reg), (s))
|
||||
#else
|
||||
#define COLLECT_USAGE_INSN(insn) /* none */
|
||||
#define COLLECT_USAGE_OPERAND(insn, n, op) /* none */
|
||||
#define COLLECT_USAGE_REGISTER(reg, s) /* none */
|
||||
#endif
|
||||
|
||||
/**********************************************************/
|
||||
/* deal with stack */
|
||||
@ -104,16 +113,16 @@ enum vm_regan_acttype {
|
||||
VM_REGAN_ACT_SET = 1,
|
||||
};
|
||||
|
||||
#ifdef COLLECT_USAGE_ANALYSIS
|
||||
#define USAGE_ANALYSIS_REGISTER_HELPER(a, b, v) \
|
||||
(USAGE_ANALYSIS_REGISTER((VM_REGAN_#a), (VM_REGAN_ACT_#b)), (v))
|
||||
#if VM_COLLECT_USAGE_DETAILS
|
||||
#define COLLECT_USAGE_REGISTER_HELPER(a, b, v) \
|
||||
(COLLECT_USAGE_REGISTER((VM_REGAN_##a), (VM_REGAN_ACT_##b)), (v))
|
||||
#else
|
||||
#define USAGE_ANALYSIS_REGISTER_HELPER(a, b, v) (v)
|
||||
#define COLLECT_USAGE_REGISTER_HELPER(a, b, v) (v)
|
||||
#endif
|
||||
|
||||
/* PC */
|
||||
#define GET_PC() (USAGE_ANALYSIS_REGISTER_HELPER(PC, GET, REG_PC))
|
||||
#define SET_PC(x) (REG_PC = (USAGE_ANALYSIS_REGISTER_HELPER(PC, SET, (x))))
|
||||
#define GET_PC() (COLLECT_USAGE_REGISTER_HELPER(PC, GET, REG_PC))
|
||||
#define SET_PC(x) (REG_PC = (COLLECT_USAGE_REGISTER_HELPER(PC, SET, (x))))
|
||||
#define GET_CURRENT_INSN() (*GET_PC())
|
||||
#define GET_OPERAND(n) (GET_PC()[(n)])
|
||||
#define ADD_PC(n) (SET_PC(REG_PC + (n)))
|
||||
@ -122,16 +131,16 @@ enum vm_regan_acttype {
|
||||
#define JUMP(dst) (REG_PC += (dst))
|
||||
|
||||
/* frame pointer, environment pointer */
|
||||
#define GET_CFP() (USAGE_ANALYSIS_REGISTER_HELPER(CFP, GET, REG_CFP))
|
||||
#define GET_EP() (USAGE_ANALYSIS_REGISTER_HELPER(EP, GET, REG_EP))
|
||||
#define SET_EP(x) (REG_EP = (USAGE_ANALYSIS_REGISTER_HELPER(EP, SET, (x))))
|
||||
#define GET_CFP() (COLLECT_USAGE_REGISTER_HELPER(CFP, GET, REG_CFP))
|
||||
#define GET_EP() (COLLECT_USAGE_REGISTER_HELPER(EP, GET, REG_EP))
|
||||
#define SET_EP(x) (REG_EP = (COLLECT_USAGE_REGISTER_HELPER(EP, SET, (x))))
|
||||
#define GET_LEP() (VM_EP_LEP(GET_EP()))
|
||||
|
||||
/* SP */
|
||||
#define GET_SP() (USAGE_ANALYSIS_REGISTER_HELPER(SP, GET, REG_SP))
|
||||
#define SET_SP(x) (REG_SP = (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define INC_SP(x) (REG_SP += (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define DEC_SP(x) (REG_SP -= (USAGE_ANALYSIS_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define GET_SP() (COLLECT_USAGE_REGISTER_HELPER(SP, GET, REG_SP))
|
||||
#define SET_SP(x) (REG_SP = (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define INC_SP(x) (REG_SP += (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define DEC_SP(x) (REG_SP -= (COLLECT_USAGE_REGISTER_HELPER(SP, SET, (x))))
|
||||
#define SET_SV(x) (*GET_SP() = (x))
|
||||
/* set current stack value as x */
|
||||
|
||||
@ -155,7 +164,7 @@ enum vm_regan_acttype {
|
||||
/* deal with values */
|
||||
/**********************************************************/
|
||||
|
||||
#define GET_SELF() (USAGE_ANALYSIS_REGISTER_HELPER(5, 0, GET_CFP()->self))
|
||||
#define GET_SELF() (COLLECT_USAGE_REGISTER_HELPER(SELF, GET, GET_CFP()->self))
|
||||
|
||||
/**********************************************************/
|
||||
/* deal with control flow 2: method/iterator */
|
||||
|
Loading…
x
Reference in New Issue
Block a user