iseq.c: add a map from encoded insn to insn data

This enhances rb_vm_insn_addr2insn which retrieves a decoded insn number
from encoded insn.
The insn data table include not only decoded insn number, but also its
len, trace and non-trace version of encoded insn.
This table can be used to simplify trace instrumentation.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mame 2018-08-23 08:32:30 +00:00
parent bf6e2eb7e7
commit d574683c40
4 changed files with 54 additions and 35 deletions

View File

@ -746,35 +746,6 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
return COMPILE_OK;
}
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
static st_table *addr2insn;
void
rb_addr2insn_init(void)
{
const void * const *table = rb_vm_get_insns_address_table();
st_data_t insn;
addr2insn = st_init_numtable_with_size(VM_INSTRUCTION_SIZE);
for (insn = 0; insn < VM_INSTRUCTION_SIZE; insn++) {
st_add_direct(addr2insn, (st_data_t)table[insn], insn);
}
}
int
rb_vm_insn_addr2insn(const void *addr)
{
st_data_t key = (st_data_t)addr;
st_data_t val;
if (st_lookup(addr2insn, key, &val)) {
return (int)val;
}
rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
}
#endif /* OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE */
VALUE *
rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
{

2
eval.c
View File

@ -66,7 +66,7 @@ ruby_setup(void)
#endif
Init_BareVM();
Init_heap();
rb_addr2insn_init();
rb_vm_encoded_insn_data_table_init();
Init_vm_objects();
EC_PUSH_TAG(GET_EC());

52
iseq.c
View File

@ -2862,6 +2862,58 @@ rb_iseq_defined_string(enum defined_type type)
return str;
}
/* A map from encoded_insn to insn_data: decoded insn number, its len,
* non-trace version of encoded insn, and trace version. */
static st_table *encoded_insn_data;
typedef struct insn_data_struct {
int insn;
int insn_len;
void *notrace_encoded_insn;
void *trace_encoded_insn;
} insn_data_t;
static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
void
rb_vm_encoded_insn_data_table_init(void)
{
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
const void * const *table = rb_vm_get_insns_address_table();
#define INSN_CODE(insn) ((VALUE)table[insn])
#else
#define INSN_CODE(insn) (insn)
#endif
st_data_t insn;
encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2);
for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) {
st_data_t key1 = (st_data_t)INSN_CODE(insn);
st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
insn_data[insn].insn = insn;
insn_data[insn].insn_len = insn_len(insn);
insn_data[insn].notrace_encoded_insn = (void *) key1;
insn_data[insn].trace_encoded_insn = (void *) key2;
st_add_direct(encoded_insn_data, key1, (st_data_t)&insn_data[insn]);
st_add_direct(encoded_insn_data, key2, (st_data_t)&insn_data[insn]);
}
}
int
rb_vm_insn_addr2insn(const void *addr)
{
st_data_t key = (st_data_t)addr;
st_data_t val;
if (st_lookup(encoded_insn_data, key, &val)) {
insn_data_t *e = (insn_data_t *)val;
return (int)e->insn;
}
rb_bug("rb_vm_insn_addr2insn: invalid insn address: %p", addr);
}
#define TRACE_INSN_P(insn) ((insn) >= VM_INSTRUCTION_SIZE/2)

View File

@ -164,11 +164,7 @@ void *rb_register_sigaltstack(void);
#endif /* OPT_STACK_CACHING */
#endif /* OPT_CALL_THREADED_CODE */
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
void rb_addr2insn_init(void);
#else
static inline void rb_addr2insn_init(void) { }
#endif
void rb_vm_encoded_insn_data_table_init(void);
typedef unsigned long rb_num_t;
typedef signed long rb_snum_t;