Project

General

Profile

Feature #14605 ยป 0001-Remove-original_iseq-from-rb_iseq_constant_body.patch

tenderlovemaking (Aaron Patterson), 03/15/2018 12:32 AM

View differences:

compile.c
}
#endif
VALUE *
rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
typedef void * iseq_original_seq_t(void *ctx, const rb_iseq_t *iseq, VALUE * original_code);
void *
rb_iseq_with_original_iseq(const rb_iseq_t *iseq, iseq_original_seq_t * cb, void *ctx)
{
VALUE *original_code;
if (ISEQ_ORIGINAL_ISEQ(iseq)) return ISEQ_ORIGINAL_ISEQ(iseq);
original_code = ISEQ_ORIGINAL_ISEQ_ALLOC(iseq, iseq->body->iseq_size);
VALUE str = rb_str_tmp_new(iseq->body->iseq_size * sizeof(VALUE));
original_code = (VALUE *)RSTRING_PTR(str);
MEMCPY(original_code, iseq->body->iseq_encoded, VALUE, iseq->body->iseq_size);
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
......
}
}
#endif
return original_code;
return cb(ctx, iseq, original_code);
}
/*********************************************/
......
return (VALUE)rb_global_entry(gid);
}
static VALUE *
ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
static void *
ibf_dump_code_i(void *ctx, const rb_iseq_t *iseq, VALUE * orig_code)
{
struct ibf_dump *dump = (struct ibf_dump *)ctx;
const int iseq_size = iseq->body->iseq_size;
int code_index;
VALUE *code;
const VALUE *orig_code = rb_iseq_original_iseq(iseq);
code = ALLOCA_N(VALUE, iseq_size);
......
return IBF_W(code, VALUE, iseq_size);
}
static VALUE *
ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
return (VALUE *)(rb_iseq_with_original_iseq(iseq, ibf_dump_code_i, (void *)dump));
}
static VALUE *
ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, const struct rb_iseq_constant_body *body)
{
......
dump_body.ci_entries = ibf_dump_ci_entries(dump, iseq);
dump_body.cc_entries = NULL;
dump_body.variable.coverage = Qnil;
dump_body.variable.original_iseq = Qnil;
return ibf_dump_write(dump, &dump_body, sizeof(dump_body));
}
......
load_body->insns_info.size = body->insns_info.size;
ISEQ_COVERAGE_SET(iseq, Qnil);
ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
iseq->body->variable.flip_count = body->variable.flip_count;
{
iseq.c
}
rb_gc_mark(body->variable.coverage);
rb_gc_mark(body->variable.original_iseq);
rb_gc_mark(body->location.label);
rb_gc_mark(body->location.base_label);
rb_gc_mark(body->location.pathobj);
......
RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label);
}
ISEQ_COVERAGE_SET(iseq, Qnil);
ISEQ_ORIGINAL_ISEQ_CLEAR(iseq);
iseq->body->variable.flip_count = 0;
ISEQ_COMPILE_DATA_ALLOC(iseq);
......
}
}
struct iseq_disasm_iter_ctx {
VALUE str;
VALUE child;
};
static void *
iseq_disasm_iter(void *ctx, const rb_iseq_t *iseq, VALUE *code)
{
size_t n;
unsigned int size;
struct iseq_disasm_iter_ctx *ictx = (struct iseq_disasm_iter_ctx *)ctx;
VALUE str = ictx->str;
VALUE child = ictx->child;
size = iseq->body->iseq_size;
for (n = 0; n < size;) {
n += rb_iseq_disasm_insn(str, code, n, iseq, child);
}
return NULL;
}
VALUE
rb_iseq_disasm(const rb_iseq_t *iseq)
{
VALUE *code;
VALUE str = rb_str_new(0, 0);
VALUE child = rb_ary_tmp_new(3);
unsigned int size;
unsigned int i;
long l;
size_t n;
......
rb_secure(1);
size = iseq->body->iseq_size;
rb_str_cat2(str, "== disasm: ");
rb_str_concat(str, iseq_inspect(iseq));
......
}
/* show each line */
code = rb_iseq_original_iseq(iseq);
for (n = 0; n < size;) {
n += rb_iseq_disasm_insn(str, code, n, iseq, child);
}
struct iseq_disasm_iter_ctx ctx;
ctx.str = str;
ctx.child = child;
rb_iseq_with_original_iseq(iseq, iseq_disasm_iter, (void *)&ctx);
for (l = 0; l < RARRAY_LEN(child); l++) {
VALUE isv = rb_ary_entry(child, l);
......
return str;
}
static VALUE
rb_iseq_all_children(const rb_iseq_t *iseq)
static void *
rb_iseq_all_children_i(void *ctx, const rb_iseq_t *iseq, VALUE * code)
{
unsigned int i;
VALUE *code = rb_iseq_original_iseq(iseq);
VALUE all_children = rb_obj_hide(rb_ident_hash_new());
VALUE child;
......
}
i += len;
}
return all_children;
return (void *)all_children;
}
static VALUE
rb_iseq_all_children(const rb_iseq_t *iseq)
{
return (VALUE)rb_iseq_with_original_iseq(iseq, rb_iseq_all_children_i, NULL);
}
/*
......
return ST_CONTINUE;
}
struct iseq_data_to_ary_ctx {
VALUE * insn_syms;
struct st_table *labels_table;
VALUE body;
};
static void *
iseq_data_to_ary_i(void * _ctx, const rb_iseq_t *iseq, VALUE * iseq_original)
{
struct iseq_data_to_ary_ctx * ctx;
VALUE *seq;
VALUE *insn_syms;
VALUE body;
struct st_table *labels_table;
ctx = (struct iseq_data_to_ary_ctx *)_ctx;
body = rb_ary_new(); /* [[:insn1, ...], ...] */
insn_syms = ctx->insn_syms;
labels_table = ctx->labels_table;
for (seq = iseq_original; seq < iseq_original + iseq->body->iseq_size; ) {
VALUE insn = *seq++;
int j, len = insn_len(insn);
VALUE *nseq = seq + len - 1;
VALUE ary = rb_ary_new2(len);
rb_ary_push(ary, insn_syms[insn%numberof(insn_syms)]);
for (j=0; j<len-1; j++, seq++) {
switch (insn_op_type(insn, j)) {
case TS_OFFSET: {
unsigned long idx = nseq - iseq_original + *seq;
rb_ary_push(ary, register_label(labels_table, idx));
break;
}
case TS_LINDEX:
case TS_NUM:
rb_ary_push(ary, INT2FIX(*seq));
break;
case TS_VALUE:
rb_ary_push(ary, obj_resurrect(*seq));
break;
case TS_ISEQ:
{
const rb_iseq_t *iseq = (rb_iseq_t *)*seq;
if (iseq) {
VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
rb_ary_push(ary, val);
}
else {
rb_ary_push(ary, Qnil);
}
}
break;
case TS_GENTRY:
{
struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
rb_ary_push(ary, ID2SYM(entry->id));
}
break;
case TS_IC:
case TS_ISE:
{
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
rb_ary_push(ary, INT2FIX(is - iseq->body->is_entries));
}
break;
case TS_CALLINFO:
{
struct rb_call_info *ci = (struct rb_call_info *)*seq;
VALUE e = rb_hash_new();
int orig_argc = ci->orig_argc;
rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag));
if (ci->flag & VM_CALL_KWARG) {
struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
int i;
VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len);
orig_argc -= ci_kw->kw_arg->keyword_len;
for (i = 0; i < ci_kw->kw_arg->keyword_len; i++) {
rb_ary_push(kw, ci_kw->kw_arg->keywords[i]);
}
rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw);
}
rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")),
INT2FIX(orig_argc));
rb_ary_push(ary, e);
}
break;
case TS_CALLCACHE:
rb_ary_push(ary, Qfalse);
break;
case TS_ID:
rb_ary_push(ary, ID2SYM(*seq));
break;
case TS_CDHASH:
{
VALUE hash = *seq;
VALUE val = rb_ary_new();
int i;
rb_hash_foreach(hash, cdhash_each, val);
for (i=0; i<RARRAY_LEN(val); i+=2) {
VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
unsigned long idx = nseq - iseq_original + pos;
rb_ary_store(val, i+1,
register_label(labels_table, idx));
}
rb_ary_push(ary, val);
}
break;
case TS_FUNCPTR:
{
#if SIZEOF_VALUE <= SIZEOF_LONG
VALUE val = LONG2NUM((SIGNED_VALUE)*seq);
#else
VALUE val = LL2NUM((SIGNED_VALUE)*seq);
#endif
rb_ary_push(ary, val);
}
break;
default:
rb_bug("unknown operand: %c", insn_op_type(insn, j));
}
}
rb_ary_push(body, ary);
}
return (void *)body;
}
static VALUE
iseq_data_to_ary(const rb_iseq_t *iseq)
{
......
const struct iseq_insn_info_entry *prev_insn_info;
unsigned int pos;
int last_line = 0;
VALUE *seq, *iseq_original;
VALUE val = rb_ary_new();
VALUE type; /* Symbol */
VALUE locals = rb_ary_new();
VALUE params = rb_hash_new();
VALUE body = rb_ary_new(); /* [[:insn1, ...], ...] */
VALUE body;
VALUE nbody;
VALUE exception = rb_ary_new(); /* [[....]] */
VALUE misc = rb_hash_new();
......
}
/* body */
iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq);
for (seq = iseq_original; seq < iseq_original + iseq->body->iseq_size; ) {
VALUE insn = *seq++;
int j, len = insn_len(insn);
VALUE *nseq = seq + len - 1;
VALUE ary = rb_ary_new2(len);
rb_ary_push(ary, insn_syms[insn%numberof(insn_syms)]);
for (j=0; j<len-1; j++, seq++) {
switch (insn_op_type(insn, j)) {
case TS_OFFSET: {
unsigned long idx = nseq - iseq_original + *seq;
rb_ary_push(ary, register_label(labels_table, idx));
break;
}
case TS_LINDEX:
case TS_NUM:
rb_ary_push(ary, INT2FIX(*seq));
break;
case TS_VALUE:
rb_ary_push(ary, obj_resurrect(*seq));
break;
case TS_ISEQ:
{
const rb_iseq_t *iseq = (rb_iseq_t *)*seq;
if (iseq) {
VALUE val = iseq_data_to_ary(rb_iseq_check(iseq));
rb_ary_push(ary, val);
}
else {
rb_ary_push(ary, Qnil);
}
}
break;
case TS_GENTRY:
{
struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
rb_ary_push(ary, ID2SYM(entry->id));
}
break;
case TS_IC:
case TS_ISE:
{
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq;
rb_ary_push(ary, INT2FIX(is - iseq->body->is_entries));
}
break;
case TS_CALLINFO:
{
struct rb_call_info *ci = (struct rb_call_info *)*seq;
VALUE e = rb_hash_new();
int orig_argc = ci->orig_argc;
rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag));
if (ci->flag & VM_CALL_KWARG) {
struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
int i;
VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len);
orig_argc -= ci_kw->kw_arg->keyword_len;
for (i = 0; i < ci_kw->kw_arg->keyword_len; i++) {
rb_ary_push(kw, ci_kw->kw_arg->keywords[i]);
}
rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw);
}
rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")),
INT2FIX(orig_argc));
rb_ary_push(ary, e);
}
break;
case TS_CALLCACHE:
rb_ary_push(ary, Qfalse);
break;
case TS_ID:
rb_ary_push(ary, ID2SYM(*seq));
break;
case TS_CDHASH:
{
VALUE hash = *seq;
VALUE val = rb_ary_new();
int i;
rb_hash_foreach(hash, cdhash_each, val);
for (i=0; i<RARRAY_LEN(val); i+=2) {
VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
unsigned long idx = nseq - iseq_original + pos;
rb_ary_store(val, i+1,
register_label(labels_table, idx));
}
rb_ary_push(ary, val);
}
break;
case TS_FUNCPTR:
{
#if SIZEOF_VALUE <= SIZEOF_LONG
VALUE val = LONG2NUM((SIGNED_VALUE)*seq);
#else
VALUE val = LL2NUM((SIGNED_VALUE)*seq);
#endif
rb_ary_push(ary, val);
}
break;
default:
rb_bug("unknown operand: %c", insn_op_type(insn, j));
}
}
rb_ary_push(body, ary);
}
nbody = body;
struct iseq_data_to_ary_ctx ctx;
ctx.insn_syms = insn_syms;
ctx.labels_table = labels_table;
nbody = (VALUE)rb_iseq_with_original_iseq(iseq, iseq_data_to_ary_i, &ctx);
RB_GC_GUARD(nbody);
/* exception */
if (iseq->body->catch_table) for (i=0; i<iseq->body->catch_table->size; i++) {
......
#define INSN_CODE(insn) (insn)
#endif
static void *
rb_iseq_trace_set_i(void * ctx, const rb_iseq_t *iseq, VALUE *code)
{
unsigned int i;
rb_event_flag_t turnon_events = *(rb_event_flag_t*)ctx;
VALUE *iseq_encoded = (VALUE *)iseq->body->iseq_encoded;
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
const void * const *table = rb_vm_get_insns_address_table();
#endif
((rb_iseq_t *)iseq)->aux.trace_events = turnon_events;
for (i=0; i<iseq->body->iseq_size;) {
int insn = (int)code[i];
rb_event_flag_t events = rb_iseq_event_flags(iseq, i);
/* code represents before transformation */
VM_ASSERT(insn < VM_INSTRUCTION_SIZE/2);
if (events & turnon_events) {
if (!TRACE_INSN_P(insn)) {
iseq_encoded[i] = INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
}
}
else if (TRACE_INSN_P(insn)) {
iseq_encoded[i] = INSN_CODE(insn - VM_INSTRUCTION_SIZE/2);
}
i += insn_len(insn);
}
return NULL;
}
void
rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
{
......
return;
}
else {
unsigned int i;
VALUE *iseq_encoded = (VALUE *)iseq->body->iseq_encoded;
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
VALUE *code = rb_iseq_original_iseq(iseq);
const void * const *table = rb_vm_get_insns_address_table();
#else
const VALUE *code = iseq->body->iseq_encoded;
#endif
((rb_iseq_t *)iseq)->aux.trace_events = turnon_events;
for (i=0; i<iseq->body->iseq_size;) {
int insn = (int)code[i];
rb_event_flag_t events = rb_iseq_event_flags(iseq, i);
if (events & turnon_events) {
if (!TRACE_INSN_P(insn)) {
iseq_encoded[i] = INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
}
}
else if (TRACE_INSN_P(insn)) {
iseq_encoded[i] = INSN_CODE(insn - VM_INSTRUCTION_SIZE/2);
}
i += insn_len(insn);
}
/* clear for debugging: ISEQ_ORIGINAL_ISEQ_CLEAR(iseq); */
rb_iseq_with_original_iseq(iseq, rb_iseq_trace_set_i, &turnon_events);
}
}
iseq.h
return cnt;
}
static inline VALUE *
ISEQ_ORIGINAL_ISEQ(const rb_iseq_t *iseq)
{
VALUE str = iseq->body->variable.original_iseq;
if (RTEST(str)) return (VALUE *)RSTRING_PTR(str);
return NULL;
}
static inline void
ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq)
{
RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, Qnil);
}
static inline VALUE *
ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size)
{
VALUE str = rb_str_tmp_new(size * sizeof(VALUE));
RB_OBJ_WRITE(iseq, &iseq->body->variable.original_iseq, str);
return (VALUE *)RSTRING_PTR(str);
}
#define ISEQ_TRACE_EVENTS (RUBY_EVENT_LINE | \
RUBY_EVENT_CLASS | \
RUBY_EVENT_END | \
......
VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node);
VALUE rb_iseq_compile_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc);
int rb_iseq_translate_threaded_code(rb_iseq_t *iseq);
VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
typedef void * iseq_original_seq_t(void *ctx, const rb_iseq_t *iseq, VALUE * original_code);
void * rb_iseq_with_original_iseq(const rb_iseq_t *iseq, iseq_original_seq_t * cb, void *ctx);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
VALUE locals, VALUE args,
VALUE exception, VALUE body);
vm_core.h
struct {
rb_snum_t flip_count;
VALUE coverage;
VALUE original_iseq;
} variable;
unsigned int local_table_size;
vm_dump.c
rb_vmdebug_debug_print_register(rb_thread_ptr(thval)->ec);
}
static void *
rb_vmdebug_debug_print_pre_i(void * ctx, const rb_iseq_t *iseq, VALUE * iseq_original)
{
size_t pc = *(size_t *)ctx;
rb_iseq_disasm_insn(0, iseq_original, (size_t)pc, iseq, 0);
return NULL;
}
void
rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc)
{
......
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(ec, cfp)); */
if (pc >= 0) {
const VALUE *iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq);
rb_iseq_disasm_insn(0, iseq_original, (size_t)pc, iseq, 0);
rb_iseq_with_original_iseq(iseq, rb_vmdebug_debug_print_pre_i, &pc);
}
}
    (1-1/1)