ruby-changes:39822
From: ko1 <ko1@a...>
Date: Sun, 20 Sep 2015 03:00:30 +0900 (JST)
Subject: [ruby-changes:39822] ko1:r51903 (trunk): * vm_core.h: split rb_call_info_t into several structs.
ko1 2015-09-20 02:59:58 +0900 (Sun, 20 Sep 2015) New Revision: 51903 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51903 Log: * vm_core.h: split rb_call_info_t into several structs. * rb_call_info (ci) has compiled fixed information. * if ci->flag & VM_CALL_KWARG, then rb_call_info is also rb_call_info_with_kwarg. This technique reduce one word for major rb_call_info data. * rb_calling_info has temporary data (argc, blockptr, recv). for each method dispatch. This data is allocated only on machine stack. * rb_call_cache is for inline method cache. Before this patch, only rb_call_info_t data is passed. After this patch, above three structs are passed. This patch improves: * data locarity (rb_call_info is now read-only data). * reduce memory consumption (rb_call_info_with_kwarg, rb_calling_info). * compile.c: use above data. * insns.def: ditto. * iseq.c: ditto. * vm_args.c: ditto. * vm_eval.c: ditto. * vm_insnhelper.c: ditto. * vm_insnhelper.h: ditto. * iseq.h: add iseq_compile_data::ci_index and iseq_compile_data::ci_kw_indx. * tool/instruction.rb: introduce TS_CALLCACHE operand type. Modified files: trunk/ChangeLog trunk/compile.c trunk/insns.def trunk/iseq.c trunk/iseq.h trunk/tool/instruction.rb trunk/vm.c trunk/vm_args.c trunk/vm_core.h trunk/vm_eval.c trunk/vm_insnhelper.c trunk/vm_insnhelper.h Index: insns.def =================================================================== --- insns.def (revision 51902) +++ insns.def (revision 51903) @@ -936,14 +936,15 @@ defineclass https://github.com/ruby/ruby/blob/trunk/insns.def#L936 */ DEFINE_INSN send -(CALL_INFO ci, ISEQ iseq) +(CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq) (...) (VALUE val) // inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0)); { - ci->argc = ci->orig_argc; - vm_caller_setup_arg_block(th, reg_cfp, ci, iseq, FALSE); - vm_search_method(ci, ci->recv = TOPN(ci->argc)); - CALL_METHOD(ci); + struct rb_calling_info calling; + + vm_caller_setup_arg_block(th, reg_cfp, &calling, ci, blockiseq, FALSE); + vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc)); + CALL_METHOD(&calling, ci, cc); } DEFINE_INSN @@ -967,13 +968,14 @@ opt_str_freeze https://github.com/ruby/ruby/blob/trunk/insns.def#L968 */ DEFINE_INSN opt_send_without_block -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (...) (VALUE val) // inc += -ci->orig_argc; { - ci->argc = ci->orig_argc; - vm_search_method(ci, ci->recv = TOPN(ci->argc)); - CALL_METHOD(ci); + struct rb_calling_info calling; + calling.blockptr = NULL; + vm_search_method(ci, cc, calling.recv = TOPN(calling.argc = ci->orig_argc)); + CALL_METHOD(&calling, ci, cc); } /** @@ -983,15 +985,17 @@ opt_send_without_block https://github.com/ruby/ruby/blob/trunk/insns.def#L985 */ DEFINE_INSN invokesuper -(CALL_INFO ci, ISEQ iseq) +(CALL_INFO ci, CALL_CACHE cc, ISEQ blockiseq) (...) (VALUE val) // inc += - (int)(ci->orig_argc + ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0)); { - ci->argc = ci->orig_argc; - vm_caller_setup_arg_block(th, reg_cfp, ci, iseq, TRUE); - ci->recv = GET_SELF(); - vm_search_super_method(th, GET_CFP(), ci); - CALL_METHOD(ci); + struct rb_calling_info calling; + calling.argc = ci->orig_argc; + + vm_caller_setup_arg_block(th, reg_cfp, &calling, ci, blockiseq, TRUE); + calling.recv = GET_SELF(); + vm_search_super_method(th, GET_CFP(), &calling, ci, cc); + CALL_METHOD(&calling, ci, cc); } /** @@ -1005,10 +1009,12 @@ invokeblock https://github.com/ruby/ruby/blob/trunk/insns.def#L1009 (...) (VALUE val) // inc += 1 - ci->orig_argc; { - ci->argc = ci->orig_argc; - ci->blockptr = 0; - ci->recv = GET_SELF(); - val = vm_invoke_block(th, GET_CFP(), ci); + struct rb_calling_info calling; + calling.argc = ci->orig_argc; + calling.blockptr = NULL; + calling.recv = GET_SELF(); + + val = vm_invoke_block(th, GET_CFP(), &calling, ci); if (val == Qundef) { RESTORE_REGS(); NEXT_INSN(); @@ -1260,7 +1266,7 @@ opt_case_dispatch https://github.com/ruby/ruby/blob/trunk/insns.def#L1266 */ DEFINE_INSN opt_plus -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1323,7 +1329,7 @@ opt_plus https://github.com/ruby/ruby/blob/trunk/insns.def#L1329 */ DEFINE_INSN opt_minus -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1371,7 +1377,7 @@ opt_minus https://github.com/ruby/ruby/blob/trunk/insns.def#L1377 */ DEFINE_INSN opt_mult -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1421,7 +1427,7 @@ opt_mult https://github.com/ruby/ruby/blob/trunk/insns.def#L1427 */ DEFINE_INSN opt_div -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1484,7 +1490,7 @@ opt_div https://github.com/ruby/ruby/blob/trunk/insns.def#L1490 */ DEFINE_INSN opt_mod -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1551,11 +1557,11 @@ opt_mod https://github.com/ruby/ruby/blob/trunk/insns.def#L1557 */ DEFINE_INSN opt_eq -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { - val = opt_eq_func(recv, obj, ci); + val = opt_eq_func(recv, obj, ci, cc); if (val == Qundef) { /* other */ @@ -1572,16 +1578,17 @@ opt_eq https://github.com/ruby/ruby/blob/trunk/insns.def#L1578 */ DEFINE_INSN opt_neq -(CALL_INFO ci, CALL_INFO ci_eq) +(CALL_INFO ci, CALL_CACHE cc, CALL_INFO ci_eq, CALL_CACHE cc_eq) (VALUE recv, VALUE obj) (VALUE val) { extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); - vm_search_method(ci, recv); + vm_search_method(ci, cc, recv); + val = Qundef; - if (check_cfunc(ci->me, rb_obj_not_equal)) { - val = opt_eq_func(recv, obj, ci_eq); + if (check_cfunc(cc->me, rb_obj_not_equal)) { + val = opt_eq_func(recv, obj, ci_eq, cc_eq); if (val != Qundef) { val = RTEST(val) ? Qfalse : Qtrue; @@ -1603,7 +1610,7 @@ opt_neq https://github.com/ruby/ruby/blob/trunk/insns.def#L1610 */ DEFINE_INSN opt_lt -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1647,7 +1654,7 @@ opt_lt https://github.com/ruby/ruby/blob/trunk/insns.def#L1654 */ DEFINE_INSN opt_le -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1682,7 +1689,7 @@ opt_le https://github.com/ruby/ruby/blob/trunk/insns.def#L1689 */ DEFINE_INSN opt_gt -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1726,7 +1733,7 @@ opt_gt https://github.com/ruby/ruby/blob/trunk/insns.def#L1733 */ DEFINE_INSN opt_ge -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1760,7 +1767,7 @@ opt_ge https://github.com/ruby/ruby/blob/trunk/insns.def#L1767 */ DEFINE_INSN opt_ltlt -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1792,7 +1799,7 @@ opt_ltlt https://github.com/ruby/ruby/blob/trunk/insns.def#L1799 */ DEFINE_INSN opt_aref -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj) (VALUE val) { @@ -1822,7 +1829,7 @@ opt_aref https://github.com/ruby/ruby/blob/trunk/insns.def#L1829 */ DEFINE_INSN opt_aset -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv, VALUE obj, VALUE set) (VALUE val) { @@ -1855,7 +1862,7 @@ opt_aset https://github.com/ruby/ruby/blob/trunk/insns.def#L1862 */ DEFINE_INSN opt_aset_with -(CALL_INFO ci, VALUE key) +(CALL_INFO ci, CALL_CACHE cc, VALUE key) (VALUE recv, VALUE val) (VALUE val) { @@ -1877,7 +1884,7 @@ opt_aset_with https://github.com/ruby/ruby/blob/trunk/insns.def#L1884 */ DEFINE_INSN opt_aref_with -(CALL_INFO ci, VALUE key) +(CALL_INFO ci, CALL_CACHE cc, VALUE key) (VALUE recv) (VALUE val) { @@ -1898,7 +1905,7 @@ opt_aref_with https://github.com/ruby/ruby/blob/trunk/insns.def#L1905 */ DEFINE_INSN opt_length -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv) (VALUE val) { @@ -1933,7 +1940,7 @@ opt_length https://github.com/ruby/ruby/blob/trunk/insns.def#L1940 */ DEFINE_INSN opt_size -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv) (VALUE val) { @@ -1968,7 +1975,7 @@ opt_size https://github.com/ruby/ruby/blob/trunk/insns.def#L1975 */ DEFINE_INSN opt_empty_p -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv) (VALUE val) { @@ -2006,7 +2013,7 @@ opt_empty_p https://github.com/ruby/ruby/blob/trunk/insns.def#L2013 */ DEFINE_INSN opt_succ -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv) (VALUE val) { @@ -2049,14 +2056,15 @@ opt_succ https://github.com/ruby/ruby/blob/trunk/insns.def#L2056 */ DEFINE_INSN opt_not -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE recv) (VALUE val) { extern VALUE rb_obj_not(VALUE obj); - vm_search_method(ci, recv); - if (check_cfunc(ci->me, rb_obj_not)) { + vm_search_method(ci, cc, recv); + + if (check_cfunc(cc->me, rb_obj_not)) { val = RTEST(recv) ? Qfalse : Qtrue; } else { @@ -2092,7 +2100,7 @@ opt_regexpmatch1 https://github.com/ruby/ruby/blob/trunk/insns.def#L2100 */ DEFINE_INSN opt_regexpmatch2 -(CALL_INFO ci) +(CALL_INFO ci, CALL_CACHE cc) (VALUE obj2, VALUE obj1) (VALUE val) { Index: ChangeLog =================================================================== --- ChangeLog (revision 51902) +++ ChangeLog (revision 51903) @@ -1,3 +1,42 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Sep 20 02:46:34 2015 Koichi Sasada <ko1@a...> + + * vm_core.h: split rb_call_info_t into several structs. + * rb_call_info (ci) has compiled fixed information. + * if ci->flag & VM_CALL_KWARG, then rb_call_info is + also rb_call_info_with_kwarg. This technique reduce one word + for major rb_call_info data. + * rb_calling_info has temporary data (argc, blockptr, recv). + for each method dispatch. This data is allocated only on + machine stack. + * rb_call_cache is for inline method cache. + + Before this patch, only rb_call_info_t data is passed. + After this patch, above three structs are passed. + + This patch improves: + * data locarity (rb_call_info is now read-only data). + * reduce memory consumption (rb_call_info_with_kwarg, + rb_calling_info). + + * compile.c: use above data. + + * insns.def: ditto. + + * iseq.c: ditto. + + * vm_args.c: ditto. + + * vm_eval.c: ditto. + + * vm_insnhelper.c: ditto. + + * vm_insnhelper.h: ditto. + + * iseq.h: add iseq_compile_data::ci_index and + iseq_compile_data::ci_kw_indx. + + * tool/instruction.rb: introduce TS_CALLCACHE operand type. + Sun Sep 20 02:18:10 2015 Tanaka Akira <akr@f...> * test/lib/envutil.rb: mkfifo command based File.mkfifo method Index: vm_core.h =================================================================== --- vm_core.h (revision 51902) +++ vm_core.h (revision 51903) @@ -173,11 +173,6 @@ union iseq_inline_storage_entry { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L173 struct rb_thread_struct; struct rb_control_frame_struct; -typedef struct rb_call_info_kw_arg_struct { - int keyword_len; - VALUE keywords[1]; -} rb_call_info_kw_arg_t; - enum method_missing_reason { MISSING_NOENTRY = 0x00, MISSING_PRIVATE = 0x01, @@ -188,14 +183,30 @@ enum method_missing_reason { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L183 MISSING_NONE = 0x20 }; -/* rb_call_info_t contains calling information including inline cache */ -typedef struct rb_call_info_struct { +struct rb_call_info { /* fixed at compile time */ ID mid; unsigned int flag; int orig_argc; - const rb_call_info_kw_arg_t *kw_arg; +}; + +struct rb_call_info_kw_arg { + int keyword_len; + VALUE keywords[1]; +}; + +struct rb_call_info_with_kwarg { + struct rb_call_info ci; + struct rb_call_info_kw_arg *kw_arg; +}; + +struct rb_calling_info { + struct rb_block_struct *blockptr; + VALUE recv; + int argc; +}; +struct rb_call_cache { /* inline cache: keys */ rb_serial_t method_state; rb_serial_t class_serial; @@ -203,18 +214,14 @@ typedef struct rb_call_info_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L214 /* inline cache: values */ const rb_callable_method_entry_t *me; - /* temporary values for method calling */ - struct rb_block_struct *blockptr; - VALUE recv; - int argc; + VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc); + union { unsigned int index; /* used by ivar */ enum method_missing_reason method_missing_reason; /* used by method_missing */ int inc_sp; /* used by cfunc */ } aux; - - VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci); -} rb_call_info_t; +}; #if 1 #define GetCoreDataFromValue(obj, type, ptr) do { \ @@ -337,12 +344,19 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L344 struct rb_iseq_struct *local_iseq; /* local_iseq->flip_cnt can be modified */ union iseq_inline_storage_entry *is_entries; - rb_call_info_t *callinfo_entries; + struct rb_call_info *ci_entries; /* struct rb_call_info ci_entries[ci_size]; + * struct rb_call_info_with_kwarg cikw_entries[ci_kw_size]; + * So that: + * struct rb_call_info_with_kwarg *cikw_entries = &body->ci_entries[ci_size]; + */ + struct rb_call_cache *cc_entries; /* size is ci_size = ci_kw_size */ + const VALUE mark_ary; /* Array: includes operands which should be GC marked */ unsigned int local_table_size; unsigned int is_size; - unsigned int callinfo_size; + unsigned int ci_size; + unsigned int ci_kw_size; unsigned int line_info_size; }; @@ -632,7 +646,7 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L646 const rb_callable_method_entry_t *passed_bmethod_me; /* for cfunc */ - rb_call_info_t *passed_ci; + struct rb_calling_info *calling; /* for load(true) */ VALUE top_self; @@ -827,14 +841,16 @@ enum vm_check_match_type { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L841 #define VM_CHECKMATCH_TYPE_MASK 0x03 #define VM_CHECKMATCH_ARRAY 0x04 -#define VM_CALL_ARGS_SPLAT (0x01 << 1) /* m(*args) */ -#define VM_CALL_ARGS_BLOCKARG (0x01 << 2) /* m(&block) */ -#define VM_CALL_FCALL (0x01 << 3) /* m(...) */ -#define VM_CALL_VCALL (0x01 << 4) /* m */ -#define VM_CALL_TAILCALL (0x01 << 5) /* located at tail position */ -#define VM_CALL_SUPER (0x01 << 6) /* super */ -#define VM_CALL_OPT_SEND (0x01 << 7) /* internal flag */ -#define VM_CALL_ARGS_SIMPLE (0x01 << 8) /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */ +#define VM_CALL_ARGS_SPLAT (0x01 << 0) /* m(*args) */ +#define VM_CALL_ARGS_BLOCKARG (0x01 << 1) /* m(&block) */ +#define VM_CALL_FCALL (0x01 << 2) /* m(...) */ +#define VM_CALL_VCALL (0x01 << 3) /* m */ +#define VM_CALL_ARGS_SIMPLE (0x01 << 4) /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */ +#define VM_CALL_BLOCKISEQ (0x01 << 5) /* has blockiseq */ +#define VM_CALL_KWARG (0x01 << 6) /* has kwarg */ +#define VM_CALL_TAILCALL (0x01 << 7) /* located at tail position */ +#define VM_CALL_SUPER (0x01 << 8) /* super */ +#define VM_CALL_OPT_SEND (0x01 << 9) /* internal flag */ enum vm_special_object_type { VM_SPECIAL_OBJECT_VMCORE = 1, @@ -878,7 +894,8 @@ enum vm_svar_index { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L894 /* inline cache */ typedef struct iseq_inline_cache_entry *IC; -typedef rb_call_info_t *CALL_INFO; +typedef struct rb_call_info *CALL_INFO; +typedef struct rb_call_cache *CALL_CACHE; void rb_vm_change_state(void); Index: iseq.c =================================================================== --- iseq.c (revision 51902) +++ iseq.c (revision 51903) @@ -74,14 +74,14 @@ rb_iseq_free(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L74 ruby_xfree((void *)iseq->body->local_table); ruby_xfree((void *)iseq->body->is_entries); - if (iseq->body->callinfo_entries) { + if (iseq->body->ci_entries) { unsigned int i; - for (i=0; i<iseq->body->callinfo_size; i++) { - /* TODO: revisit callinfo data structure */ - const rb_call_info_kw_arg_t *kw_arg = iseq->body->callinfo_entries[i].kw_arg; + struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&iseq->body->ci_entries[iseq->body->ci_size]; + for (i=0; i<iseq->body->ci_kw_size; i++) { + const struct rb_call_info_kw_arg *kw_arg = ci_kw_entries[i].kw_arg; ruby_xfree((void *)kw_arg); } - ruby_xfree(iseq->body->callinfo_entries); + ruby_xfree(iseq->body->ci_entries); } ruby_xfree((void *)iseq->body->catch_table); ruby_xfree((void *)iseq->body->param.opt_table); @@ -161,7 +161,7 @@ iseq_memsize(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L161 } if (body) { - rb_call_info_t *ci_entries = body->callinfo_entries; + struct rb_call_info_with_kwarg *ci_kw_entries = (struct rb_call_info_with_kwarg *)&body->ci_entries[body->ci_size]; size += sizeof(struct rb_iseq_constant_body); size += body->iseq_size * sizeof(VALUE); @@ -173,13 +173,14 @@ iseq_memsize(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L173 size += (body->param.opt_num + 1) * sizeof(VALUE); size += param_keyword_size(body->param.keyword); size += body->is_size * sizeof(union iseq_inline_storage_entry); - size += body->callinfo_size * sizeof(rb_call_info_t); + size += body->ci_size * sizeof(struct rb_call_info); + size += body->ci_kw_size * sizeof(struct rb_call_info_with_kwarg); - if (ci_entries) { + if (ci_kw_entries) { unsigned int i; - for (i = 0; i < body->callinfo_size; i++) { - const rb_call_info_kw_arg_t *kw_arg = ci_entries[i].kw_arg; + for (i = 0; i < body->ci_kw_size; i++) { + const struct rb_call_info_kw_arg *kw_arg = ci_kw_entries[i].kw_arg; if (kw_arg) { size += rb_call_info_kw_arg_bytes(kw_arg->keyword_len); @@ -1267,7 +1268,7 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1268 case TS_CALLINFO: { - rb_call_info_t *ci = (rb_call_info_t *)op; + struct rb_call_info *ci = (struct rb_call_info *)op; VALUE ary = rb_ary_new(); if (ci->mid) { @@ -1276,8 +1277,8 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1277 rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc)); - if (ci->kw_arg) { - rb_ary_push(ary, rb_sprintf("kw:%d", ci->kw_arg->keyword_len)); + if (ci->flag & VM_CALL_KWARG) { + rb_ary_push(ary, rb_sprintf("kw:%d", ((struct rb_call_info_with_kwarg *)ci)->kw_arg->keyword_len)); } if (ci->flag) { @@ -1288,6 +1289,7 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1289 if (ci->flag & VM_CALL_VCALL) rb_ary_push(flags, rb_str_new2("VCALL")); if (ci->flag & VM_CALL_TAILCALL) rb_ary_push(flags, rb_str_new2("TAILCALL")); if (ci->flag & VM_CALL_SUPER) rb_ary_push(flags, rb_str_new2("SUPER")); + if (ci->flag & VM_CALL_KWARG) rb_ary_push(flags, rb_str_new2("KWARG")); if (ci->flag & VM_CALL_OPT_SEND) rb_ary_push(flags, rb_str_new2("SNED")); /* maybe not reachable */ if (ci->flag & VM_CALL_ARGS_SIMPLE) rb_ary_push(flags, rb_str_new2("ARGS_SIMPLE")); /* maybe not reachable */ rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|"))); @@ -1296,6 +1298,10 @@ rb_insn_operand_intern(const rb_iseq_t * https://github.com/ruby/ruby/blob/trunk/iseq.c#L1298 } break; + case TS_CALLCACHE: + ret = rb_str_new2("<callcache>"); + break; + case TS_CDHASH: ret = rb_str_new2("<cdhash>"); break; @@ -1883,20 +1889,21 @@ iseq_data_to_ary(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L1889 break; case TS_CALLINFO: { - rb_call_info_t *ci = (rb_call_info_t *)*seq; + 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->kw_arg) { + 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_arg->keyword_len); + VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len); - orig_argc -= ci->kw_arg->keyword_len; - for (i = 0; i < ci->kw_arg->keyword_len; i++) { - rb_ary_push(kw, ci->kw_arg->keywords[i]); + 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); } @@ (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/