From 58cc1a8f03d68e9dd4f142e8fba576bb730d8a0a Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 13 Mar 2018 16:42:40 -0700 Subject: [PATCH] Remove `original_iseq` from `rb_iseq_constant_body` This patch replaces `rb_iseq_original_iseq` with a function that decodes the instructions and calls a callback with the decoded instructions. This way we don't need to store the temporary decoded instructions in the iseq struct, we just keep it on the stack and let it go when we're done. --- compile.c | 26 +++-- iseq.c | 366 +++++++++++++++++++++++++++++++++++--------------------------- iseq.h | 27 +---- vm_core.h | 1 - vm_dump.c | 12 ++- 5 files changed, 239 insertions(+), 193 deletions(-) diff --git a/compile.c b/compile.c index 2c388b8a8c..a985164a99 100644 --- a/compile.c +++ b/compile.c @@ -761,13 +761,15 @@ rb_vm_insn_addr2insn(const void *addr) /* cold path */ } #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 @@ -783,7 +785,7 @@ rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */ } } #endif - return original_code; + return cb(ctx, iseq, original_code); } /*********************************************/ @@ -8330,13 +8332,13 @@ ibf_load_gentry(const struct ibf_load *load, const struct rb_global_entry *entry 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); @@ -8395,6 +8397,12 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) 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) { @@ -8726,7 +8734,6 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) 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)); } @@ -8759,7 +8766,6 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of 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; { diff --git a/iseq.c b/iseq.c index f9a676b0d8..87c606defd 100644 --- a/iseq.c +++ b/iseq.c @@ -222,7 +222,6 @@ rb_iseq_mark(const rb_iseq_t *iseq) } 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); @@ -432,7 +431,6 @@ prepare_iseq_build(rb_iseq_t *iseq, 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); @@ -1897,13 +1895,35 @@ iseq_inspect(const rb_iseq_t *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; @@ -1912,8 +1932,6 @@ rb_iseq_disasm(const rb_iseq_t *iseq) rb_secure(1); - size = iseq->body->iseq_size; - rb_str_cat2(str, "== disasm: "); rb_str_concat(str, iseq_inspect(iseq)); @@ -1995,10 +2013,11 @@ rb_iseq_disasm(const rb_iseq_t *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); @@ -2010,11 +2029,10 @@ rb_iseq_disasm(const rb_iseq_t *iseq) 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; @@ -2047,7 +2065,13 @@ rb_iseq_all_children(const rb_iseq_t *iseq) } 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); } /* @@ -2300,6 +2324,141 @@ cdhash_each(VALUE key, VALUE value, VALUE ary) 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; jid)); + } + 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; ibody->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; jid)); - } - 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; ibody->catch_table) for (i=0; ibody->catch_table->size; i++) { @@ -2766,6 +2813,37 @@ rb_iseq_defined_string(enum defined_type type) #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; ibody->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) { @@ -2779,31 +2857,7 @@ 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; ibody->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); } } diff --git a/iseq.h b/iseq.h index 0a0edd9b7a..47bfa2f813 100644 --- a/iseq.h +++ b/iseq.h @@ -43,28 +43,6 @@ ISEQ_FLIP_CNT_INCREMENT(const rb_iseq_t *iseq) 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 | \ @@ -150,7 +128,10 @@ RUBY_SYMBOL_EXPORT_BEGIN 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); diff --git a/vm_core.h b/vm_core.h index 9b8aede35c..3b1ca6c382 100644 --- a/vm_core.h +++ b/vm_core.h @@ -414,7 +414,6 @@ struct rb_iseq_constant_body { struct { rb_snum_t flip_count; VALUE coverage; - VALUE original_iseq; } variable; unsigned int local_table_size; diff --git a/vm_dump.c b/vm_dump.c index 67afcff5e4..c0ae7908f0 100644 --- a/vm_dump.c +++ b/vm_dump.c @@ -329,6 +329,14 @@ rb_vmdebug_thread_dump_regs(VALUE thval) 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) { @@ -346,9 +354,7 @@ rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_fr /* 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); } } -- 2.14.2