diff options
-rw-r--r-- | ChangeLog | 45 | ||||
-rw-r--r-- | class.c | 2 | ||||
-rw-r--r-- | compile.c | 742 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | ext/objspace/objspace.c | 3 | ||||
-rw-r--r-- | gc.c | 60 | ||||
-rw-r--r-- | insns.def | 6 | ||||
-rw-r--r-- | internal.h | 9 | ||||
-rw-r--r-- | iseq.c | 828 | ||||
-rw-r--r-- | iseq.h | 29 | ||||
-rw-r--r-- | load.c | 4 | ||||
-rw-r--r-- | method.h | 4 | ||||
-rw-r--r-- | proc.c | 30 | ||||
-rw-r--r-- | ruby.c | 6 | ||||
-rw-r--r-- | struct.c | 12 | ||||
-rw-r--r-- | thread.c | 2 | ||||
-rw-r--r-- | vm.c | 153 | ||||
-rw-r--r-- | vm_args.c | 68 | ||||
-rw-r--r-- | vm_backtrace.c | 87 | ||||
-rw-r--r-- | vm_core.h | 51 | ||||
-rw-r--r-- | vm_dump.c | 22 | ||||
-rw-r--r-- | vm_eval.c | 20 | ||||
-rw-r--r-- | vm_insnhelper.c | 85 | ||||
-rw-r--r-- | vm_method.c | 17 | ||||
-rw-r--r-- | vm_trace.c | 2 |
25 files changed, 1155 insertions, 1138 deletions
@@ -1,3 +1,48 @@ +Wed Jul 22 07:24:18 2015 Koichi Sasada <ko1@atdot.net> + + * make rb_iseq_t T_IMEMO object (type is imemo_iseq). + + All contents of previous rb_iseq_t is in rb_iseq_t::body. + Remove rb_iseq_t::self because rb_iseq_t is an object. + + RubyVM::InstructionSequence is wrapper object points T_IMEMO/iseq. + So RubyVM::ISeq.of(something) method returns different wrapper + objects but they point the same T_IMEMO/iseq object. + + This patch is big, but most of difference is replacement of + iseq->xxx to iseq->body->xxx. + + (previous) rb_iseq_t::compile_data is also located to + rb_iseq_t::compile_data. + It was moved from rb_iseq_body::compile_data. + + Now rb_iseq_t has empty two pointers. + I will split rb_iseq_body data into static data and dynamic data. + + * compile.c: rename some functions/macros. + Now, we don't need to separate iseq and iseqval (only VALUE). + + * eval.c (ruby_exec_internal): `n' is rb_iseq_t (T_IMEMO/iseq). + + * ext/objspace/objspace.c (count_imemo_objects): count T_IMEMO/iseq. + + * gc.c: check T_IMEMO/iseq. + + * internal.h: add imemo_type::imemo_iseq. + + * iseq.c: define RubyVM::InstructionSequnce as T_OBJECT. + Methods are implemented by functions named iseqw_.... + + * load.c (rb_load_internal0): rb_iseq_new_top() returns + rb_iseq_t (T_IMEMO/iesq). + + * method.h (rb_add_method_iseq): accept rb_iseq_t (T_IMEMO/iseq). + + * vm_core.h (GetISeqPtr): removed because it is not T_DATA now. + + * vm_core.h (struct rb_iseq_body): remove padding for + [Bug #10037][ruby-core:63721]. + Wed Jul 22 07:15:33 2015 Koichi Sasada <ko1@atdot.net> * ext/objspace/objspace.c (total_i): no need to skip singleton classes. @@ -246,7 +246,7 @@ clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t * if (me->def->type == VM_METHOD_TYPE_ISEQ) { rb_cref_t *new_cref; rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref); - rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr->self, new_cref, METHOD_ENTRY_VISI(me)); + rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me)); } else { rb_method_entry_set(new_klass, mid, me, METHOD_ENTRY_VISI(me)); @@ -168,17 +168,14 @@ r_value(VALUE value) /* create new label */ #define NEW_LABEL(l) new_label_body(iseq, (l)) -#define iseq_path(iseq) \ - (((rb_iseq_t*)DATA_PTR(iseq))->location.path) +#define iseq_path(iseq) ((iseq)->body->location.path) +#define iseq_absolute_path(iseq) ((iseq)->body->location.absolute_path) -#define iseq_absolute_path(iseq) \ - (((rb_iseq_t*)DATA_PTR(iseq))->location.absolute_path) - -#define NEW_ISEQVAL(node, name, type, line_no) \ +#define NEW_ISEQ(node, name, type, line_no) \ new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no)) -#define NEW_CHILD_ISEQVAL(node, name, type, line_no) \ - new_child_iseq(iseq, (node), rb_fstring(name), iseq->self, (type), (line_no)) +#define NEW_CHILD_ISEQ(node, name, type, line_no) \ + new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no)) /* add instructions */ #define ADD_SEQ(seq1, seq2) \ @@ -206,31 +203,31 @@ r_value(VALUE value) /* Specific Insn factory */ #define ADD_SEND(seq, line, id, argc) \ - ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(0), NULL) + ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(0), NULL) #define ADD_SEND_WITH_FLAG(seq, line, id, argc, flag) \ - ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)(flag), NULL) + ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)(flag), NULL) #define ADD_SEND_WITH_BLOCK(seq, line, id, argc, block) \ - ADD_SEND_R((seq), (line), (id), (argc), (VALUE)(block), (VALUE)INT2FIX(0), NULL) + ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(0), NULL) #define ADD_CALL_RECEIVER(seq, line) \ ADD_INSN((seq), (line), putself) #define ADD_CALL(seq, line, id, argc) \ - ADD_SEND_R((seq), (line), (id), (argc), (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL), NULL) + ADD_SEND_R((seq), (line), (id), (argc), NULL, (VALUE)INT2FIX(VM_CALL_FCALL), NULL) #define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \ ADD_SEND_R((seq), (line), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL) #define ADD_SEND_R(seq, line, id, argc, block, flag, keywords) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (VALUE)(block), (VALUE)(flag), (keywords))) + ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) #define ADD_TRACE(seq, line, event) \ do { \ - if ((event) == RUBY_EVENT_LINE && iseq->coverage && \ + if ((event) == RUBY_EVENT_LINE && iseq->body->coverage && \ (line) != iseq->compile_data->last_coverable_line) { \ - RARRAY_ASET(iseq->coverage, (line) - 1, INT2FIX(0)); \ + RARRAY_ASET(iseq->body->coverage, (line) - 1, INT2FIX(0)); \ iseq->compile_data->last_coverable_line = (line); \ ADD_INSN1((seq), (line), trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ } \ @@ -252,11 +249,12 @@ r_value(VALUE value) #define ADD_ADJUST_RESTORE(seq, label) \ ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1)) -#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \ - (rb_ary_push(iseq->compile_data->catch_table_ary, \ - rb_ary_new3(5, (type), \ - (VALUE)(ls) | 1, (VALUE)(le) | 1, \ - (VALUE)(iseqv), (VALUE)(lc) | 1))) +#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) do { \ + VALUE _e = rb_ary_new3(5, (type), \ + (VALUE)(ls) | 1, (VALUE)(le) | 1, \ + (VALUE)(iseqv), (VALUE)(lc) | 1); \ + rb_ary_push(iseq->compile_data->catch_table_ary, freeze_hide_obj(_e)); \ +} while (0) /* compile node */ #define COMPILE(anchor, desc, node) \ @@ -292,7 +290,7 @@ r_value(VALUE value) if (compile_debug) rb_compile_bug strs; \ th->errinfo = iseq->compile_data->err_info; \ rb_compile_error strs; \ - RB_OBJ_WRITE(iseq->self, &iseq->compile_data->err_info, th->errinfo); \ + RB_OBJ_WRITE(iseq, &iseq->compile_data->err_info, th->errinfo); \ th->errinfo = tmp; \ ret = 0; \ break; \ @@ -312,7 +310,13 @@ r_value(VALUE value) #define INIT_ANCHOR(name) \ (name##_body__.last = &name##_body__.anchor, name = &name##_body__) -#define hide_obj(obj) do {OBJ_FREEZE(obj); RBASIC_CLEAR_CLASS(obj);} while (0) +static inline VALUE +freeze_hide_obj(VALUE obj) +{ + OBJ_FREEZE(obj); + RBASIC_CLEAR_CLASS(obj); + return obj; +} #include "optinsn.inc" #if OPT_INSTRUCTIONS_UNIFICATION @@ -430,7 +434,7 @@ iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v) return COMPILE_OK; } -#define ruby_sourcefile RSTRING_PTR(iseq->location.path) +#define ruby_sourcefile RSTRING_PTR(iseq->body->location.path) static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) @@ -468,12 +472,10 @@ validate_labels(rb_iseq_t *iseq, st_table *labels_table) } VALUE -rb_iseq_compile_node(VALUE self, NODE *node) +rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node) { DECL_ANCHOR(ret); - rb_iseq_t *iseq; INIT_ANCHOR(ret); - GetISeqPtr(self, iseq); if (node == 0) { COMPILE(ret, "nil", node); @@ -484,13 +486,13 @@ rb_iseq_compile_node(VALUE self, NODE *node) iseq_set_local_table(iseq, node->nd_tbl); iseq_set_arguments(iseq, ret, node->nd_args); - switch (iseq->type) { + switch (iseq->body->type) { case ISEQ_TYPE_BLOCK: { LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0); LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0); - ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_B_CALL); + ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_B_CALL); ADD_LABEL(ret, start); COMPILE(ret, "block body", node->nd_body); ADD_LABEL(ret, end); @@ -503,14 +505,14 @@ rb_iseq_compile_node(VALUE self, NODE *node) } case ISEQ_TYPE_CLASS: { - ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS); + ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CLASS); COMPILE(ret, "scoped node", node->nd_body); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); break; } case ISEQ_TYPE_METHOD: { - ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL); + ADD_TRACE(ret, FIX2INT(iseq->body->location.first_lineno), RUBY_EVENT_CALL); COMPILE(ret, "scoped node", node->nd_body); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); break; @@ -527,7 +529,7 @@ rb_iseq_compile_node(VALUE self, NODE *node) (*ifunc->func)(iseq, ret, ifunc->data); } else { - switch (iseq->type) { + switch (iseq->body->type) { case ISEQ_TYPE_METHOD: case ISEQ_TYPE_CLASS: case ISEQ_TYPE_BLOCK: @@ -554,7 +556,7 @@ rb_iseq_compile_node(VALUE self, NODE *node) } } - if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) { + if (iseq->body->type == ISEQ_TYPE_RESCUE || iseq->body->type == ISEQ_TYPE_ENSURE) { ADD_INSN2(ret, 0, getlocal, INT2FIX(2), INT2FIX(0)); ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ ); } @@ -577,10 +579,10 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) const void * const *table = rb_vm_get_insns_address_table(); unsigned int i; - for (i = 0; i < iseq->iseq_size; /* */ ) { - int insn = (int)iseq->iseq_encoded[i]; + for (i = 0; i < iseq->body->iseq_size; /* */ ) { + int insn = (int)iseq->body->iseq_encoded[i]; int len = insn_len(insn); - iseq->iseq_encoded[i] = (VALUE)table[insn]; + iseq->body->iseq_encoded[i] = (VALUE)table[insn]; i += len; } #endif @@ -604,28 +606,28 @@ rb_vm_insn_addr2insn(const void *addr) /* cold path */ #endif VALUE * -rb_iseq_original_iseq(rb_iseq_t *iseq) /* cold path */ +rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */ { - if (iseq->iseq) return iseq->iseq; + if (iseq->body->iseq) return iseq->body->iseq; - iseq->iseq = ALLOC_N(VALUE, iseq->iseq_size); + iseq->body->iseq = ALLOC_N(VALUE, iseq->body->iseq_size); - MEMCPY(iseq->iseq, iseq->iseq_encoded, VALUE, iseq->iseq_size); + MEMCPY(iseq->body->iseq, iseq->body->iseq_encoded, VALUE, iseq->body->iseq_size); #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE { unsigned int i; - for (i = 0; i < iseq->iseq_size; /* */ ) { - const void *addr = (const void *)iseq->iseq[i]; + for (i = 0; i < iseq->body->iseq_size; /* */ ) { + const void *addr = (const void *)iseq->body->iseq[i]; const int insn = rb_vm_insn_addr2insn(addr); - iseq->iseq[i] = insn; + iseq->body->iseq[i] = insn; i += insn_len(insn); } } #endif - return iseq->iseq; + return iseq->body->iseq; } /*********************************************/ @@ -942,7 +944,7 @@ new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int a } static rb_call_info_t * -new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned int flag, rb_call_info_kw_arg_t *kw_arg) +new_callinfo(rb_iseq_t *iseq, ID mid, int argc, const rb_iseq_t *blockiseq, unsigned int flag, rb_call_info_kw_arg_t *kw_arg) { rb_call_info_t *ci = (rb_call_info_t *)compile_data_alloc(iseq, sizeof(rb_call_info_t)); @@ -957,12 +959,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned int flag, ci->orig_argc += kw_arg->keyword_len; } - if (block) { - GetISeqPtr(block, ci->blockiseq); - } - else { - ci->blockiseq = 0; - } + ci->blockiseq = blockiseq; if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG)) && ci->blockiseq == NULL && ci->kw_arg == NULL) { @@ -975,32 +972,32 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned int flag, ci->recv = Qundef; ci->call = 0; /* TODO: should set default function? */ - ci->aux.index = iseq->callinfo_size++; + ci->aux.index = iseq->body->callinfo_size++; return ci; } static INSN * -new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, VALUE block, VALUE flag, rb_call_info_kw_arg_t *keywords) +new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *block, VALUE flag, rb_call_info_kw_arg_t *keywords) { VALUE *operands = (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 1); operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), block, FIX2INT(flag), keywords); return new_insn_core(iseq, line_no, BIN(send), 1, operands); } -static VALUE +static rb_iseq_t * new_child_iseq(rb_iseq_t *iseq, NODE *node, - VALUE name, VALUE parent, enum iseq_type type, int line_no) + VALUE name, const rb_iseq_t *parent, enum iseq_type type, int line_no) { - VALUE ret; + rb_iseq_t *ret_iseq; debugs("[new_child_iseq]> ---------------------------------------\n"); - ret = rb_iseq_new_with_opt(node, name, - iseq_path(iseq->self), iseq_absolute_path(iseq->self), - INT2FIX(line_no), parent, type, iseq->compile_data->option); + ret_iseq = rb_iseq_new_with_opt(node, name, + iseq_path(iseq), iseq_absolute_path(iseq), + INT2FIX(line_no), parent, type, iseq->compile_data->option); debugs("[new_child_iseq]< ---------------------------------------\n"); - iseq_add_mark_object(iseq, ret); - return ret; + iseq_add_mark_object(iseq, (VALUE)ret_iseq); + return ret_iseq; } static int @@ -1046,7 +1043,7 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor) rb_iseq_translate_threaded_code(iseq); if (compile_debug > 1) { - VALUE str = rb_iseq_disasm(iseq->self); + VALUE str = rb_iseq_disasm(iseq); printf("%s\n", StringValueCStr(str)); } debugs("[compile step: finish]\n"); @@ -1060,10 +1057,10 @@ iseq_set_exception_local_table(rb_iseq_t *iseq) ID id_dollar_bang; CONST_ID(id_dollar_bang, "#$!"); - iseq->local_table = (ID *)ALLOC_N(ID, 1); - iseq->local_table_size = 1; - iseq->local_size = iseq->local_table_size + 1; - iseq->local_table[0] = id_dollar_bang; + iseq->body->local_table = (ID *)ALLOC_N(ID, 1); + iseq->body->local_table_size = 1; + iseq->body->local_size = iseq->body->local_table_size + 1; + iseq->body->local_table[0] = id_dollar_bang; return COMPILE_OK; } @@ -1071,9 +1068,9 @@ static int get_lvar_level(const rb_iseq_t *iseq) { int lev = 0; - while (iseq != iseq->local_iseq) { + while (iseq != iseq->body->local_iseq) { lev++; - iseq = iseq->parent_iseq; + iseq = iseq->body->parent_iseq; } return lev; } @@ -1083,8 +1080,8 @@ get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id) { int i; - for (i = 0; i < iseq->local_table_size; i++) { - if (iseq->local_table[i] == id) { + for (i = 0; i < iseq->body->local_table_size; i++) { + if (iseq->body->local_table[i] == id) { return i; } } @@ -1094,7 +1091,7 @@ get_dyna_var_idx_at_raw(const rb_iseq_t *iseq, ID id) static int get_local_var_idx(const rb_iseq_t *iseq, ID id) { - int idx = get_dyna_var_idx_at_raw(iseq->local_iseq, id); + int idx = get_dyna_var_idx_at_raw(iseq->body->local_iseq, id); if (idx < 0) { rb_bug("get_local_var_idx: %d", idx); @@ -1113,7 +1110,7 @@ get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls) if (idx >= 0) { break; } - iseq = iseq->parent_iseq; + iseq = iseq->body->parent_iseq; lv++; } @@ -1122,44 +1119,44 @@ get_dyna_var_idx(const rb_iseq_t *iseq, ID id, int *level, int *ls) } *level = lv; - *ls = iseq->local_size; + *ls = iseq->body->local_size; return idx; } static void iseq_calc_param_size(rb_iseq_t *iseq) { - if (iseq->param.flags.has_opt || - iseq->param.flags.has_post || - iseq->param.flags.has_rest || - iseq->param.flags.has_block || - iseq->param.flags.has_kw || - iseq->param.flags.has_kwrest) { + if (iseq->body->param.flags.has_opt || + iseq->body->param.flags.has_post || + iseq->body->param.flags.has_rest || + iseq->body->param.flags.has_block || + iseq->body->param.flags.has_kw || + iseq->body->param.flags.has_kwrest) { - if (iseq->param.flags.has_block) { - iseq->param.size = iseq->param.block_start + 1; + if (iseq->body->param.flags.has_block) { + iseq->body->param.size = iseq->body->param.block_start + 1; } - else if (iseq->param.flags.has_kwrest) { - iseq->param.size = iseq->param.keyword->rest_start + 1; + else if (iseq->body->param.flags.has_kwrest) { + iseq->body->param.size = iseq->body->param.keyword->rest_start + 1; } - else if (iseq->param.flags.has_kw) { - iseq->param.size = iseq->param.keyword->bits_start + 1; + else if (iseq->body->param.flags.has_kw) { + iseq->body->param.size = iseq->body->param.keyword->bits_start + 1; } - else if (iseq->param.flags.has_post) { - iseq->param.size = iseq->param.post_start + iseq->param.post_num; + else if (iseq->body->param.flags.has_post) { + iseq->body->param.size = iseq->body->param.post_start + iseq->body->param.post_num; } - else if (iseq->param.flags.has_rest) { - iseq->param.size = iseq->param.rest_start + 1; + else if (iseq->body->param.flags.has_rest) { + iseq->body->param.size = iseq->body->param.rest_start + 1; } - else if (iseq->param.flags.has_opt) { - iseq->param.size = iseq->param.lead_num + iseq->param.opt_num; + else if (iseq->body->param.flags.has_opt) { + iseq->body->param.size = iseq->body->param.lead_num + iseq->body->param.opt_num; } else { rb_bug("unreachable"); } } else { - iseq->param.size = iseq->param.lead_num; + iseq->body->param.size = iseq->body->param.lead_num; } } @@ -1180,9 +1177,9 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) } - iseq->param.lead_num = (int)args->pre_args_num; - if (iseq->param.lead_num > 0) iseq->param.flags.has_lead = TRUE; - debugs(" - argc: %d\n", iseq->param.lead_num); + iseq->body->param.lead_num = (int)args->pre_args_num; + if (iseq->body->param.lead_num > 0) iseq->body->param.flags.has_lead = TRUE; + debugs(" - argc: %d\n", iseq->body->param.lead_num); rest_id = args->rest_arg; if (rest_id == 1) { @@ -1192,9 +1189,9 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) block_id = args->block_arg; if (args->first_post_arg) { - iseq->param.post_start = get_dyna_var_idx_at_raw(iseq, args->first_post_arg); - iseq->param.post_num = args->post_args_num; - iseq->param.flags.has_post = TRUE; + iseq->body->param.post_start = get_dyna_var_idx_at_raw(iseq, args->first_post_arg); + iseq->body->param.post_num = args->post_args_num; + iseq->body->param.flags.has_post = TRUE; } if (args->opt_args) { @@ -1217,15 +1214,15 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) rb_ary_push(labels, (VALUE)label | 1); ADD_LABEL(optargs, label); - iseq->param.opt_num = i; - iseq->param.opt_table = ALLOC_N(VALUE, i+1); - MEMCPY(iseq->param.opt_table, RARRAY_CONST_PTR(labels), VALUE, i+1); + iseq->body->param.opt_num = i; + iseq->body->param.opt_table = ALLOC_N(VALUE, i+1); + MEMCPY(iseq->body->param.opt_table, RARRAY_CONST_PTR(labels), VALUE, i+1); for (j = 0; j < i+1; j++) { - iseq->param.opt_table[j] &= ~1; + iseq->body->param.opt_table[j] &= ~1; } rb_ary_clear(labels); - iseq->param.flags.has_opt = TRUE; + iseq->body->param.flags.has_opt = TRUE; } if (args->kw_args) { @@ -1234,9 +1231,9 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) const VALUE complex_mark = rb_str_tmp_new(0); int kw = 0, rkw = 0, di = 0, i; - iseq->param.flags.has_kw = TRUE; - iseq->param.keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); - iseq->param.keyword->bits_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); + iseq->body->param.flags.has_kw = TRUE; + iseq->body->param.keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); + iseq->body->param.keyword->bits_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); while (node) { NODE *val_node = node->nd_body->nd_value; @@ -1265,7 +1262,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) dv = complex_mark; } - iseq->param.keyword->num = ++di; + iseq->body->param.keyword->num = ++di; rb_ary_push(default_values, dv); } @@ -1273,26 +1270,26 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) node = node->nd_next; } - iseq->param.keyword->num = kw; + iseq->body->param.keyword->num = kw; if (args->kw_rest_arg->nd_cflag != 0) { - iseq->param.keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_cflag); - iseq->param.flags.has_kwrest = TRUE; + iseq->body->param.keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_cflag); + iseq->body->param.flags.has_kwrest = TRUE; } - iseq->param.keyword->required_num = rkw; - iseq->param.keyword->table = &iseq->local_table[iseq->param.keyword->bits_start - iseq->param.keyword->num]; - iseq->param.keyword->default_values = ALLOC_N(VALUE, RARRAY_LEN(default_values)); + iseq->body->param.keyword->required_num = rkw; + iseq->body->param.keyword->table = &iseq->body->local_table[iseq->body->param.keyword->bits_start - iseq->body->param.keyword->num]; + iseq->body->param.keyword->default_values = ALLOC_N(VALUE, RARRAY_LEN(default_values)); for (i = 0; i < RARRAY_LEN(default_values); i++) { VALUE dv = RARRAY_AREF(default_values, i); if (dv == complex_mark) dv = Qundef; - iseq->param.keyword->default_values[i] = dv; + iseq->body->param.keyword->default_values[i] = dv; } } else if (args->kw_rest_arg) { - iseq->param.flags.has_kwrest = TRUE; - iseq->param.keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); - iseq->param.keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); + iseq->body->param.flags.has_kwrest = TRUE; + iseq->body->param.keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); + iseq->body->param.keyword->rest_start = get_dyna_var_idx_at_raw(iseq, args->kw_rest_arg->nd_vid); } if (args->pre_init) { /* m_init */ @@ -1303,32 +1300,32 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) } if (rest_id) { - iseq->param.rest_start = get_dyna_var_idx_at_raw(iseq, rest_id); - iseq->param.flags.has_rest = TRUE; - assert(iseq->param.rest_start != -1); + iseq->body->param.rest_start = get_dyna_var_idx_at_raw(iseq, rest_id); + iseq->body->param.flags.has_rest = TRUE; + assert(iseq->body->param.rest_start != -1); - if (iseq->param.post_start == 0) { /* TODO: why that? */ - iseq->param.post_start = iseq->param.rest_start + 1; + if (iseq->body->param.post_start == 0) { /* TODO: why that? */ + iseq->body->param.post_start = iseq->body->param.rest_start + 1; } } if (block_id) { - iseq->param.block_start = get_dyna_var_idx_at_raw(iseq, block_id); - iseq->param.flags.has_block = TRUE; + iseq->body->param.block_start = get_dyna_var_idx_at_raw(iseq, block_id); + iseq->body->param.flags.has_block = TRUE; } iseq_calc_param_size(iseq); - if (iseq->type == ISEQ_TYPE_BLOCK) { - if (iseq->param.flags.has_opt == FALSE && - iseq->param.flags.has_post == FALSE && - iseq->param.flags.has_rest == FALSE && - iseq->param.flags.has_kw == FALSE && - iseq->param.flags.has_kwrest == FALSE) { + if (iseq->body->type == ISEQ_TYPE_BLOCK) { + if (iseq->body->param.flags.has_opt == FALSE && + iseq->body->param.flags.has_post == FALSE && + iseq->body->param.flags.has_rest == FALSE && + iseq->body->param.flags.has_kw == FALSE && + iseq->body->param.flags.has_kwrest == FALSE) { - if (iseq->param.lead_num == 1 && last_comma == 0) { + if (iseq->body->param.lead_num == 1 && last_comma == 0) { /* {|a|} */ - iseq->param.flags.ambiguous_param0 = TRUE; + iseq->body->param.flags.ambiguous_param0 = TRUE; } } } @@ -1351,12 +1348,12 @@ iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl) } if (size > 0) { - iseq->local_table = (ID *)ALLOC_N(ID, size); - MEMCPY(iseq->local_table, tbl, ID, size); + iseq->body->local_table = (ID *)ALLOC_N(ID, size); + MEMCPY(iseq->body->local_table, tbl, ID, size); } - iseq->local_size = iseq->local_table_size = size; - iseq->local_size += 1; + iseq->body->local_size = iseq->body->local_table_size = size; + iseq->body->local_size += 1; /* if (lfp == dfp ) { // top, class, method dfp[-1]: svar @@ -1365,7 +1362,7 @@ iseq_set_local_table(rb_iseq_t *iseq, const ID *tbl) } */ - debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size); + debugs("iseq_set_local_table: %d, %d\n", iseq->body->local_size, iseq->body->local_table_size); return COMPILE_OK; } @@ -1468,7 +1465,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) default: dump_disasm_list(FIRST_ELEMENT(anchor)); dump_disasm_list(list); - rb_compile_error(RSTRING_PTR(iseq->location.path), line, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), line, "error: set_sequence"); break; } @@ -1478,9 +1475,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) /* make instruction sequence */ generated_iseq = ALLOC_N(VALUE, pos); line_info_table = ALLOC_N(struct iseq_line_info_entry, k); - iseq->is_entries = ZALLOC_N(union iseq_inline_storage_entry, iseq->is_size); - iseq->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->callinfo_size); - /* MEMZERO(iseq->callinfo_entries, rb_call_info_t, iseq->callinfo_size); */ + iseq->body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, iseq->body->is_size); + iseq->body->callinfo_entries = ALLOC_N(rb_call_info_t, iseq->body->callinfo_size); + /* MEMZERO(iseq->body->callinfo_entries, rb_call_info_t, iseq->body->callinfo_size); */ list = FIRST_ELEMENT(anchor); k = pos = sp = 0; @@ -1512,7 +1509,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) if (iobj->operand_size != len - 1) { /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */ dump_disasm_list(list); - rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), iobj->line_no, "operand size miss! (%d for %d)", iobj->operand_size, len - 1); xfree(generated_iseq); @@ -1529,7 +1526,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) /* label(destination position) */ lobj = (LABEL *)operands[j]; if (!lobj->set) { - rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), iobj->line_no, "unknown label"); } if (lobj->sp == -1) { @@ -1547,7 +1544,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) data.len = len; rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data); - hide_obj(map); + freeze_hide_obj(map); generated_iseq[pos + 1 + j] = map; break; } @@ -1558,11 +1555,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) case TS_ISEQ: /* iseq */ { VALUE v = operands[j]; - rb_iseq_t *block = 0; - if (v) { - GetISeqPtr(v, block); - } - generated_iseq[pos + 1 + j] = (VALUE)block; + generated_iseq[pos + 1 + j] = v; break; } case TS_VALUE: /* VALUE */ @@ -1576,9 +1569,9 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) case TS_IC: /* inline cache */ { int ic_index = FIX2INT(operands[j]); - IC ic = (IC)&iseq->is_entries[ic_index]; - if (UNLIKELY(ic_index >= iseq->is_size)) { - rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->is_size); + IC ic = (IC)&iseq->body->is_entries[ic_index]; + if (UNLIKELY(ic_index >= iseq->body->is_size)) { + rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", ic_index, iseq->body->is_size); } generated_iseq[pos + 1 + j] = (VALUE)ic; break; @@ -1586,11 +1579,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) case TS_CALLINFO: /* call info */ { rb_call_info_t *base_ci = (rb_call_info_t *)operands[j]; - rb_call_info_t *ci = &iseq->callinfo_entries[base_ci->aux.index]; + rb_call_info_t *ci = &iseq->body->callinfo_entries[base_ci->aux.index]; *ci = *base_ci; - if (UNLIKELY(base_ci->aux.index >= iseq->callinfo_size)) { - rb_bug("iseq_set_sequence: ci_index overflow: index: %d, size: %d", base_ci->argc, iseq->callinfo_size); + if (UNLIKELY(base_ci->aux.index >= iseq->body->callinfo_size)) { + rb_bug("iseq_set_sequence: ci_index overflow: index: %d, size: %d", base_ci->argc, iseq->body->callinfo_size); } generated_iseq[pos + 1 + j] = (VALUE)ci; break; @@ -1609,7 +1602,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) generated_iseq[pos + 1 + j] = operands[j]; break; default: - rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), iobj->line_no, "unknown operand type: %c", type); xfree(generated_iseq); xfree(line_info_table); @@ -1680,13 +1673,13 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor) list = list->next; } - iseq->iseq_encoded = (void *)generated_iseq; - iseq->iseq_size = pos; - iseq->stack_max = stack_max; + iseq->body->iseq_encoded = (void *)generated_iseq; + iseq->body->iseq_size = pos; + iseq->body->stack_max = stack_max; REALLOC_N(line_info_table, struct iseq_line_info_entry, k); - iseq->line_info_table = line_info_table; - iseq->line_info_size = k; + iseq->body->line_info_table = line_info_table; + iseq->body->line_info_size = k; return COMPILE_OK; } @@ -1713,23 +1706,23 @@ iseq_set_exception_table(rb_iseq_t *iseq) tlen = (int)RARRAY_LEN(iseq->compile_data->catch_table_ary); tptr = RARRAY_CONST_PTR(iseq->compile_data->catch_table_ary); - iseq->catch_table = 0; + iseq->body->catch_table = 0; if (tlen > 0) { - iseq->catch_table = xmalloc(iseq_catch_table_bytes(tlen)); - iseq->catch_table->size = tlen; + iseq->body->catch_table = xmalloc(iseq_catch_table_bytes(tlen)); + iseq->body->catch_table->size = tlen; } - if (iseq->catch_table) for (i = 0; i < iseq->catch_table->size; i++) { + if (iseq->body->catch_table) for (i = 0; i < iseq->body->catch_table->size; i++) { ptr = RARRAY_CONST_PTR(tptr[i]); - entry = &iseq->catch_table->entries[i]; + entry = &iseq->body->catch_table->entries[i]; entry->type = (enum catch_type)(ptr[0] & 0xffff); entry->start = label_get_position((LABEL *)(ptr[1] & ~1)); entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); - entry->iseq = ptr[3]; + entry->iseq = (rb_iseq_t *)ptr[3]; /* register iseq as mark object */ if (entry->iseq != 0) { - iseq_add_mark_object(iseq, entry->iseq); + iseq_add_mark_object(iseq, (VALUE)entry->iseq); } /* stack depth */ @@ -1750,7 +1743,7 @@ iseq_set_exception_table(rb_iseq_t *iseq) } } - RB_OBJ_WRITE(iseq->self, &iseq->compile_data->catch_table_ary, 0); /* free */ + RB_OBJ_WRITE(iseq, &iseq->compile_data->catch_table_ary, 0); /* free */ return COMPILE_OK; } @@ -1768,9 +1761,9 @@ iseq_set_optargs_table(rb_iseq_t *iseq) { int i; - if (iseq->param.flags.has_opt) { - for (i = 0; i < iseq->param.opt_num + 1; i++) { - iseq->param.opt_table[i] = label_get_position((LABEL *)iseq->param.opt_table[i]); + if (iseq->body->param.flags.has_opt) { + for (i = 0; i < iseq->body->param.opt_num + 1; i++) { + iseq->body->param.opt_table[i] = label_get_position((LABEL *)iseq->body->param.opt_table[i]); } } return COMPILE_OK; @@ -2156,7 +2149,7 @@ insn_set_sc_state(rb_iseq_t *iseq, INSN *iobj, int state) dump_disasm_list((LINK_ELEMENT *)iobj); dump_disasm_list((LINK_ELEMENT *)lobj); printf("\n-- %d, %d\n", lobj->sc_state, nstate); - rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), iobj->line_no, "insn_set_sc_state error\n"); return 0; } @@ -2258,7 +2251,7 @@ iseq_set_sequence_stackcaching(rb_iseq_t *iseq, LINK_ANCHOR *anchor) case SCS_XX: goto normal_insn; default: - rb_compile_error(RSTRING_PTR(iseq->location.path), iobj->line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), iobj->line_no, "unreachable"); } /* remove useless pop */ @@ -2632,7 +2625,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int onl } else { if (rb_hash_lookup(literals, lit) != Qnil) { - rb_compile_warning(RSTRING_PTR(iseq->location.path), nd_line(val), "duplicated when clause is ignored"); + rb_compile_warning(RSTRING_PTR(iseq->body->location.path), nd_line(val), "duplicated when clause is ignored"); } else { rb_hash_aset(literals, lit, (VALUE)(l1) | 1); @@ -3111,11 +3104,11 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, int line = nd_line(node); LABEL *lstart = NEW_LABEL(line); LABEL *lend = NEW_LABEL(line); - VALUE rescue = NEW_CHILD_ISEQVAL(NEW_NIL(), - rb_str_concat(rb_str_new2 - ("defined guard in "), - iseq->location.label), - ISEQ_TYPE_DEFINED_GUARD, 0); + const rb_iseq_t *rescue = NEW_CHILD_ISEQ(NEW_NIL(), + rb_str_concat(rb_str_new2 + ("defined guard in "), + iseq->body->location.label), + ISEQ_TYPE_DEFINED_GUARD, 0); APPEND_LABEL(ret, lcur, lstart); ADD_LABEL(ret, lend); ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]); @@ -3124,25 +3117,25 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret, } static VALUE -make_name_for_block(const rb_iseq_t *iseq) +make_name_for_block(const rb_iseq_t *orig_iseq) { int level = 1; - const rb_iseq_t *ip = iseq; + const rb_iseq_t *iseq = orig_iseq; - if (iseq->parent_iseq != 0) { - while (ip->local_iseq != ip) { - if (ip->type == ISEQ_TYPE_BLOCK) { + if (orig_iseq->body->parent_iseq != 0) { + while (orig_iseq->body->local_iseq != iseq) { + if (iseq->body->type == ISEQ_TYPE_BLOCK) { level++; } - ip = ip->parent_iseq; + iseq = iseq->body->parent_iseq; } } if (level == 1) { - return rb_sprintf("block in %"PRIsVALUE, ip->location.label); + return rb_sprintf("block in %"PRIsVALUE, iseq->body->location.label); } else { - return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, ip->location.label); + return rb_sprintf("block (%d levels) in %"PRIsVALUE, level, iseq->body->location.label); } } @@ -3296,7 +3289,8 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *body) { int line = nd_line(body); VALUE argc = INT2FIX(0); - VALUE block = NEW_CHILD_ISEQVAL(body, make_name_for_block(iseq->parent_iseq), ISEQ_TYPE_BLOCK, line); + const rb_iseq_t *block = NEW_CHILD_ISEQ(body, make_name_for_block(iseq->body->parent_iseq), ISEQ_TYPE_BLOCK, line); + ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_CALL_WITH_BLOCK(ret, line, id_core_set_postexe, argc, block); iseq_set_local_table(iseq, 0); @@ -3653,7 +3647,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_ITER:{ - VALUE prevblock = iseq->compile_data->current_block; + const rb_iseq_t *prevblock = iseq->compile_data->current_block; LABEL *retry_label = NEW_LABEL(line); LABEL *retry_end_l = NEW_LABEL(line); @@ -3661,16 +3655,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (nd_type(node) == NODE_FOR) { COMPILE(ret, "iter caller (for)", node->nd_iter); - iseq->compile_data->current_block = - NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), - ISEQ_TYPE_BLOCK, line); - + iseq->compile_data->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), + ISEQ_TYPE_BLOCK, line); ADD_SEND_WITH_BLOCK(ret, line, idEach, INT2FIX(0), iseq->compile_data->current_block); } else { - iseq->compile_data->current_block = - NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), - ISEQ_TYPE_BLOCK, line); + iseq->compile_data->current_block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), + ISEQ_TYPE_BLOCK, line); COMPILE(ret, "iter caller", node->nd_iter); } ADD_LABEL(ret, retry_end_l); @@ -3702,7 +3693,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, line, putnil); } } - else if (iseq->type == ISEQ_TYPE_BLOCK) { + else if (iseq->body->type == ISEQ_TYPE_BLOCK) { break_by_insn: /* escape from block */ COMPILE(ret, "break val (block)", node->nd_stts); @@ -3711,12 +3702,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, line, pop); } } - else if (iseq->type == ISEQ_TYPE_EVAL) { + else if (iseq->body->type == ISEQ_TYPE_EVAL) { break_in_eval: COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with break")); } else { - const rb_iseq_t *ip = iseq->parent_iseq; + const rb_iseq_t *ip = iseq->body->parent_iseq; + while (ip) { if (!ip->compile_data) { ip = 0; @@ -3728,15 +3720,15 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) level = VM_THROW_NO_ESCAPE_FLAG; goto break_by_insn; } - else if (ip->type == ISEQ_TYPE_BLOCK) { + else if (ip->body->type == ISEQ_TYPE_BLOCK) { level <<= VM_THROW_LEVEL_SHIFT; goto break_by_insn; } - else if (ip->type == ISEQ_TYPE_EVAL) { + else if (ip->body->type == ISEQ_TYPE_EVAL) { goto break_in_eval; } - ip = ip->parent_iseq; + ip = ip->body->parent_iseq; } COMPILE_ERROR((ERROR_ARGS "Invalid break")); } @@ -3772,7 +3764,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, line, putnil); } } - else if (iseq->type == ISEQ_TYPE_EVAL) { + else if (iseq->body->type == ISEQ_TYPE_EVAL) { next_in_eval: COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with next")); } @@ -3790,14 +3782,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) /* while loop */ break; } - else if (ip->type == ISEQ_TYPE_BLOCK) { + else if (ip->body->type == ISEQ_TYPE_BLOCK) { break; } - else if (ip->type == ISEQ_TYPE_EVAL) { + else if (ip->body->type == ISEQ_TYPE_EVAL) { goto next_in_eval; } - ip = ip->parent_iseq; + ip = ip->body->parent_iseq; } if (ip != 0) { COMPILE(ret, "next val", node->nd_stts); @@ -3826,7 +3818,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, line, putnil); } } - else if (iseq->type == ISEQ_TYPE_EVAL) { + else if (iseq->body->type == ISEQ_TYPE_EVAL) { redo_in_eval: COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); } @@ -3857,14 +3849,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (ip->compile_data->redo_label != 0) { break; } - else if (ip->type == ISEQ_TYPE_BLOCK) { + else if (ip->body->type == ISEQ_TYPE_BLOCK) { break; } - else if (ip->type == ISEQ_TYPE_EVAL) { + else if (ip->body->type == ISEQ_TYPE_EVAL) { goto redo_in_eval; } - ip = ip->parent_iseq; + ip = ip->body->parent_iseq; } if (ip != 0) { ADD_INSN(ret, line, putnil); @@ -3881,7 +3873,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_RETRY:{ - if (iseq->type == ISEQ_TYPE_RESCUE) { + if (iseq->body->type == ISEQ_TYPE_RESCUE) { ADD_INSN(ret, line, putnil); ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETRY)); @@ -3902,10 +3894,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *lstart = NEW_LABEL(line); LABEL *lend = NEW_LABEL(line); LABEL *lcont = NEW_LABEL(line); - VALUE rescue = NEW_CHILD_ISEQVAL( - node->nd_resq, - rb_str_concat(rb_str_new2("rescue in "), iseq->location.label), - ISEQ_TYPE_RESCUE, line); + const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq, + rb_str_concat(rb_str_new2("rescue in "), iseq->body->location.label), + ISEQ_TYPE_RESCUE, line); ADD_LABEL(ret, lstart); COMPILE(ret, "rescue head", node->nd_head); @@ -3980,11 +3971,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_ENSURE:{ DECL_ANCHOR(ensr); - VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr, - rb_str_concat(rb_str_new2 - ("ensure in "), - iseq->location.label), - ISEQ_TYPE_ENSURE, line); + const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr, + rb_str_concat(rb_str_new2 ("ensure in "), iseq->body->location.label), + ISEQ_TYPE_ENSURE, line); LABEL *lstart = NEW_LABEL(line); LABEL *lend = NEW_LABEL(line); LABEL *lcont = NEW_LABEL(line); @@ -4050,7 +4039,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_LASGN:{ ID id = node->nd_vid; - int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); + int idx = iseq->body->local_iseq->body->local_size - get_local_var_idx(iseq, id); debugs("lvar: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx); COMPILE(ret, "rvalue", node->nd_value); @@ -4098,7 +4087,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) ADD_INSN(ret, line, dup); } ADD_INSN2(ret, line, setinstancevariable, - ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++)); + ID2SYM(node->nd_vid), INT2FIX(iseq->body->is_size++)); break; } case NODE_CDECL:{ @@ -4470,7 +4459,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) */ if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR && node->nd_mid == idFreeze && node->nd_args == NULL && - iseq->compile_data->current_block == Qfalse && + iseq->compile_data->current_block == NULL && iseq->compile_data->option->specialized_instruction) { VALUE str = rb_fstring(node->nd_recv->nd_lit); iseq_add_mark_object(iseq, str); @@ -4486,7 +4475,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args && nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 1 && nd_type(node->nd_args->nd_head) == NODE_STR && - iseq->compile_data->current_block == Qfalse && + iseq->compile_data->current_block == NULL && iseq->compile_data->option->specialized_instruction) { VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); node->nd_args->nd_head->nd_lit = str; @@ -4511,8 +4500,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) VALUE argc; unsigned int flag = 0; rb_call_info_kw_arg_t *keywords = NULL; - VALUE parent_block = iseq->compile_data->current_block; - iseq->compile_data->current_block = Qfalse; + const rb_iseq_t *parent_block = iseq->compile_data->current_block; + iseq->compile_data->current_block = NULL; INIT_ANCHOR(recv); INIT_ANCHOR(args); @@ -4623,10 +4612,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) int argc; unsigned int flag = 0; rb_call_info_kw_arg_t *keywords = NULL; - VALUE parent_block = iseq->compile_data->current_block; + const rb_iseq_t *parent_block = iseq->compile_data->current_block; INIT_ANCHOR(args); - iseq->compile_data->current_block = Qfalse; + iseq->compile_data->current_block = NULL; if (nd_type(node) == NODE_SUPER) { VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords); argc = FIX2INT(vargc); @@ -4634,43 +4623,43 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) else { /* NODE_ZSUPER */ int i; - const rb_iseq_t *liseq = iseq->local_iseq; + const rb_iseq_t *liseq = iseq->body->local_iseq; int lvar_level = get_lvar_level(iseq); - argc = liseq->param.lead_num; + argc = liseq->body->param.lead_num; /* normal arguments */ - for (i = 0; i < liseq->param.lead_num; i++) { - int idx = liseq->local_size - i; + for (i = 0; i < liseq->body->param.lead_num; i++) { + int idx = liseq->body->local_size - i; ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); } - if (liseq->param.flags.has_opt) { + if (liseq->body->param.flags.has_opt) { /* optional arguments */ int j; - for (j = 0; j < liseq->param.opt_num; j++) { - int idx = liseq->local_size - (i + j); + for (j = 0; j < liseq->body->param.opt_num; j++) { + int idx = liseq->body->local_size - (i + j); ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); } i += j; argc = i; } - if (liseq->param.flags.has_rest) { + if (liseq->body->param.flags.has_rest) { /* rest argument */ - int idx = liseq->local_size - liseq->param.rest_start; + int idx = liseq->body->local_size - liseq->body->param.rest_start; ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); - argc = liseq->param.rest_start + 1; + argc = liseq->body->param.rest_start + 1; flag |= VM_CALL_ARGS_SPLAT; } - if (liseq->param.flags.has_post) { + if (liseq->body->param.flags.has_post) { /* post arguments */ - int post_len = liseq->param.post_num; - int post_start = liseq->param.post_start; + int post_len = liseq->body->param.post_num; + int post_start = liseq->body->param.post_start; - if (liseq->param.flags.has_rest) { + if (liseq->body->param.flags.has_rest) { int j; for (j=0; j<post_len; j++) { - int idx = liseq->local_size - (post_start + j); + int idx = liseq->body->local_size - (post_start + j); ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); } ADD_INSN1(args, line, newarray, INT2FIX(j)); @@ -4680,43 +4669,43 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) else { int j; for (j=0; j<post_len; j++) { - int idx = liseq->local_size - (post_start + j); + int idx = liseq->body->local_size - (post_start + j); ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); } argc = post_len + post_start; } } - if (liseq->param.flags.has_kw) { /* TODO: support keywords */ - int local_size = liseq->local_size; + if (liseq->body->param.flags.has_kw) { /* TODO: support keywords */ + int local_size = liseq->body->local_size; argc++; ADD_INSN1(args, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (liseq->param.flags.has_kwrest) { - ADD_INSN2(args, line, getlocal, INT2FIX(liseq->local_size - liseq->param.keyword->rest_start), INT2FIX(lvar_level)); + if (liseq->body->param.flags.has_kwrest) { + ADD_INSN2(args, line, getlocal, INT2FIX(liseq->body->local_size - liseq->body->param.keyword->rest_start), INT2FIX(lvar_level)); ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0)); } else { ADD_INSN1(args, line, newhash, INT2FIX(0)); } - for (i = 0; i < liseq->param.keyword->num; ++i) { - ID id = liseq->param.keyword->table[i]; + for (i = 0; i < liseq->body->param.keyword->num; ++i) { + ID id = liseq->body->param.keyword->table[i]; int idx = local_size - get_local_var_idx(liseq, id); ADD_INSN1(args, line, putobject, ID2SYM(id)); ADD_INSN2(args, line, getlocal, INT2FIX(idx), INT2FIX(lvar_level)); } ADD_SEND(args, line, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1)); - if (liseq->param.flags.has_rest) { + if (liseq->body->param.flags.has_rest) { ADD_INSN1(args, line, newarray, INT2FIX(1)); ADD_INSN (args, line, concatarray); --argc; } } - else if (liseq->param.flags.has_kwrest) { - ADD_INSN2(args, line, getlocal, INT2FIX(liseq->local_size - liseq->param.keyword->rest_start), INT2FIX(lvar_level)); + else if (liseq->body->param.flags.has_kwrest) { + ADD_INSN2(args, line, getlocal, INT2FIX(liseq->body->local_size - liseq->body->param.keyword->rest_start), INT2FIX(lvar_level)); ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0)); - if (liseq->param.flags.has_rest) { + if (liseq->body->param.flags.has_rest) { ADD_INSN1(args, line, newarray, INT2FIX(1)); ADD_INSN (args, line, concatarray); } @@ -4787,13 +4776,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) rb_iseq_t *is = iseq; if (is) { - if (is->type == ISEQ_TYPE_TOP) { + if (is->body->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid return")); } else { LABEL *splabel = 0; - if (is->type == ISEQ_TYPE_METHOD) { + if (is->body->type == ISEQ_TYPE_METHOD) { splabel = NEW_LABEL(0); ADD_LABEL(ret, splabel); ADD_ADJUST(ret, line, 0); @@ -4801,7 +4790,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) COMPILE(ret, "return nd_stts (return val)", node->nd_stts); - if (is->type == ISEQ_TYPE_METHOD) { + if (is->body->type == ISEQ_TYPE_METHOD) { add_ensure_iseq(ret, iseq, 1); ADD_TRACE(ret, line, RUBY_EVENT_RETURN); ADD_INSN(ret, line, leave); @@ -4828,7 +4817,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) rb_call_info_kw_arg_t *keywords = NULL; INIT_ANCHOR(args); - if (iseq->type == ISEQ_TYPE_TOP) { + if (iseq->body->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid yield")); } @@ -4850,7 +4839,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_LVAR:{ if (!poped) { ID id = node->nd_vid; - int idx = iseq->local_iseq->local_size - get_local_var_idx(iseq, id); + int idx = iseq->body->local_iseq->body->local_size - get_local_var_idx(iseq, id); debugs("id: %"PRIsVALUE" idx: %d\n", rb_id2str(id), idx); ADD_INSN2(ret, line, getlocal, INT2FIX(idx), INT2FIX(get_lvar_level(iseq))); @@ -4881,7 +4870,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) debugi("nd_vid", node->nd_vid); if (!poped) { ADD_INSN2(ret, line, getinstancevariable, - ID2SYM(node->nd_vid), INT2FIX(iseq->is_size++)); + ID2SYM(node->nd_vid), INT2FIX(iseq->body->is_size++)); } break; } @@ -4890,7 +4879,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (iseq->compile_data->option->inline_const_cache) { LABEL *lend = NEW_LABEL(line); - int ic_index = iseq->is_size++; + int ic_index = iseq->body->is_size++; ADD_INSN2(ret, line, getinlinecache, lend, INT2FIX(ic_index)); ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid)); @@ -5046,10 +5035,10 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_DREGX_ONCE:{ - int ic_index = iseq->is_size++; + int ic_index = iseq->body->is_size++; NODE *dregx_node = NEW_NODE(NODE_DREGX, node->u1.value, node->u2.value, node->u3.value); NODE *block_node = NEW_NODE(NODE_SCOPE, 0, dregx_node, 0); - VALUE block_iseq = NEW_CHILD_ISEQVAL(block_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); + const rb_iseq_t * block_iseq = NEW_CHILD_ISEQ(block_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); ADD_INSN2(ret, line, once, block_iseq, INT2FIX(ic_index)); @@ -5099,36 +5088,35 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_DEFN:{ - VALUE iseqval = NEW_ISEQVAL(node->nd_defn, - rb_id2str(node->nd_mid), - ISEQ_TYPE_METHOD, line); + const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn, + rb_id2str(node->nd_mid), + ISEQ_TYPE_METHOD, line); - debugp_param("defn/iseq", iseqval); + debugp_param("defn/iseq", (VALUE)method_iseq); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid)); - ADD_INSN1(ret, line, putiseq, iseqval); + ADD_INSN1(ret, line, putiseq, method_iseq); ADD_SEND (ret, line, id_core_define_method, INT2FIX(3)); if (poped) { ADD_INSN(ret, line, pop); } - debugp_param("defn", iseqval); break; } case NODE_DEFS:{ - VALUE iseqval = NEW_ISEQVAL(node->nd_defn, - rb_id2str(node->nd_mid), - ISEQ_TYPE_METHOD, line); + const rb_iseq_t * singleton_method = NEW_ISEQ(node->nd_defn, + rb_id2str(node->nd_mid), + ISEQ_TYPE_METHOD, line); - debugp_param("defs/iseq", iseqval); + debugp_param("defs/iseq", (VALUE)singleton_method); ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); COMPILE(ret, "defs: recv", node->nd_recv); ADD_INSN1(ret, line, putobject, ID2SYM(node->nd_mid)); - ADD_INSN1(ret, line, putiseq, iseqval); + ADD_INSN1(ret, line, putiseq, singleton_method); ADD_SEND (ret, line, id_core_define_singleton_method, INT2FIX(3)); if (poped) { @@ -5171,18 +5159,16 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_CLASS:{ - VALUE iseqval = - NEW_CHILD_ISEQVAL( - node->nd_body, - rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)), - ISEQ_TYPE_CLASS, line); + const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body, + rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)), + ISEQ_TYPE_CLASS, line); VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath); int flags = VM_DEFINECLASS_TYPE_CLASS; + if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED; if (node->nd_super) flags |= VM_DEFINECLASS_FLAG_HAS_SUPERCLASS; COMPILE(ret, "super", node->nd_super); - ADD_INSN3(ret, line, defineclass, - ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags)); + ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags)); if (poped) { ADD_INSN(ret, line, pop); @@ -5190,17 +5176,16 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) break; } case NODE_MODULE:{ - VALUE iseqval = NEW_CHILD_ISEQVAL( - node->nd_body, - rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)), - ISEQ_TYPE_CLASS, line); - + const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body, + rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid)), + ISEQ_TYPE_CLASS, line); VALUE noscope = compile_cpath(ret, iseq, node->nd_cpath); int flags = VM_DEFINECLASS_TYPE_MODULE; + if (!noscope) flags |= VM_DEFINECLASS_FLAG_SCOPED; ADD_INSN (ret, line, putnil); /* dummy */ - ADD_INSN3(ret, line, defineclass, - ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(flags)); + ADD_INSN3(ret, line, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags)); + if (poped) { ADD_INSN(ret, line, pop); } @@ -5208,15 +5193,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_SCLASS:{ ID singletonclass; - VALUE iseqval = - NEW_ISEQVAL(node->nd_body, rb_str_new2("singleton class"), - ISEQ_TYPE_CLASS, line); + const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_str_new2("singleton class"), + ISEQ_TYPE_CLASS, line); COMPILE(ret, "sclass#recv", node->nd_recv); ADD_INSN (ret, line, putnil); CONST_ID(singletonclass, "singletonclass"); ADD_INSN3(ret, line, defineclass, - ID2SYM(singletonclass), iseqval, + ID2SYM(singletonclass), singleton_class, INT2FIX(VM_DEFINECLASS_TYPE_SINGLETON_CLASS)); if (poped) { @@ -5228,7 +5212,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (rb_is_const_id(node->nd_mid)) { /* constant */ LABEL *lend = NEW_LABEL(line); - int ic_index = iseq->is_size++; + int ic_index = iseq->body->is_size++; DECL_ANCHOR(pref); DECL_ANCHOR(body); @@ -5269,7 +5253,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_COLON3:{ LABEL *lend = NEW_LABEL(line); - int ic_index = iseq->is_size++; + int ic_index = iseq->body->is_size++; debugi("colon3#nd_mid", node->nd_mid); @@ -5311,11 +5295,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *lend = NEW_LABEL(line); LABEL *lfin = NEW_LABEL(line); LABEL *ltrue = NEW_LABEL(line); - rb_iseq_t *local_iseq = iseq->local_iseq; + rb_iseq_t *local_iseq = iseq->body->local_iseq; rb_num_t cnt; VALUE key; - cnt = local_iseq->flip_cnt++ + VM_SVAR_FLIPFLOP_START; + cnt = local_iseq->body->flip_cnt++ + VM_SVAR_FLIPFLOP_START; key = INT2FIX(cnt); ADD_INSN2(ret, line, getspecial, key, INT2FIX(0)); @@ -5373,17 +5357,17 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_ERRINFO:{ if (!poped) { - if (iseq->type == ISEQ_TYPE_RESCUE) { + if (iseq->body->type == ISEQ_TYPE_RESCUE) { ADD_INSN2(ret, line, getlocal, INT2FIX(2), INT2FIX(0)); } else { const rb_iseq_t *ip = iseq; int level = 0; while (ip) { - if (ip->type == ISEQ_TYPE_RESCUE) { + if (ip->body->type == ISEQ_TYPE_RESCUE) { break; } - ip = ip->parent_iseq; + ip = ip->body->parent_iseq; level++; } if (ip) { @@ -5421,10 +5405,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) /* compiled to: * ONCE{ rb_mRubyVMFrozenCore::core#set_postexe{ ... } } */ - int is_index = iseq->is_size++; - VALUE once_iseq = NEW_CHILD_ISEQVAL( - (NODE *)IFUNC_NEW(build_postexe_iseq, node->nd_body, 0), - make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); + int is_index = iseq->body->is_size++; + const rb_iseq_t *once_iseq = NEW_CHILD_ISEQ((NODE *)IFUNC_NEW(build_postexe_iseq, node->nd_body, 0), + make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); ADD_INSN2(ret, line, once, once_iseq, INT2FIX(is_index)); @@ -5453,8 +5436,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) * kw = default_value * end */ - int kw_bits_idx = iseq->local_size - iseq->param.keyword->bits_start; - int keyword_idx = iseq->param.keyword->num; + int kw_bits_idx = iseq->body->local_size - iseq->body->param.keyword->bits_start; + int keyword_idx = iseq->body->param.keyword->num; ADD_INSN2(ret, line, checkkeyword, INT2FIX(kw_bits_idx), INT2FIX(keyword_idx)); ADD_INSNL(ret, line, branchif, end_label); @@ -5486,7 +5469,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) if (node->nd_mid == idASET && !private_recv_p(node) && node->nd_args && nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 2 && nd_type(node->nd_args->nd_head) == NODE_STR && - iseq->compile_data->current_block == Qfalse && + iseq->compile_data->current_block == NULL && iseq->compile_data->option->specialized_instruction) { VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); @@ -5554,8 +5537,9 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) } case NODE_LAMBDA:{ /* compile same as lambda{...} */ - VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); + const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); VALUE argc = INT2FIX(0); + ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_CALL_WITH_BLOCK(ret, line, idLambda, argc, block); @@ -5640,7 +5624,7 @@ insn_data_to_s_detail(INSN *iobj) rb_iseq_t *iseq = (rb_iseq_t *)OPERAND_AT(iobj, j); VALUE val = Qnil; if (0 && iseq) { /* TODO: invalidate now */ - val = iseq->self; + val = (VALUE)iseq; } rb_str_concat(str, opobj_inspect(val)); } @@ -5817,7 +5801,8 @@ iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, int i; for (i=0; i<RARRAY_LEN(exception); i++) { - VALUE v, type, eiseqval; + const rb_iseq_t *eiseq; + VALUE v, type; const VALUE *ptr; LABEL *lstart, *lend, *lcont; unsigned int sp; @@ -5830,10 +5815,10 @@ iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, ptr = RARRAY_CONST_PTR(v); type = get_exception_sym2type(ptr[0]); if (ptr[1] == Qnil) { - eiseqval = 0; + eiseq = NULL; } else { - eiseqval = rb_iseq_load(ptr[1], iseq->self, Qnil); + eiseq = rb_iseqw_to_iseq(rb_iseq_load(ptr[1], (VALUE)iseq, Qnil)); } lstart = register_label(iseq, labels_table, ptr[2]); @@ -5843,7 +5828,7 @@ iseq_build_from_ary_exception(rb_iseq_t *iseq, struct st_table *labels_table, (void)sp; - ADD_CATCH_ENTRY(type, lstart, lend, eiseqval, lcont); + ADD_CATCH_ENTRY(type, lstart, lend, eiseq, lcont); RB_GC_GUARD(v); } @@ -5864,21 +5849,25 @@ insn_make_insn_table(void) return table; } -static VALUE -iseq_build_load_iseq(rb_iseq_t *iseq, VALUE op) +static const rb_iseq_t * +iseq_build_load_iseq(const rb_iseq_t *iseq, VALUE op) { - VALUE iseqval; + VALUE iseqw; + const rb_iseq_t *loaded_iseq; + if (RB_TYPE_P(op, T_ARRAY)) { - iseqval = rb_iseq_load(op, iseq->self, Qnil); + iseqw = rb_iseq_load(op, (VALUE)iseq, Qnil); } else if (CLASS_OF(op) == rb_cISeq) { - iseqval = op; + iseqw = op; } else { rb_raise(rb_eSyntaxError, "ISEQ is required"); } - iseq_add_mark_object(iseq, iseqval); - return iseqval; + + loaded_iseq = rb_iseqw_to_iseq(iseqw); + iseq_add_mark_object(iseq, (VALUE)loaded_iseq); + return loaded_iseq; } static VALUE @@ -5886,7 +5875,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op) { ID mid = 0; int orig_argc = 0; - VALUE block = 0; + const rb_iseq_t *block = NULL; unsigned int flag = 0; rb_call_info_kw_arg_t *kw_arg = 0; @@ -5957,12 +5946,12 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, insn = (argc < 0) ? Qnil : RARRAY_AREF(obj, 0); if (st_lookup(insn_table, (st_data_t)insn, &insn_id) == 0) { /* TODO: exception */ - rb_compile_error(RSTRING_PTR(iseq->location.path), line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), line_no, "unknown instruction: %+"PRIsVALUE, insn); } if (argc != insn_len((VALUE)insn_id)-1) { - rb_compile_error(RSTRING_PTR(iseq->location.path), line_no, + rb_compile_error(RSTRING_PTR(iseq->body->location.path), line_no, "operand size mismatch"); } @@ -5988,7 +5977,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, case TS_ISEQ: { if (op != Qnil) { - argv[j] = iseq_build_load_iseq(iseq, op); + argv[j] = (VALUE)iseq_build_load_iseq(iseq, op); } else { argv[j] = 0; @@ -6001,8 +5990,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, break; case TS_IC: argv[j] = op; - if (NUM2INT(op) >= iseq->is_size) { - iseq->is_size = NUM2INT(op) + 1; + if (NUM2INT(op) >= iseq->body->is_size) { + iseq->body->is_size = NUM2INT(op) + 1; } break; case TS_CALLINFO: @@ -6089,14 +6078,14 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords) int default_len; VALUE key, sym, default_val; - iseq->param.flags.has_kw = TRUE; + iseq->body->param.flags.has_kw = TRUE; - iseq->param.keyword = ZALLOC(struct rb_iseq_param_keyword); - iseq->param.keyword->num = len; + iseq->body->param.keyword = ZALLOC(struct rb_iseq_param_keyword); + iseq->body->param.keyword->num = len; #define SYM(s) ID2SYM(rb_intern(#s)) - (void)int_param(&iseq->param.keyword->bits_start, params, SYM(kwbits)); - i = iseq->param.keyword->bits_start - iseq->param.keyword->num; - iseq->param.keyword->table = &iseq->local_table[i]; + (void)int_param(&iseq->body->param.keyword->bits_start, params, SYM(kwbits)); + i = iseq->body->param.keyword->bits_start - iseq->body->param.keyword->num; + iseq->body->param.keyword->table = &iseq->body->local_table[i]; #undef SYM /* required args */ @@ -6106,8 +6095,8 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords) if (!SYMBOL_P(val)) { goto default_values; } - iseq->param.keyword->table[i] = SYM2ID(val); - iseq->param.keyword->required_num++; + iseq->body->param.keyword->table[i] = SYM2ID(val); + iseq->body->param.keyword->required_num++; } default_values: /* note: we intentionally preserve `i' from previous loop */ @@ -6116,7 +6105,7 @@ default_values: /* note: we intentionally preserve `i' from previous loop */ return; } - iseq->param.keyword->default_values = ALLOC_N(VALUE, default_len); + iseq->body->param.keyword->default_values = ALLOC_N(VALUE, default_len); for (j = 0; i < len; i++, j++) { key = RARRAY_AREF(keywords, i); @@ -6136,12 +6125,12 @@ default_values: /* note: we intentionally preserve `i' from previous loop */ "keyword default has unsupported len %+"PRIsVALUE, key); } - iseq->param.keyword->table[i] = SYM2ID(sym); - iseq->param.keyword->default_values[j] = default_val; + iseq->body->param.keyword->table[i] = SYM2ID(sym); + iseq->body->param.keyword->default_values[j] = default_val; } } -VALUE +void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body) { @@ -6156,9 +6145,9 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, INIT_ANCHOR(anchor); len = RARRAY_LENINT(locals); - iseq->local_table_size = len; - iseq->local_table = tbl = (ID *)ALLOC_N(ID, iseq->local_table_size); - iseq->local_size = iseq->local_table_size + 1; + iseq->body->local_table_size = len; + iseq->body->local_table = tbl = (ID *)ALLOC_N(ID, iseq->body->local_table_size); + iseq->body->local_size = iseq->body->local_table_size + 1; for (i = 0; i < len; i++) { VALUE lv = RARRAY_AREF(locals, i); @@ -6176,30 +6165,30 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, * local_size, stack_size and param.size are all calculated */ -#define INT_PARAM(F) int_param(&iseq->param.F, params, SYM(F)) +#define INT_PARAM(F) int_param(&iseq->body->param.F, params, SYM(F)) if (INT_PARAM(lead_num)) { - iseq->param.flags.has_lead = TRUE; + iseq->body->param.flags.has_lead = TRUE; } - if (INT_PARAM(post_num)) iseq->param.flags.has_post = TRUE; - if (INT_PARAM(post_start)) iseq->param.flags.has_post = TRUE; - if (INT_PARAM(rest_start)) iseq->param.flags.has_rest = TRUE; - if (INT_PARAM(block_start)) iseq->param.flags.has_block = TRUE; + if (INT_PARAM(post_num)) iseq->body->param.flags.has_post = TRUE; + if (INT_PARAM(post_start)) iseq->body->param.flags.has_post = TRUE; + if (INT_PARAM(rest_start)) iseq->body->param.flags.has_rest = TRUE; + if (INT_PARAM(block_start)) iseq->body->param.flags.has_block = TRUE; #undef INT_PARAM switch (TYPE(arg_opt_labels)) { case T_ARRAY: len = RARRAY_LENINT(arg_opt_labels); - iseq->param.flags.has_opt = !!(len - 1 >= 0); + iseq->body->param.flags.has_opt = !!(len - 1 >= 0); - if (iseq->param.flags.has_opt) { - iseq->param.opt_num = len - 1; - iseq->param.opt_table = (VALUE *)ALLOC_N(VALUE, len); + if (iseq->body->param.flags.has_opt) { + iseq->body->param.opt_num = len - 1; + iseq->body->param.opt_table = (VALUE *)ALLOC_N(VALUE, len); for (i = 0; i < len; i++) { VALUE ent = RARRAY_AREF(arg_opt_labels, i); LABEL *label = register_label(iseq, labels_table, ent); - iseq->param.opt_table[i] = (VALUE)label; + iseq->body->param.opt_table[i] = (VALUE)label; } } case T_NIL: @@ -6220,15 +6209,15 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, } if (Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) { - iseq->param.flags.ambiguous_param0 = TRUE; + iseq->body->param.flags.ambiguous_param0 = TRUE; } if (int_param(&i, params, SYM(kwrest))) { - if (!iseq->param.keyword) { - iseq->param.keyword = ZALLOC(struct rb_iseq_param_keyword); + if (!iseq->body->param.keyword) { + iseq->body->param.keyword = ZALLOC(struct rb_iseq_param_keyword); } - iseq->param.keyword->rest_start = i; - iseq->param.flags.has_kwrest = TRUE; + iseq->body->param.keyword->rest_start = i; + iseq->body->param.flags.has_kwrest = TRUE; } #undef SYM @@ -6239,7 +6228,6 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, /* body */ iseq_build_from_ary_body(iseq, anchor, body, labels_table); - return iseq->self; } /* for parser */ @@ -6251,20 +6239,20 @@ rb_dvar_defined(ID id) const rb_iseq_t *iseq; if (th->base_block && (iseq = th->base_block->iseq)) { - while (iseq->type == ISEQ_TYPE_BLOCK || - iseq->type == ISEQ_TYPE_RESCUE || - iseq->type == ISEQ_TYPE_ENSURE || - iseq->type == ISEQ_TYPE_EVAL || - iseq->type == ISEQ_TYPE_MAIN + while (iseq->body->type == ISEQ_TYPE_BLOCK || + iseq->body->type == ISEQ_TYPE_RESCUE || + iseq->body->type == ISEQ_TYPE_ENSURE || + iseq->body->type == ISEQ_TYPE_EVAL || + iseq->body->type == ISEQ_TYPE_MAIN ) { int i; - for (i = 0; i < iseq->local_table_size; i++) { - if (iseq->local_table[i] == id) { + for (i = 0; i < iseq->body->local_table_size; i++) { + if (iseq->body->local_table[i] == id) { return 1; } } - iseq = iseq->parent_iseq; + iseq = iseq->body->parent_iseq; } } return 0; @@ -6278,10 +6266,10 @@ rb_local_defined(ID id) if (th->base_block && th->base_block->iseq) { int i; - iseq = th->base_block->iseq->local_iseq; + iseq = th->base_block->iseq->body->local_iseq; - for (i=0; i<iseq->local_table_size; i++) { - if (iseq->local_table[i] == id) { + for (i=0; i<iseq->body->local_table_size; i++) { + if (iseq->body->local_table[i] == id) { return 1; } } @@ -6310,8 +6298,8 @@ caller_location(VALUE *path, VALUE *absolute_path) if (cfp) { int line = rb_vm_get_sourceline(cfp); - *path = cfp->iseq->location.path; - *absolute_path = cfp->iseq->location.absolute_path; + *path = cfp->iseq->body->location.path; + *absolute_path = cfp->iseq->body->location.absolute_path; return line; } else { @@ -6327,7 +6315,7 @@ typedef struct { int line; } accessor_args; -static VALUE +static const rb_iseq_t * method_for_self(VALUE name, VALUE arg, rb_insn_func_t func, VALUE (*build)(rb_iseq_t *, LINK_ANCHOR *, VALUE)) { @@ -6349,8 +6337,8 @@ for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a) const int line = args->line; iseq_set_local_table(iseq, 0); - iseq->param.lead_num = 0; - iseq->param.size = 0; + iseq->body->param.lead_num = 0; + iseq->body->param.size = 0; ADD_INSN1(ret, line, putobject, args->arg); ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func); @@ -6365,8 +6353,8 @@ for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a) static const ID vars[] = {1, idUScore}; iseq_set_local_table(iseq, vars); - iseq->param.lead_num = 1; - iseq->param.size = 1; + iseq->body->param.lead_num = 1; + iseq->body->param.size = 1; ADD_INSN2(ret, line, getlocal, INT2FIX(numberof(vars)-0), INT2FIX(0)); ADD_INSN1(ret, line, putobject, args->arg); @@ -6378,7 +6366,7 @@ for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, VALUE a) /* * func (index) -> (value) */ -VALUE +const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func) { return method_for_self(name, arg, func, for_self_aref); @@ -6387,7 +6375,7 @@ rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func) /* * func (index, value) -> (index, value) */ -VALUE +const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func) { return method_for_self(name, arg, func, for_self_aset); @@ -237,7 +237,7 @@ static int ruby_exec_internal(void *n) { volatile int state; - VALUE iseq = (VALUE)n; + rb_iseq_t *iseq = (rb_iseq_t *)n; rb_thread_t *th = GET_THREAD(); if (!n) return 0; @@ -1448,10 +1448,10 @@ errinfo_place(rb_thread_t *th) while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { - if (cfp->iseq->type == ISEQ_TYPE_RESCUE) { + if (cfp->iseq->body->type == ISEQ_TYPE_RESCUE) { return &cfp->ep[-2]; } - else if (cfp->iseq->type == ISEQ_TYPE_ENSURE && + else if (cfp->iseq->body->type == ISEQ_TYPE_ENSURE && !THROW_DATA_P(cfp->ep[-2]) && !FIXNUM_P(cfp->ep[-2])) { return &cfp->ep[-2]; diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index 352380d89b..a268be8f76 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -497,7 +497,7 @@ count_tdata_objects(int argc, VALUE *argv, VALUE self) return hash; } -static ID imemo_type_ids[imemo_mask]; +static ID imemo_type_ids[imemo_mask+1]; static int count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data) @@ -567,6 +567,7 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self) imemo_type_ids[4] = rb_intern("imemo_ifunc"); imemo_type_ids[5] = rb_intern("imemo_memo"); imemo_type_ids[6] = rb_intern("imemo_ment"); + imemo_type_ids[7] = rb_intern("imemo_iseq"); } rb_objspace_each_objects(count_imemo_objects_i, (void *)hash); @@ -404,6 +404,7 @@ typedef struct RVALUE { struct vm_ifunc ifunc; struct MEMO memo; struct rb_method_entry_struct ment; + const rb_iseq_t iseq; } imemo; struct { struct RBasic basic; @@ -699,6 +700,7 @@ static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT_MIN}}; #endif #define ruby_initial_gc_stress gc_params.gc_stress + VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress; #define malloc_limit objspace->malloc_params.limit @@ -778,6 +780,9 @@ int ruby_gc_debug_indent = 0; VALUE rb_mGC; int ruby_disable_gc = 0; +void rb_iseq_mark(const rb_iseq_t *iseq); +void rb_iseq_free(const rb_iseq_t *iseq); + void rb_gcdebug_print_obj_condition(VALUE obj); static void rb_objspace_call_finalizer(rb_objspace_t *objspace); @@ -2140,11 +2145,18 @@ obj_free(rb_objspace_t *objspace, VALUE obj) case T_IMEMO: { - if (imemo_type(obj) == imemo_ment) { + switch (imemo_type(obj)) { + case imemo_ment: rb_free_method_entry(&RANY(obj)->as.imemo.ment); + break; + case imemo_iseq: + rb_iseq_free(&RANY(obj)->as.imemo.iseq); + break; + default: + break; } } - break; + return 0; default: rb_bug("gc_sweep(): unknown data type 0x%x(%p) 0x%"PRIxVALUE, @@ -3924,7 +3936,7 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me) if (def) { switch (def->type) { case VM_METHOD_TYPE_ISEQ: - if (def->body.iseq.iseqptr) gc_mark(objspace, def->body.iseq.iseqptr->self); + if (def->body.iseq.iseqptr) gc_mark(objspace, (VALUE)def->body.iseq.iseqptr); gc_mark(objspace, (VALUE)def->body.iseq.cref); break; case VM_METHOD_TYPE_ATTRSET: @@ -4272,6 +4284,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) case T_IMEMO: switch (imemo_type(obj)) { + case imemo_none: + rb_bug("unreachable"); + return; case imemo_cref: gc_mark(objspace, RANY(obj)->as.imemo.cref.klass); gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next); @@ -4297,9 +4312,11 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) case imemo_ment: mark_method_entry(objspace, &RANY(obj)->as.imemo.ment); return; - default: - rb_bug("T_IMEMO: unreachable"); + case imemo_iseq: + rb_iseq_mark((rb_iseq_t *)obj); + return; } + rb_bug("T_IMEMO: unreachable"); } gc_mark(objspace, any->as.basic.klass); @@ -8917,15 +8934,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) } case T_DATA: { const char * const type_name = rb_objspace_data_type_name(obj); - if (type_name && strcmp(type_name, "iseq") == 0) { - rb_iseq_t *iseq; - GetISeqPtr(obj, iseq); - if (iseq->location.label) { - snprintf(buff, buff_size, "%s %s@%s:%d", buff, - RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path), (int)iseq->location.first_lineno); - } - } - else if (type_name) { + if (type_name) { snprintf(buff, buff_size, "%s %s", buff, type_name); } break; @@ -8945,10 +8954,25 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj) #undef IMEMO_NAME } snprintf(buff, buff_size, "%s %s", buff, imemo_name); - if (imemo_type(obj) == imemo_ment) { - const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment; - snprintf(buff, buff_size, "%s (called_id: %s, type: %s, alias: %d, class: %s)", buff, - rb_id2name(me->called_id), method_type_name(me->def->type), me->def->alias_count, obj_info(me->defined_class)); + + switch (imemo_type(obj)) { + case imemo_ment: { + const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment; + snprintf(buff, buff_size, "%s (called_id: %s, type: %s, alias: %d, class: %s)", buff, + rb_id2name(me->called_id), method_type_name(me->def->type), me->def->alias_count, obj_info(me->defined_class)); + break; + } + case imemo_iseq: { + const rb_iseq_t *iseq = (const rb_iseq_t *)obj; + + if (iseq->body->location.label) { + snprintf(buff, buff_size, "%s %s@%s:%d", buff, + RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path), (int)iseq->body->location.first_lineno); + } + break; + } + default: + break; } } default: @@ -337,7 +337,7 @@ putiseq () (VALUE ret) { - ret = iseq->self; + ret = (VALUE)iseq; } /** @@ -917,8 +917,8 @@ defineclass vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, klass, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), (VALUE)vm_cref_push(th, klass, NULL), - class_iseq->iseq_encoded, GET_SP(), - class_iseq->local_size, class_iseq->stack_max); + class_iseq->body->iseq_encoded, GET_SP(), + class_iseq->body->local_size, class_iseq->body->stack_max); RESTORE_REGS(); NEXT_INSN(); diff --git a/internal.h b/internal.h index c91d8caba0..5ba73847fa 100644 --- a/internal.h +++ b/internal.h @@ -546,6 +546,7 @@ enum imemo_type { imemo_ifunc = 4, imemo_memo = 5, imemo_ment = 6, + imemo_iseq = 7, imemo_mask = 0x07 }; @@ -854,14 +855,6 @@ void rb_write_error_str(VALUE mesg); VALUE rb_io_flush_raw(VALUE, int); size_t rb_io_memsize(const rb_io_t *); -/* iseq.c */ -VALUE rb_iseq_path(VALUE iseqval); -VALUE rb_iseq_absolute_path(VALUE iseqval); -VALUE rb_iseq_label(VALUE iseqval); -VALUE rb_iseq_base_label(VALUE iseqval); -VALUE rb_iseq_first_lineno(VALUE iseqval); -VALUE rb_iseq_method_name(VALUE self); - /* load.c */ VALUE rb_get_load_path(void); VALUE rb_get_expanded_load_path(void); @@ -29,6 +29,7 @@ #define ISEQ_MINOR_VERSION 2 VALUE rb_cISeq; +ID iseqw_iseq_key; #define hidden_obj_p(obj) (!SPECIAL_CONST_P(obj) && !RBASIC(obj)->klass) @@ -63,60 +64,61 @@ compile_data_free(struct iseq_compile_data *compile_data) } } -static void -iseq_free(void *ptr) +void +rb_iseq_free(const rb_iseq_t *iseq) { RUBY_FREE_ENTER("iseq"); - if (ptr) { + if (iseq) { int i; - rb_iseq_t *iseq = ptr; - ruby_xfree(iseq->iseq_encoded); - ruby_xfree(iseq->line_info_table); - ruby_xfree(iseq->local_table); - ruby_xfree(iseq->is_entries); + ruby_xfree(iseq->body->iseq_encoded); + ruby_xfree(iseq->body->line_info_table); + ruby_xfree(iseq->body->local_table); + ruby_xfree(iseq->body->is_entries); - if (iseq->callinfo_entries) { - for (i=0; i<iseq->callinfo_size; i++) { + if (iseq->body->callinfo_entries) { + for (i=0; i<iseq->body->callinfo_size; i++) { /* TODO: revisit callinfo data structure */ - const rb_call_info_kw_arg_t *kw_arg = iseq->callinfo_entries[i].kw_arg; + const rb_call_info_kw_arg_t *kw_arg = iseq->body->callinfo_entries[i].kw_arg; ruby_xfree((void *)kw_arg); } - ruby_xfree(iseq->callinfo_entries); + ruby_xfree(iseq->body->callinfo_entries); } - ruby_xfree(iseq->catch_table); - ruby_xfree(iseq->param.opt_table); - if (iseq->param.keyword != NULL) { - ruby_xfree(iseq->param.keyword->default_values); - ruby_xfree(iseq->param.keyword); + ruby_xfree(iseq->body->catch_table); + ruby_xfree(iseq->body->param.opt_table); + if (iseq->body->param.keyword != NULL) { + ruby_xfree(iseq->body->param.keyword->default_values); + ruby_xfree(iseq->body->param.keyword); } compile_data_free(iseq->compile_data); - ruby_xfree(iseq->iseq); - - ruby_xfree(ptr); + ruby_xfree(iseq->body->iseq); + ruby_xfree(iseq->body); } RUBY_FREE_LEAVE("iseq"); } -static void -iseq_mark(void *ptr) +void +rb_iseq_mark(const rb_iseq_t *iseq) { - const rb_iseq_t *iseq = ptr; - RUBY_MARK_ENTER("iseq"); - RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path)); + RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); + + if (iseq->body) { + const struct rb_iseq_body *body = iseq->body; - RUBY_MARK_UNLESS_NULL(iseq->mark_ary); - RUBY_MARK_UNLESS_NULL(iseq->location.label); - RUBY_MARK_UNLESS_NULL(iseq->location.base_label); - RUBY_MARK_UNLESS_NULL(iseq->location.path); - RUBY_MARK_UNLESS_NULL(iseq->location.absolute_path); - RUBY_MARK_UNLESS_NULL(iseq->coverage); + RUBY_MARK_UNLESS_NULL(body->mark_ary); + RUBY_MARK_UNLESS_NULL(body->location.label); + RUBY_MARK_UNLESS_NULL(body->location.base_label); + RUBY_MARK_UNLESS_NULL(body->location.path); + RUBY_MARK_UNLESS_NULL(body->location.absolute_path); + RUBY_MARK_UNLESS_NULL(body->coverage); + } if (iseq->compile_data != 0) { - struct iseq_compile_data *const compile_data = iseq->compile_data; + const struct iseq_compile_data *const compile_data = iseq->compile_data; + RUBY_MARK_UNLESS_NULL(compile_data->mark_ary); RUBY_MARK_UNLESS_NULL(compile_data->err_info); RUBY_MARK_UNLESS_NULL(compile_data->catch_table_ary); @@ -125,6 +127,7 @@ iseq_mark(void *ptr) RUBY_MARK_LEAVE("iseq"); } +#if 0 /* TODO */ static size_t iseq_memsize(const void *ptr) { @@ -133,19 +136,19 @@ iseq_memsize(const void *ptr) if (ptr) { const rb_iseq_t *iseq = ptr; - size += iseq->iseq_size * sizeof(VALUE); - size += iseq->line_info_size * sizeof(struct iseq_line_info_entry); - size += iseq->local_table_size * sizeof(ID); - if (iseq->catch_table) { - size += iseq_catch_table_bytes(iseq->catch_table->size); + size += iseq->body->iseq_size * sizeof(VALUE); + size += iseq->body->line_info_size * sizeof(struct iseq_line_info_entry); + size += iseq->body->local_table_size * sizeof(ID); + if (iseq->body->catch_table) { + size += iseq_catch_table_bytes(iseq->body->catch_table->size); } - size += (iseq->param.opt_num + 1) * sizeof(VALUE); - if (iseq->param.keyword != NULL) { + size += (iseq->body->param.opt_num + 1) * sizeof(VALUE); + if (iseq->body->param.keyword != NULL) { size += sizeof(struct rb_iseq_param_keyword); - size += sizeof(VALUE) * (iseq->param.keyword->num - iseq->param.keyword->required_num); + size += sizeof(VALUE) * (iseq->body->param.keyword->num - iseq->body->param.keyword->required_num); } - size += iseq->is_size * sizeof(union iseq_inline_storage_entry); - size += iseq->callinfo_size * sizeof(rb_call_info_t); + size += iseq->body->is_size * sizeof(union iseq_inline_storage_entry); + size += iseq->body->callinfo_size * sizeof(rb_call_info_t); if (iseq->compile_data) { struct iseq_compile_data_storage *cur; @@ -157,115 +160,103 @@ iseq_memsize(const void *ptr) } size += sizeof(struct iseq_compile_data); } - if (iseq->iseq) { - size += iseq->iseq_size * sizeof(VALUE); + if (iseq->body->iseq) { + size += iseq->body->iseq_size * sizeof(VALUE); } } return size; } +#endif -static const rb_data_type_t iseq_data_type = { - "iseq", - { - iseq_mark, - iseq_free, - iseq_memsize, - }, /* functions */ - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_PROMOTED1 /* start from age == 2 */ | RUBY_TYPED_WB_PROTECTED -}; - -static VALUE -iseq_alloc(VALUE klass) +static rb_iseq_t * +iseq_alloc(void) { - rb_iseq_t *iseq; - return TypedData_Make_Struct(klass, rb_iseq_t, &iseq_data_type, iseq); + rb_iseq_t *iseq = (rb_iseq_t *)rb_imemo_new(imemo_iseq, 0, 0, 0, 0); + iseq->body = ZALLOC(struct rb_iseq_body); + return iseq; } static rb_iseq_location_t * iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name, VALUE first_lineno) { - rb_iseq_location_t *loc = &iseq->location; - RB_OBJ_WRITE(iseq->self, &loc->path, path); + rb_iseq_location_t *loc = &iseq->body->location; + RB_OBJ_WRITE(iseq, &loc->path, path); if (RTEST(absolute_path) && rb_str_cmp(path, absolute_path) == 0) { - RB_OBJ_WRITE(iseq->self, &loc->absolute_path, path); + RB_OBJ_WRITE(iseq, &loc->absolute_path, path); } else { - RB_OBJ_WRITE(iseq->self, &loc->absolute_path, absolute_path); + RB_OBJ_WRITE(iseq, &loc->absolute_path, absolute_path); } - RB_OBJ_WRITE(iseq->self, &loc->label, name); - RB_OBJ_WRITE(iseq->self, &loc->base_label, name); + RB_OBJ_WRITE(iseq, &loc->label, name); + RB_OBJ_WRITE(iseq, &loc->base_label, name); loc->first_lineno = first_lineno; return loc; } static void -set_relation(rb_iseq_t *iseq, const VALUE parent) +set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq) { - const VALUE type = iseq->type; - rb_iseq_t *piseq; + const VALUE type = iseq->body->type; /* set class nest stack */ if (type == ISEQ_TYPE_TOP) { - iseq->local_iseq = iseq; + iseq->body->local_iseq = iseq; } else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) { - iseq->local_iseq = iseq; + iseq->body->local_iseq = iseq; } - else if (RTEST(parent)) { - GetISeqPtr(parent, piseq); - iseq->local_iseq = piseq->local_iseq; + else if (piseq) { + iseq->body->local_iseq = piseq->body->local_iseq; } - if (RTEST(parent)) { - GetISeqPtr(parent, piseq); - iseq->parent_iseq = piseq; + if (piseq) { + iseq->body->parent_iseq = piseq; } if (type == ISEQ_TYPE_MAIN) { - iseq->local_iseq = iseq; + iseq->body->local_iseq = iseq; } } void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj) { - if (!RTEST(iseq->mark_ary)) { - RB_OBJ_WRITE(iseq->self, &iseq->mark_ary, rb_ary_tmp_new(3)); - RBASIC_CLEAR_CLASS(iseq->mark_ary); + if (!RTEST(iseq->body->mark_ary)) { + RB_OBJ_WRITE(iseq, &iseq->body->mark_ary, rb_ary_tmp_new(3)); + RBASIC_CLEAR_CLASS(iseq->body->mark_ary); } - rb_ary_push(iseq->mark_ary, obj); + rb_ary_push(iseq->body->mark_ary, obj); } static VALUE prepare_iseq_build(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, - VALUE parent, enum iseq_type type, + const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option) { - iseq->type = type; + iseq->body->type = type; set_relation(iseq, parent); name = rb_fstring(name); path = rb_fstring(path); if (RTEST(absolute_path)) absolute_path = rb_fstring(absolute_path); iseq_location_setup(iseq, path, absolute_path, name, first_lineno); - if (iseq != iseq->local_iseq) { - RB_OBJ_WRITE(iseq->self, &iseq->location.base_label, iseq->local_iseq->location.label); + if (iseq != iseq->body->local_iseq) { + RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label); } - RB_OBJ_WRITE(iseq->self, &iseq->mark_ary, 0); + RB_OBJ_WRITE(iseq, &iseq->body->mark_ary, 0); iseq->compile_data = ZALLOC(struct iseq_compile_data); - RB_OBJ_WRITE(iseq->self, &iseq->compile_data->err_info, Qnil); - RB_OBJ_WRITE(iseq->self, &iseq->compile_data->mark_ary, rb_ary_tmp_new(3)); + RB_OBJ_WRITE(iseq, &iseq->compile_data->err_info, Qnil); + RB_OBJ_WRITE(iseq, &iseq->compile_data->mark_ary, rb_ary_tmp_new(3)); iseq->compile_data->storage_head = iseq->compile_data->storage_current = (struct iseq_compile_data_storage *) ALLOC_N(char, INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE + SIZEOF_ISEQ_COMPILE_DATA_STORAGE); - RB_OBJ_WRITE(iseq->self, &iseq->compile_data->catch_table_ary, rb_ary_new()); + RB_OBJ_WRITE(iseq, &iseq->compile_data->catch_table_ary, rb_ary_tmp_new(3)); iseq->compile_data->storage_head->pos = 0; iseq->compile_data->storage_head->next = 0; iseq->compile_data->storage_head->size = @@ -273,12 +264,13 @@ prepare_iseq_build(rb_iseq_t *iseq, iseq->compile_data->option = option; iseq->compile_data->last_coverable_line = -1; - RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse); + RB_OBJ_WRITE(iseq, &iseq->body->coverage, Qfalse); + if (!GET_THREAD()->parse_in_eval) { VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { - RB_OBJ_WRITE(iseq->self, &iseq->coverage, rb_hash_lookup(coverages, path)); - if (NIL_P(iseq->coverage)) RB_OBJ_WRITE(iseq->self, &iseq->coverage, Qfalse); + RB_OBJ_WRITE(iseq, &iseq->body->coverage, rb_hash_lookup(coverages, path)); + if (NIL_P(iseq->body->coverage)) RB_OBJ_WRITE(iseq, &iseq->body->coverage, Qfalse); } } @@ -294,7 +286,7 @@ cleanup_iseq_build(rb_iseq_t *iseq) compile_data_free(data); if (RTEST(err)) { - rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->location.path); + rb_funcall2(err, rb_intern("set_backtrace"), 1, &iseq->body->location.path); rb_exc_raise(err); } return Qtrue; @@ -379,49 +371,45 @@ make_compile_option_value(rb_compile_option_t *option) return opt; } -VALUE +rb_iseq_t * rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path, - VALUE parent, enum iseq_type type) + const rb_iseq_t *parent, enum iseq_type type) { return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, type, &COMPILE_OPTION_DEFAULT); } -VALUE -rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent) +rb_iseq_t * +rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, const rb_iseq_t *parent) { return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT); } -VALUE +rb_iseq_t * rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path) { rb_thread_t *th = GET_THREAD(); - VALUE parent = th->base_block->iseq->self; + const rb_iseq_t *parent = th->base_block->iseq; return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), path, absolute_path, INT2FIX(0), parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT); } -VALUE +rb_iseq_t * rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, - VALUE first_lineno, VALUE parent, enum iseq_type type, - const rb_compile_option_t *option) + VALUE first_lineno, const rb_iseq_t *parent, + enum iseq_type type, const rb_compile_option_t *option) { /* TODO: argument check */ - rb_iseq_t *iseq; - VALUE self = iseq_alloc(rb_cISeq); - - GetISeqPtr(self, iseq); - iseq->self = self; + rb_iseq_t *iseq = iseq_alloc(); if (!option) option = &COMPILE_OPTION_DEFAULT; - prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, - type, option); + prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, type, option); - rb_iseq_compile_node(self, node); + rb_iseq_compile_node(iseq, node); cleanup_iseq_build(iseq); - return self; + + return iseq; } #define CHECK_ARRAY(v) rb_convert_type((v), T_ARRAY, "Array", "to_ary") @@ -457,17 +445,18 @@ iseq_type_from_sym(VALUE type) return (enum iseq_type)-1; } +static VALUE iseqw_new(const rb_iseq_t *iseq); + static VALUE -iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt) +iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) { - VALUE iseqval = iseq_alloc(self); + rb_iseq_t *iseq = iseq_alloc(); VALUE magic, version1, version2, format_type, misc; VALUE name, path, absolute_path, first_lineno; VALUE type, body, locals, params, exception; st_data_t iseq_type; - rb_iseq_t *iseq; rb_compile_option_t option; int i = 0; @@ -497,28 +486,22 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt) exception = CHECK_ARRAY(rb_ary_entry(data, i++)); body = CHECK_ARRAY(rb_ary_entry(data, i++)); - GetISeqPtr(iseqval, iseq); - iseq->self = iseqval; - iseq->local_iseq = iseq; + iseq->body->local_iseq = iseq; iseq_type = iseq_type_from_sym(type); if (iseq_type == (enum iseq_type)-1) { rb_raise(rb_eTypeError, "unsupport type: :%"PRIsVALUE, rb_sym2str(type)); } - if (parent == Qnil) { - parent = 0; - } - make_compile_option(&option, opt); - prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, (enum iseq_type)iseq_type, &option); rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body); cleanup_iseq_build(iseq); - return iseqval; + + return iseqw_new(iseq); } /* @@ -530,22 +513,22 @@ iseq_s_load(int argc, VALUE *argv, VALUE self) VALUE data, opt=Qnil; rb_scan_args(argc, argv, "11", &data, &opt); - return iseq_load(self, data, 0, opt); + return iseq_load(data, NULL, opt); } VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt) { - return iseq_load(rb_cISeq, data, parent, opt); + return iseq_load(data, RTEST(parent) ? (rb_iseq_t *)parent : NULL, opt); } -VALUE +rb_iseq_t * rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt) { int state; rb_thread_t *th = GET_THREAD(); rb_block_t *prev_base_block = th->base_block; - VALUE iseqval = Qundef; + rb_iseq_t *iseq = NULL; th->base_block = base_block; @@ -573,13 +556,13 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE li } if (base_block && base_block->iseq) { - iseqval = rb_iseq_new_with_opt(node, base_block->iseq->location.label, - file, absolute_path, line, base_block->iseq->self, - ISEQ_TYPE_EVAL, &option); + iseq = rb_iseq_new_with_opt(node, base_block->iseq->body->location.label, + file, absolute_path, line, base_block->iseq, + ISEQ_TYPE_EVAL, &option); } else { - iseqval = rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, Qfalse, - ISEQ_TYPE_TOP, &option); + iseq = rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, + NULL, ISEQ_TYPE_TOP, &option); } } TH_POP_TAG(); @@ -590,21 +573,82 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE li JUMP_TAG(state); } - return iseqval; + return iseq; } -VALUE +rb_iseq_t * rb_iseq_compile(VALUE src, VALUE file, VALUE line) { return rb_iseq_compile_with_option(src, file, Qnil, line, 0, Qnil); } -VALUE +rb_iseq_t * rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block) { return rb_iseq_compile_with_option(src, file, Qnil, line, base_block, Qnil); } +VALUE +rb_iseq_path(const rb_iseq_t *iseq) +{ + return iseq->body->location.path; +} + +VALUE +rb_iseq_absolute_path(const rb_iseq_t *iseq) +{ + return iseq->body->location.absolute_path; +} + +VALUE +rb_iseq_label(const rb_iseq_t *iseq) +{ + return iseq->body->location.label; +} + +VALUE +rb_iseq_base_label(const rb_iseq_t *iseq) +{ + return iseq->body->location.base_label; +} + +VALUE +rb_iseq_first_lineno(const rb_iseq_t *iseq) +{ + return iseq->body->location.first_lineno; +} + +VALUE +rb_iseq_method_name(const rb_iseq_t *iseq) +{ + const rb_iseq_t *local_iseq; + + local_iseq = iseq->body->local_iseq; + + if (local_iseq->body->type == ISEQ_TYPE_METHOD) { + return local_iseq->body->location.base_label; + } + else { + return Qnil; + } +} + +/* define wrapper class methods (RubyVM::InstructionSequence) */ + +static VALUE +iseqw_new(const rb_iseq_t *iseq) +{ + VALUE iseqw = rb_obj_alloc(rb_cISeq); + rb_ivar_set(iseqw, iseqw_iseq_key, (VALUE)iseq); + return iseqw; +} + +VALUE +rb_iseqw_new(const rb_iseq_t *iseq) +{ + return iseqw_new(iseq); +} + /* * call-seq: * InstructionSequence.compile(source[, file[, path[, line[, options]]]]) -> iseq @@ -627,17 +671,16 @@ rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_bloc * */ static VALUE -iseq_s_compile(int argc, VALUE *argv, VALUE self) +iseqw_s_compile(int argc, VALUE *argv, VALUE self) { VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil; - rb_secure(1); rb_scan_args(argc, argv, "14", &src, &file, &path, &line, &opt); if (NIL_P(file)) file = rb_str_new2("<compiled>"); if (NIL_P(line)) line = INT2FIX(1); - return rb_iseq_compile_with_option(src, file, path, line, 0, opt); + return iseqw_new(rb_iseq_compile_with_option(src, file, path, line, 0, opt)); } /* @@ -661,7 +704,7 @@ iseq_s_compile(int argc, VALUE *argv, VALUE self) * #=> <RubyVM::InstructionSequence:<main>@/tmp/hello.rb> */ static VALUE -iseq_s_compile_file(int argc, VALUE *argv, VALUE self) +iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) { VALUE file, line = INT2FIX(1), opt = Qnil; VALUE parser; @@ -683,9 +726,10 @@ iseq_s_compile_file(int argc, VALUE *argv, VALUE self) rb_io_close(f); make_compile_option(&option, opt); - return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, - rb_realpath_internal(Qnil, file, 1), line, Qfalse, - ISEQ_TYPE_TOP, &option); + + return iseqw_new(rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, + rb_realpath_internal(Qnil, file, 1), line, NULL, + ISEQ_TYPE_TOP, &option)); } /* @@ -721,7 +765,7 @@ iseq_s_compile_file(int argc, VALUE *argv, VALUE self) * ::new, ::compile and ::compile_file. */ static VALUE -iseq_s_compile_option_set(VALUE self, VALUE opt) +iseqw_s_compile_option_set(VALUE self, VALUE opt) { rb_compile_option_t option; rb_secure(1); @@ -739,22 +783,28 @@ iseq_s_compile_option_set(VALUE self, VALUE opt) * For details, see InstructionSequence.compile_option=. */ static VALUE -iseq_s_compile_option_get(VALUE self) +iseqw_s_compile_option_get(VALUE self) { return make_compile_option_value(&COMPILE_OPTION_DEFAULT); } -static rb_iseq_t * -iseq_check(VALUE val) +static const rb_iseq_t * +iseqw_check(VALUE iseqw) { - rb_iseq_t *iseq; - GetISeqPtr(val, iseq); - if (!iseq->location.label) { + const rb_iseq_t *iseq = (rb_iseq_t *)rb_ivar_get(iseqw, iseqw_iseq_key); + + if (!iseq->body->location.label) { rb_raise(rb_eTypeError, "uninitialized InstructionSequence"); } return iseq; } +const rb_iseq_t * +rb_iseqw_to_iseq(VALUE iseqw) +{ + return iseqw_check(iseqw); +} + /* * call-seq: * iseq.eval -> obj @@ -764,10 +814,10 @@ iseq_check(VALUE val) * RubyVM::InstructionSequence.compile("1 + 2").eval #=> 3 */ static VALUE -iseq_eval(VALUE self) +iseqw_eval(VALUE self) { rb_secure(1); - return rb_iseq_eval(self); + return rb_iseq_eval(iseqw_check(self)); } /* @@ -775,17 +825,18 @@ iseq_eval(VALUE self) * sequence, including the #label and #path. */ static VALUE -iseq_inspect(VALUE self) +iseqw_inspect(VALUE self) { - rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - if (!iseq->location.label) { + const rb_iseq_t *iseq = iseqw_check(self); + + if (!iseq->body->location.label) { return rb_sprintf("#<%s: uninitialized>", rb_obj_classname(self)); } - - return rb_sprintf("<%s:%s@%s>", - rb_obj_classname(self), - RSTRING_PTR(iseq->location.label), RSTRING_PTR(iseq->location.path)); + else { + return rb_sprintf("<%s:%s@%s>", + rb_obj_classname(self), + RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); + } } /* @@ -811,12 +862,10 @@ iseq_inspect(VALUE self) * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb') * > iseq.path #=> /tmp/method.rb */ -VALUE -rb_iseq_path(VALUE self) +static VALUE +iseqw_path(VALUE self) { - rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - return iseq->location.path; + return rb_iseq_path(iseqw_check(self)); } /* @@ -835,12 +884,10 @@ rb_iseq_path(VALUE self) * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb') * > iseq.absolute_path #=> /tmp/method.rb */ -VALUE -rb_iseq_absolute_path(VALUE self) +static VALUE +iseqw_absolute_path(VALUE self) { - rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - return iseq->location.absolute_path; + return rb_iseq_absolute_path(iseqw_check(self)); } /* Returns the label of this instruction sequence. @@ -867,11 +914,9 @@ rb_iseq_absolute_path(VALUE self) * > iseq.label #=> <main> */ VALUE -rb_iseq_label(VALUE self) +iseqw_label(VALUE self) { - rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - return iseq->location.label; + return rb_iseq_label(iseqw_check(self)); } /* Returns the base label of this instruction sequence. @@ -894,12 +939,10 @@ rb_iseq_label(VALUE self) * > iseq = RubyVM::InstructionSequence.compile_file('/tmp/method.rb') * > iseq.base_label #=> <main> */ -VALUE -rb_iseq_base_label(VALUE self) +static VALUE +iseqw_base_label(VALUE self) { - rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - return iseq->location.base_label; + return rb_iseq_base_label(iseqw_check(self)); } /* Returns the number of the first source line where the instruction sequence @@ -913,25 +956,9 @@ rb_iseq_base_label(VALUE self) * #=> 1 */ VALUE -rb_iseq_first_lineno(VALUE self) +iseqw_first_lineno(VALUE self) { - const rb_iseq_t *iseq; - GetISeqPtr(self, iseq); - return iseq->location.first_lineno; -} - -VALUE -rb_iseq_method_name(VALUE self) -{ - const rb_iseq_t *iseq, *local_iseq; - GetISeqPtr(self, iseq); - local_iseq = iseq->local_iseq; - if (local_iseq->type == ISEQ_TYPE_METHOD) { - return local_iseq->location.base_label; - } - else { - return Qnil; - } + return rb_iseq_first_lineno(iseqw_check(self)); } static VALUE iseq_data_to_ary(const rb_iseq_t *iseq); @@ -1018,9 +1045,9 @@ static VALUE iseq_data_to_ary(const rb_iseq_t *iseq); * */ static VALUE -iseq_to_a(VALUE self) +iseqw_to_a(VALUE self) { - rb_iseq_t *iseq = iseq_check(self); + const rb_iseq_t *iseq = iseqw_check(self); rb_secure(1); return iseq_data_to_ary(iseq); } @@ -1031,8 +1058,8 @@ iseq_to_a(VALUE self) static struct iseq_line_info_entry * get_line_info(const rb_iseq_t *iseq, size_t pos) { - size_t i = 0, size = iseq->line_info_size; - struct iseq_line_info_entry *table = iseq->line_info_table; + size_t i = 0, size = iseq->body->line_info_size; + struct iseq_line_info_entry *table = iseq->body->line_info_table; const int debug = 0; if (debug) { @@ -1124,9 +1151,9 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE level = *pnop, i; for (i = 0; i < level; i++) { - diseq = diseq->parent_iseq; + diseq = diseq->body->parent_iseq; } - ret = id_to_name(diseq->local_table[diseq->local_size - op], INT2FIX('*')); + ret = id_to_name(diseq->body->local_table[diseq->body->local_size - op], INT2FIX('*')); } else { ret = rb_sprintf("%"PRIuVALUE, op); @@ -1154,9 +1181,9 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, { rb_iseq_t *iseq = (rb_iseq_t *)op; if (iseq) { - ret = iseq->location.label; + ret = iseq->body->location.label; if (child) { - rb_ary_push(child, iseq->self); + rb_ary_push(child, (VALUE)iseq); } } else { @@ -1172,7 +1199,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, break; case TS_IC: - ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->is_entries); + ret = rb_sprintf("<is:%"PRIdPTRDIFF">", (union iseq_inline_storage_entry *)op - iseq->body->is_entries); break; case TS_CALLINFO: @@ -1191,9 +1218,9 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, } if (ci->blockiseq) { if (child) { - rb_ary_push(child, ci->blockiseq->self); + rb_ary_push(child, (VALUE)ci->blockiseq); } - rb_ary_push(ary, rb_sprintf("block:%"PRIsVALUE, ci->blockiseq->location.label)); + rb_ary_push(ary, rb_sprintf("block:%"PRIsVALUE, ci->blockiseq->body->location.label)); } if (ci->flag) { @@ -1313,31 +1340,23 @@ catch_type(int type) } } -/* - * call-seq: - * iseq.disasm -> str - * iseq.disassemble -> str - * - * Returns the instruction sequence as a +String+ in human readable form. - * - * puts RubyVM::InstructionSequence.compile('1 + 2').disasm - * - * Produces: - * - * == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== - * 0000 trace 1 ( 1) - * 0002 putobject 1 - * 0004 putobject 2 - * 0006 opt_plus <ic:1> - * 0008 leave - */ +static VALUE +iseq_inspect(const rb_iseq_t *iseq) +{ + if (!iseq->body->location.label) { + return rb_sprintf("#<ISeq: uninitialized>"); + } + else { + return rb_sprintf("#<ISeq:%s@%s>", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); + } +} + VALUE -rb_iseq_disasm(VALUE self) +rb_iseq_disasm(const rb_iseq_t *iseq) { - rb_iseq_t *iseq = iseq_check(self); /* TODO: rename to iseq */ VALUE *code; VALUE str = rb_str_new(0, 0); - VALUE child = rb_ary_new(); + VALUE child = rb_ary_tmp_new(3); unsigned int size; int i; long l; @@ -1347,11 +1366,11 @@ rb_iseq_disasm(VALUE self) rb_secure(1); - size = iseq->iseq_size; + size = iseq->body->iseq_size; rb_str_cat2(str, "== disasm: "); - rb_str_concat(str, iseq_inspect(iseq->self)); + rb_str_concat(str, iseq_inspect(iseq)); if ((l = RSTRING_LEN(str)) < header_minlen) { rb_str_resize(str, header_minlen); memset(RSTRING_PTR(str) + l, '=', header_minlen - l); @@ -1359,11 +1378,11 @@ rb_iseq_disasm(VALUE self) rb_str_cat2(str, "\n"); /* show catch table information */ - if (iseq->catch_table) { + if (iseq->body->catch_table) { rb_str_cat2(str, "== catch table\n"); } - if (iseq->catch_table) for (i = 0; i < iseq->catch_table->size; i++) { - struct iseq_catch_table_entry *entry = &iseq->catch_table->entries[i]; + if (iseq->body->catch_table) for (i = 0; i < iseq->body->catch_table->size; i++) { + struct iseq_catch_table_entry *entry = &iseq->body->catch_table->entries[i]; rb_str_catf(str, "| catch type: %-6s st: %04d ed: %04d sp: %04d cont: %04d\n", catch_type((int)entry->type), (int)entry->start, @@ -1372,51 +1391,51 @@ rb_iseq_disasm(VALUE self) rb_str_concat(str, rb_iseq_disasm(entry->iseq)); } } - if (iseq->catch_table) { + if (iseq->body->catch_table) { rb_str_cat2(str, "|-------------------------------------" "-----------------------------------\n"); } /* show local table information */ - tbl = iseq->local_table; + tbl = iseq->body->local_table; if (tbl) { rb_str_catf(str, "local table (size: %d, argc: %d " "[opts: %d, rest: %d, post: %d, block: %d, kw: %d@%d, kwrest: %d])\n", - iseq->local_size, - iseq->param.lead_num, - iseq->param.opt_num, - iseq->param.flags.has_rest ? iseq->param.rest_start : -1, - iseq->param.post_num, - iseq->param.flags.has_block ? iseq->param.block_start : -1, - iseq->param.flags.has_kw ? iseq->param.keyword->num : -1, - iseq->param.flags.has_kw ? iseq->param.keyword->required_num : -1, - iseq->param.flags.has_kwrest ? iseq->param.keyword->rest_start : -1); - - for (i = 0; i < iseq->local_table_size; i++) { + iseq->body->local_size, + iseq->body->param.lead_num, + iseq->body->param.opt_num, + iseq->body->param.flags.has_rest ? iseq->body->param.rest_start : -1, + iseq->body->param.post_num, + iseq->body->param.flags.has_block ? iseq->body->param.block_start : -1, + iseq->body->param.flags.has_kw ? iseq->body->param.keyword->num : -1, + iseq->body->param.flags.has_kw ? iseq->body->param.keyword->required_num : -1, + iseq->body->param.flags.has_kwrest ? iseq->body->param.keyword->rest_start : -1); + + for (i = 0; i < iseq->body->local_table_size; i++) { long width; VALUE name = id_to_name(tbl[i], 0); char argi[0x100] = ""; char opti[0x100] = ""; - if (iseq->param.flags.has_opt) { - int argc = iseq->param.lead_num; - int opts = iseq->param.opt_num; + if (iseq->body->param.flags.has_opt) { + int argc = iseq->body->param.lead_num; + int opts = iseq->body->param.opt_num; if (i >= argc && i < argc + opts) { snprintf(opti, sizeof(opti), "Opt=%"PRIdVALUE, - iseq->param.opt_table[i - argc]); + iseq->body->param.opt_table[i - argc]); } } snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post block */ - iseq->param.lead_num > i ? "Arg" : "", + iseq->body->param.lead_num > i ? "Arg" : "", opti, - (iseq->param.flags.has_rest && iseq->param.rest_start == i) ? "Rest" : "", - (iseq->param.flags.has_post && iseq->param.post_start <= i && i < iseq->param.post_start + iseq->param.post_num) ? "Post" : "", - (iseq->param.flags.has_block && iseq->param.block_start == i) ? "Block" : ""); + (iseq->body->param.flags.has_rest && iseq->body->param.rest_start == i) ? "Rest" : "", + (iseq->body->param.flags.has_post && iseq->body->param.post_start <= i && i < iseq->body->param.post_start + iseq->body->param.post_num) ? "Post" : "", + (iseq->body->param.flags.has_block && iseq->body->param.block_start == i) ? "Block" : ""); - rb_str_catf(str, "[%2d] ", iseq->local_size - i); + rb_str_catf(str, "[%2d] ", iseq->body->local_size - i); width = RSTRING_LEN(str) + 11; if (name) rb_str_append(str, name); @@ -1436,13 +1455,37 @@ rb_iseq_disasm(VALUE self) for (i = 0; i < RARRAY_LEN(child); i++) { VALUE isv = rb_ary_entry(child, i); - rb_str_concat(str, rb_iseq_disasm(isv)); + rb_str_concat(str, rb_iseq_disasm((rb_iseq_t *)isv)); } return str; } /* + * call-seq: + * iseq.disasm -> str + * iseq.disassemble -> str + * + * Returns the instruction sequence as a +String+ in human readable form. + * + * puts RubyVM::InstructionSequence.compile('1 + 2').disasm + * + * Produces: + * + * == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== + * 0000 trace 1 ( 1) + * 0002 putobject 1 + * 0004 putobject 2 + * 0006 opt_plus <ic:1> + * 0008 leave + */ +static VALUE +iseqw_disasm(VALUE self) +{ + return rb_iseq_disasm(iseqw_check(self)); +} + +/* * Returns the instruction sequence containing the given proc or method. * * For example, using irb: @@ -1478,10 +1521,9 @@ rb_iseq_disasm(VALUE self) * > #=> #<RubyVM::InstructionSequence:0x007fb73d7caf78> */ static VALUE -iseq_s_of(VALUE klass, VALUE body) +iseqw_s_of(VALUE klass, VALUE body) { - VALUE ret = Qnil; - const rb_iseq_t *iseq; + const rb_iseq_t *iseq = NULL; rb_secure(1); @@ -1489,14 +1531,16 @@ iseq_s_of(VALUE klass, VALUE body) rb_proc_t *proc; GetProcPtr(body, proc); iseq = proc->block.iseq; - if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { - ret = iseq->self; + + if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) { + iseq = NULL; } } - else if ((iseq = rb_method_iseq(body)) != 0) { - ret = iseq->self; + else { + iseq = rb_method_iseq(body); } - return ret; + + return iseq ? iseqw_new(iseq) : Qnil; } /* @@ -1551,12 +1595,11 @@ iseq_s_of(VALUE klass, VALUE body) * 0012 leave * */ - static VALUE -iseq_s_disasm(VALUE klass, VALUE body) +iseqw_s_disasm(VALUE klass, VALUE body) { - VALUE iseqval = iseq_s_of(klass, body); - return NIL_P(iseqval) ? Qnil : rb_iseq_disasm(iseqval); + VALUE iseqw = iseqw_s_of(klass, body); + return NIL_P(iseqw) ? Qnil : rb_iseq_disasm(iseqw_check(iseqw)); } const char * @@ -1657,7 +1700,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) } /* type */ - switch (iseq->type) { + switch (iseq->body->type) { case ISEQ_TYPE_TOP: type = sym_top; break; case ISEQ_TYPE_METHOD: type = sym_method; break; case ISEQ_TYPE_BLOCK: type = sym_block; break; @@ -1671,14 +1714,14 @@ iseq_data_to_ary(const rb_iseq_t *iseq) }; /* locals */ - for (i=0; i<iseq->local_table_size; i++) { - ID lid = iseq->local_table[i]; + for (i=0; i<iseq->body->local_table_size; i++) { + ID lid = iseq->body->local_table[i]; if (lid) { if (rb_id2str(lid)) { rb_ary_push(locals, ID2SYM(lid)); } else { /* hidden variable from id_internal() */ - rb_ary_push(locals, ULONG2NUM(iseq->local_table_size-i+1)); + rb_ary_push(locals, ULONG2NUM(iseq->body->local_table_size-i+1)); } } else { @@ -1690,49 +1733,49 @@ iseq_data_to_ary(const rb_iseq_t *iseq) { int j; - if (iseq->param.flags.has_opt) { - int len = iseq->param.opt_num + 1; + if (iseq->body->param.flags.has_opt) { + int len = iseq->body->param.opt_num + 1; VALUE arg_opt_labels = rb_ary_new2(len); for (j = 0; j < len; j++) { - VALUE l = register_label(labels_table, iseq->param.opt_table[j]); + VALUE l = register_label(labels_table, iseq->body->param.opt_table[j]); rb_ary_push(arg_opt_labels, l); } rb_hash_aset(params, ID2SYM(rb_intern("opt")), arg_opt_labels); } /* commit */ - if (iseq->param.flags.has_lead) rb_hash_aset(params, ID2SYM(rb_intern("lead_num")), INT2FIX(iseq->param.lead_num)); - if (iseq->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_num")), INT2FIX(iseq->param.post_num)); - if (iseq->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_start")), INT2FIX(iseq->param.post_start)); - if (iseq->param.flags.has_rest) rb_hash_aset(params, ID2SYM(rb_intern("rest_start")), INT2FIX(iseq->param.rest_start)); - if (iseq->param.flags.has_block) rb_hash_aset(params, ID2SYM(rb_intern("block_start")), INT2FIX(iseq->param.block_start)); - if (iseq->param.flags.has_kw) { + if (iseq->body->param.flags.has_lead) rb_hash_aset(params, ID2SYM(rb_intern("lead_num")), INT2FIX(iseq->body->param.lead_num)); + if (iseq->body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_num")), INT2FIX(iseq->body->param.post_num)); + if (iseq->body->param.flags.has_post) rb_hash_aset(params, ID2SYM(rb_intern("post_start")), INT2FIX(iseq->body->param.post_start)); + if (iseq->body->param.flags.has_rest) rb_hash_aset(params, ID2SYM(rb_intern("rest_start")), INT2FIX(iseq->body->param.rest_start)); + if (iseq->body->param.flags.has_block) rb_hash_aset(params, ID2SYM(rb_intern("block_start")), INT2FIX(iseq->body->param.block_start)); + if (iseq->body->param.flags.has_kw) { VALUE keywords = rb_ary_new(); int i, j; - for (i=0; i<iseq->param.keyword->required_num; i++) { - rb_ary_push(keywords, ID2SYM(iseq->param.keyword->table[i])); + for (i=0; i<iseq->body->param.keyword->required_num; i++) { + rb_ary_push(keywords, ID2SYM(iseq->body->param.keyword->table[i])); } - for (j=0; i<iseq->param.keyword->num; i++, j++) { - VALUE key = rb_ary_new_from_args(1, ID2SYM(iseq->param.keyword->table[i])); - if (iseq->param.keyword->default_values[j] != Qundef) { - rb_ary_push(key, iseq->param.keyword->default_values[j]); + for (j=0; i<iseq->body->param.keyword->num; i++, j++) { + VALUE key = rb_ary_new_from_args(1, ID2SYM(iseq->body->param.keyword->table[i])); + if (iseq->body->param.keyword->default_values[j] != Qundef) { + rb_ary_push(key, iseq->body->param.keyword->default_values[j]); } rb_ary_push(keywords, key); } rb_hash_aset(params, ID2SYM(rb_intern("kwbits")), - INT2FIX(iseq->param.keyword->bits_start)); + INT2FIX(iseq->body->param.keyword->bits_start)); rb_hash_aset(params, ID2SYM(rb_intern("keyword")), keywords); } - if (iseq->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(iseq->param.keyword->rest_start)); - if (iseq->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue); + if (iseq->body->param.flags.has_kwrest) rb_hash_aset(params, ID2SYM(rb_intern("kwrest")), INT2FIX(iseq->body->param.keyword->rest_start)); + if (iseq->body->param.flags.ambiguous_param0) rb_hash_aset(params, ID2SYM(rb_intern("ambiguous_param0")), Qtrue); } /* body */ iseq_original = rb_iseq_original_iseq((rb_iseq_t *)iseq); - for (seq = iseq_original; seq < iseq_original + iseq->iseq_size; ) { + 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; @@ -1774,7 +1817,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq) case TS_IC: { union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)*seq; - rb_ary_push(ary, INT2FIX(is - iseq->is_entries)); + rb_ary_push(ary, INT2FIX(is - iseq->body->is_entries)); } break; case TS_CALLINFO: @@ -1844,14 +1887,12 @@ iseq_data_to_ary(const rb_iseq_t *iseq) nbody = body; /* exception */ - if (iseq->catch_table) for (i=0; i<iseq->catch_table->size; i++) { + if (iseq->body->catch_table) for (i=0; i<iseq->body->catch_table->size; i++) { VALUE ary = rb_ary_new(); - struct iseq_catch_table_entry *entry = &iseq->catch_table->entries[i]; + struct iseq_catch_table_entry *entry = &iseq->body->catch_table->entries[i]; rb_ary_push(ary, exception_type2symbol(entry->type)); if (entry->iseq) { - rb_iseq_t *eiseq; - GetISeqPtr(entry->iseq, eiseq); - rb_ary_push(ary, iseq_data_to_ary(eiseq)); + rb_ary_push(ary, iseq_data_to_ary(entry->iseq)); } else { rb_ary_push(ary, Qnil); @@ -1875,8 +1916,8 @@ iseq_data_to_ary(const rb_iseq_t *iseq) rb_ary_push(body, (VALUE)label); } - if (ti < iseq->line_info_size && iseq->line_info_table[ti].position == pos) { - line = iseq->line_info_table[ti].line_no; + if (ti < iseq->body->line_info_size && iseq->body->line_info_table[ti].position == pos) { + line = iseq->body->line_info_table[ti].line_no; rb_ary_push(body, INT2FIX(line)); ti++; } @@ -1888,9 +1929,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq) st_free_table(labels_table); - rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->param.size)); - rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->local_size)); - rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->stack_max)); + rb_hash_aset(misc, ID2SYM(rb_intern("arg_size")), INT2FIX(iseq->body->param.size)); + rb_hash_aset(misc, ID2SYM(rb_intern("local_size")), INT2FIX(iseq->body->local_size)); + rb_hash_aset(misc, ID2SYM(rb_intern("stack_max")), INT2FIX(iseq->body->stack_max)); /* TODO: compatibility issue */ /* @@ -1903,10 +1944,10 @@ iseq_data_to_ary(const rb_iseq_t *iseq) rb_ary_push(val, INT2FIX(ISEQ_MINOR_VERSION)); /* minor */ rb_ary_push(val, INT2FIX(1)); rb_ary_push(val, misc); - rb_ary_push(val, iseq->location.label); - rb_ary_push(val, iseq->location.path); - rb_ary_push(val, iseq->location.absolute_path); - rb_ary_push(val, iseq->location.first_lineno); + rb_ary_push(val, iseq->body->location.label); + rb_ary_push(val, iseq->body->location.path); + rb_ary_push(val, iseq->body->location.absolute_path); + rb_ary_push(val, iseq->body->location.first_lineno); rb_ary_push(val, type); rb_ary_push(val, locals); rb_ary_push(val, params); @@ -1919,10 +1960,10 @@ VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) { int i, r; - VALUE a, args = rb_ary_new2(iseq->param.size); + VALUE a, args = rb_ary_new2(iseq->body->param.size); ID req, opt, rest, block, key, keyrest; #define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type)) -#define PARAM_ID(i) iseq->local_table[(i)] +#define PARAM_ID(i) iseq->body->local_table[(i)] #define PARAM(i, type) ( \ PARAM_TYPE(type), \ rb_id2str(PARAM_ID(i)) ? \ @@ -1932,18 +1973,18 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) CONST_ID(req, "req"); CONST_ID(opt, "opt"); if (is_proc) { - for (i = 0; i < iseq->param.lead_num; i++) { + for (i = 0; i < iseq->body->param.lead_num; i++) { PARAM_TYPE(opt); rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil); rb_ary_push(args, a); } } else { - for (i = 0; i < iseq->param.lead_num; i++) { + for (i = 0; i < iseq->body->param.lead_num; i++) { rb_ary_push(args, PARAM(i, req)); } } - r = iseq->param.lead_num + iseq->param.opt_num; + r = iseq->body->param.lead_num + iseq->body->param.opt_num; for (; i < r; i++) { PARAM_TYPE(opt); if (rb_id2str(PARAM_ID(i))) { @@ -1951,52 +1992,52 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) } rb_ary_push(args, a); } - if (iseq->param.flags.has_rest) { + if (iseq->body->param.flags.has_rest) { CONST_ID(rest, "rest"); - rb_ary_push(args, PARAM(iseq->param.rest_start, rest)); + rb_ary_push(args, PARAM(iseq->body->param.rest_start, rest)); } - r = iseq->param.post_start + iseq->param.post_num; + r = iseq->body->param.post_start + iseq->body->param.post_num; if (is_proc) { - for (i = iseq->param.post_start; i < r; i++) { + for (i = iseq->body->param.post_start; i < r; i++) { PARAM_TYPE(opt); rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil); rb_ary_push(args, a); } } else { - for (i = iseq->param.post_start; i < r; i++) { + for (i = iseq->body->param.post_start; i < r; i++) { rb_ary_push(args, PARAM(i, req)); } } - if (iseq->param.flags.has_kw) { + if (iseq->body->param.flags.has_kw) { i = 0; - if (iseq->param.keyword->required_num > 0) { + if (iseq->body->param.keyword->required_num > 0) { ID keyreq; CONST_ID(keyreq, "keyreq"); - for (; i < iseq->param.keyword->required_num; i++) { + for (; i < iseq->body->param.keyword->required_num; i++) { PARAM_TYPE(keyreq); - if (rb_id2str(iseq->param.keyword->table[i])) { - rb_ary_push(a, ID2SYM(iseq->param.keyword->table[i])); + if (rb_id2str(iseq->body->param.keyword->table[i])) { + rb_ary_push(a, ID2SYM(iseq->body->param.keyword->table[i])); } rb_ary_push(args, a); } } CONST_ID(key, "key"); - for (; i < iseq->param.keyword->num; i++) { + for (; i < iseq->body->param.keyword->num; i++) { PARAM_TYPE(key); - if (rb_id2str(iseq->param.keyword->table[i])) { - rb_ary_push(a, ID2SYM(iseq->param.keyword->table[i])); + if (rb_id2str(iseq->body->param.keyword->table[i])) { + rb_ary_push(a, ID2SYM(iseq->body->param.keyword->table[i])); } rb_ary_push(args, a); } } - if (iseq->param.flags.has_kwrest) { + if (iseq->body->param.flags.has_kwrest) { CONST_ID(keyrest, "keyrest"); - rb_ary_push(args, PARAM(iseq->param.keyword->rest_start, keyrest)); + rb_ary_push(args, PARAM(iseq->body->param.keyword->rest_start, keyrest)); } - if (iseq->param.flags.has_block) { + if (iseq->body->param.flags.has_block) { CONST_ID(block, "block"); - rb_ary_push(args, PARAM(iseq->param.block_start, block)); + rb_ary_push(args, PARAM(iseq->body->param.block_start, block)); } return args; } @@ -2041,85 +2082,22 @@ rb_iseq_defined_string(enum defined_type type) return str; } -/* ruby2cext */ - -VALUE -rb_iseq_build_for_ruby2cext( - const rb_iseq_t *iseq_template, - const rb_insn_func_t *func, - const struct iseq_line_info_entry *line_info_table, - const char **local_table, - const VALUE *arg_opt_table, - const struct iseq_catch_table_entry *catch_table, - const char *name, - const char *path, - const unsigned short first_lineno) -{ - unsigned long i; - VALUE iseqval = iseq_alloc(rb_cISeq); - rb_iseq_t *iseq; - GetISeqPtr(iseqval, iseq); - - /* copy iseq */ - MEMCPY(iseq, iseq_template, rb_iseq_t, 1); /* TODO: write barrier, *iseq = *iseq_template; */ - RB_OBJ_WRITE(iseq->self, &iseq->location.label, rb_str_new2(name)); - RB_OBJ_WRITE(iseq->self, &iseq->location.path, rb_str_new2(path)); - iseq->location.first_lineno = UINT2NUM(first_lineno); - RB_OBJ_WRITE(iseq->self, &iseq->mark_ary, 0); - iseq->self = iseqval; - - iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size); - - for (i=0; i<iseq->iseq_size; i+=2) { - iseq->iseq_encoded[i] = BIN(opt_call_c_function); - iseq->iseq_encoded[i+1] = (VALUE)func; - } - - rb_iseq_translate_threaded_code(iseq); - -#define ALLOC_AND_COPY(dst, src, type, size) do { \ - if (size) { \ - (dst) = ALLOC_N(type, (size)); \ - MEMCPY((dst), (src), type, (size)); \ - } \ -} while (0) - - ALLOC_AND_COPY(iseq->line_info_table, line_info_table, - struct iseq_line_info_entry, iseq->line_info_size); - - /* - * FIXME: probably broken, but this function is probably unused - * and should be removed - */ - if (iseq->catch_table) { - MEMCPY(&iseq->catch_table->entries, catch_table, - struct iseq_catch_table_entry, iseq->catch_table->size); - } - - ALLOC_AND_COPY(iseq->param.opt_table, arg_opt_table, VALUE, iseq->param.opt_num + 1); - - set_relation(iseq, 0); - - return iseqval; -} - /* Experimental tracing support: trace(line) -> trace(specified_line) * MRI Specific. */ int -rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data) +rb_iseqw_line_trace_each(VALUE iseqw, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data) { int trace_num = 0; unsigned int pos; size_t insn; - rb_iseq_t *iseq; + const rb_iseq_t *iseq = iseqw_check(iseqw); int cont = 1; VALUE *iseq_original; - GetISeqPtr(iseqval, iseq); iseq_original = rb_iseq_original_iseq(iseq); - for (pos = 0; cont && pos < iseq->iseq_size; pos += insn_len(insn)) { + for (pos = 0; cont && pos < iseq->body->iseq_size; pos += insn_len(insn)) { insn = iseq_original[pos]; if (insn == BIN(trace)) { @@ -2136,7 +2114,7 @@ rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *ev /* printf("line: %d\n", line); */ cont = (*func)(line, &events, data); if (current_events != events) { - iseq_original[pos+1] = iseq->iseq_encoded[pos+1] = + iseq_original[pos+1] = iseq->body->iseq_encoded[pos+1] = (VALUE)(current_events | (events & RUBY_EVENT_SPECIFIED_LINE)); } } @@ -2160,10 +2138,10 @@ collect_trace(int line, rb_event_flag_t *events_ptr, void *ptr) * Returns all +specified_line+ events. */ VALUE -rb_iseq_line_trace_all(VALUE iseqval) +rb_iseqw_line_trace_all(VALUE iseqw) { VALUE result = rb_ary_new(); - rb_iseq_line_trace_each(iseqval, collect_trace, (void *)result); + rb_iseqw_line_trace_each(iseqw, collect_trace, (void *)result); return result; } @@ -2207,7 +2185,7 @@ line_trace_specify(int line, rb_event_flag_t *events_ptr, void *ptr) * If +pos+ is a negative integer a TypeError exception is raised. */ VALUE -rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set) +rb_iseqw_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set) { struct set_specifc_data data; @@ -2222,7 +2200,7 @@ rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set) rb_raise(rb_eTypeError, "`set' should be true/false"); } - rb_iseq_line_trace_each(iseqval, line_trace_specify, (void *)&data); + rb_iseqw_line_trace_each(iseqval, line_trace_specify, (void *)&data); if (data.prev == 0) { rb_raise(rb_eTypeError, "`pos' is out of range."); @@ -2255,45 +2233,45 @@ Init_ISeq(void) { /* declare ::RubyVM::InstructionSequence */ rb_cISeq = rb_define_class_under(rb_cRubyVM, "InstructionSequence", rb_cObject); - rb_define_alloc_func(rb_cISeq, iseq_alloc); - rb_define_method(rb_cISeq, "inspect", iseq_inspect, 0); - rb_define_method(rb_cISeq, "disasm", rb_iseq_disasm, 0); - rb_define_method(rb_cISeq, "disassemble", rb_iseq_disasm, 0); - rb_define_method(rb_cISeq, "to_a", iseq_to_a, 0); - rb_define_method(rb_cISeq, "eval", iseq_eval, 0); + rb_define_method(rb_cISeq, "inspect", iseqw_inspect, 0); + rb_define_method(rb_cISeq, "disasm", iseqw_disasm, 0); + rb_define_method(rb_cISeq, "disassemble", iseqw_disasm, 0); + rb_define_method(rb_cISeq, "to_a", iseqw_to_a, 0); + rb_define_method(rb_cISeq, "eval", iseqw_eval, 0); /* location APIs */ - rb_define_method(rb_cISeq, "path", rb_iseq_path, 0); - rb_define_method(rb_cISeq, "absolute_path", rb_iseq_absolute_path, 0); - rb_define_method(rb_cISeq, "label", rb_iseq_label, 0); - rb_define_method(rb_cISeq, "base_label", rb_iseq_base_label, 0); - rb_define_method(rb_cISeq, "first_lineno", rb_iseq_first_lineno, 0); + rb_define_method(rb_cISeq, "path", iseqw_path, 0); + rb_define_method(rb_cISeq, "absolute_path", iseqw_absolute_path, 0); + rb_define_method(rb_cISeq, "label", iseqw_label, 0); + rb_define_method(rb_cISeq, "base_label", iseqw_base_label, 0); + rb_define_method(rb_cISeq, "first_lineno", iseqw_first_lineno, 0); #if 0 /* Now, it is experimental. No discussions, no tests. */ /* They can be used from C level. Please give us feedback. */ - rb_define_method(rb_cISeq, "line_trace_all", rb_iseq_line_trace_all, 0); - rb_define_method(rb_cISeq, "line_trace_specify", rb_iseq_line_trace_specify, 2); + rb_define_method(rb_cISeq, "line_trace_all", rb_iseqw_line_trace_all, 0); + rb_define_method(rb_cISeq, "line_trace_specify", rb_iseqw_line_trace_specify, 2); #else - (void)rb_iseq_line_trace_all; - (void)rb_iseq_line_trace_specify; + (void)rb_iseqw_line_trace_all; + (void)rb_iseqw_line_trace_specify; #endif #if 0 /* TBD */ - rb_define_private_method(rb_cISeq, "marshal_dump", iseq_marshal_dump, 0); - rb_define_private_method(rb_cISeq, "marshal_load", iseq_marshal_load, 1); + rb_define_private_method(rb_cISeq, "marshal_dump", iseqw_marshal_dump, 0); + rb_define_private_method(rb_cISeq, "marshal_load", iseqw_marshal_load, 1); #endif - /* disable this feature because there is no verifier. */ /* rb_define_singleton_method(rb_cISeq, "load", iseq_s_load, -1); */ (void)iseq_s_load; - rb_define_singleton_method(rb_cISeq, "compile", iseq_s_compile, -1); - rb_define_singleton_method(rb_cISeq, "new", iseq_s_compile, -1); - rb_define_singleton_method(rb_cISeq, "compile_file", iseq_s_compile_file, -1); - rb_define_singleton_method(rb_cISeq, "compile_option", iseq_s_compile_option_get, 0); - rb_define_singleton_method(rb_cISeq, "compile_option=", iseq_s_compile_option_set, 1); - rb_define_singleton_method(rb_cISeq, "disasm", iseq_s_disasm, 1); - rb_define_singleton_method(rb_cISeq, "disassemble", iseq_s_disasm, 1); - rb_define_singleton_method(rb_cISeq, "of", iseq_s_of, 1); + rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1); + rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1); + rb_define_singleton_method(rb_cISeq, "compile_file", iseqw_s_compile_file, -1); + rb_define_singleton_method(rb_cISeq, "compile_option", iseqw_s_compile_option_get, 0); + rb_define_singleton_method(rb_cISeq, "compile_option=", iseqw_s_compile_option_set, 1); + rb_define_singleton_method(rb_cISeq, "disasm", iseqw_s_disasm, 1); + rb_define_singleton_method(rb_cISeq, "disassemble", iseqw_s_disasm, 1); + rb_define_singleton_method(rb_cISeq, "of", iseqw_s_of, 1); + + iseqw_iseq_key = rb_intern("T_IMEMO/iseq"); } @@ -15,12 +15,12 @@ RUBY_SYMBOL_EXPORT_BEGIN /* compile.c */ -VALUE rb_iseq_compile_node(VALUE self, NODE *node); +VALUE rb_iseq_compile_node(rb_iseq_t *iseq, NODE *node); int rb_iseq_translate_threaded_code(rb_iseq_t *iseq); -VALUE *rb_iseq_original_iseq(rb_iseq_t *iseq); -VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, - VALUE locals, VALUE args, - VALUE exception, VALUE body); +VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq); +void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, + VALUE locals, VALUE args, + VALUE exception, VALUE body); /* iseq.c */ void rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj); @@ -29,9 +29,18 @@ VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc); struct st_table *ruby_insn_make_insn_table(void); unsigned int rb_iseq_line_no(const rb_iseq_t *iseq, size_t pos); -int rb_iseq_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data); -VALUE rb_iseq_line_trace_all(VALUE iseqval); -VALUE rb_iseq_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set); +int rb_iseqw_line_trace_each(VALUE iseqval, int (*func)(int line, rb_event_flag_t *events_ptr, void *d), void *data); +VALUE rb_iseqw_line_trace_all(VALUE iseqval); +VALUE rb_iseqw_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set); +VALUE rb_iseqw_new(const rb_iseq_t *iseq); +const rb_iseq_t *rb_iseqw_to_iseq(VALUE iseqw); + +VALUE rb_iseq_path(const rb_iseq_t *iseq); +VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq); +VALUE rb_iseq_label(const rb_iseq_t *iseq); +VALUE rb_iseq_base_label(const rb_iseq_t *iseq); +VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq); +VALUE rb_iseq_method_name(const rb_iseq_t *iseq); /* proc.c */ const rb_iseq_t *rb_method_iseq(VALUE body); @@ -63,7 +72,7 @@ struct iseq_catch_table_entry { CATCH_TYPE_REDO = INT2FIX(5), CATCH_TYPE_NEXT = INT2FIX(6) } type; - VALUE iseq; + const rb_iseq_t *iseq; unsigned int start; unsigned int end; unsigned int cont; @@ -109,7 +118,7 @@ struct iseq_compile_data { struct iseq_label_data *start_label; struct iseq_label_data *end_label; struct iseq_label_data *redo_label; - VALUE current_block; + const rb_iseq_t *current_block; VALUE ensure_node; VALUE for_iseq; struct iseq_compile_data_ensure_node_stack *ensure_node_stack; @@ -602,12 +602,12 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap) state = EXEC_TAG(); if (state == 0) { NODE *node; - VALUE iseq; + rb_iseq_t *iseq; th->mild_compile_error++; node = (NODE *)rb_load_file_str(fname); loaded = TRUE; - iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), Qfalse); + iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), NULL); th->mild_compile_error--; rb_iseq_eval(iseq); } @@ -121,7 +121,7 @@ typedef enum { typedef struct rb_iseq_struct rb_iseq_t; typedef struct rb_method_iseq_struct { - const rb_iseq_t * const iseqptr; /* should be separated from iseqval */ + const rb_iseq_t * const iseqptr; /* should be separated from iseqval */ rb_cref_t * const cref; /* shoudl be marked */ } rb_method_iseq_t; /* check rb_add_method_iseq() when modify the fields */ @@ -174,7 +174,7 @@ typedef struct rb_method_definition_struct { UNDEFINED_METHOD_ENTRY_P((def)->body.refined.orig_me)) void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi); -void rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_visibility_t visi); +void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi); void rb_add_refined_method_entry(VALUE refined_class, ID mid); rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi); @@ -369,8 +369,8 @@ get_local_variable_ptr(VALUE envval, ID lid) iseq = env->block.iseq; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { - for (i=0; i<iseq->local_table_size; i++) { - if (iseq->local_table[i] == lid) { + for (i=0; i<iseq->body->local_table_size; i++) { + if (iseq->body->local_table[i] == lid) { return &env->env[i]; } } @@ -735,7 +735,7 @@ proc_call(int argc, VALUE *argv, VALUE procval) GetProcPtr(procval, proc); iseq = proc->block.iseq; - if (RUBY_VM_IFUNC_P(iseq) || iseq->param.flags.has_block) { + if (RUBY_VM_IFUNC_P(iseq) || iseq->body->param.flags.has_block) { if (rb_block_given_p()) { rb_proc_t *passed_proc; RB_GC_GUARD(passed_procval) = rb_block_proc(); @@ -847,11 +847,11 @@ proc_arity(VALUE self) static inline int rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max) { - *max = iseq->param.flags.has_rest == FALSE ? - iseq->param.lead_num + iseq->param.opt_num + iseq->param.post_num + - (iseq->param.flags.has_kw == TRUE || iseq->param.flags.has_kwrest == TRUE) + *max = iseq->body->param.flags.has_rest == FALSE ? + iseq->body->param.lead_num + iseq->body->param.opt_num + iseq->body->param.post_num + + (iseq->body->param.flags.has_kw == TRUE || iseq->body->param.flags.has_kwrest == TRUE) : UNLIMITED_ARGUMENTS; - return iseq->param.lead_num + iseq->param.post_num + (iseq->param.flags.has_kw && iseq->param.keyword->required_num > 0); + return iseq->body->param.lead_num + iseq->body->param.post_num + (iseq->body->param.flags.has_kw && iseq->body->param.keyword->required_num > 0); } static int @@ -950,9 +950,9 @@ iseq_location(const rb_iseq_t *iseq) VALUE loc[2]; if (!iseq) return Qnil; - loc[0] = iseq->location.path; - if (iseq->line_info_table) { - loc[1] = rb_iseq_first_lineno(iseq->self); + loc[0] = iseq->body->location.path; + if (iseq->body->line_info_table) { + loc[1] = rb_iseq_first_lineno(iseq); } else { loc[1] = Qnil; @@ -1066,11 +1066,11 @@ proc_to_s(VALUE self) if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int first_lineno = 0; - if (iseq->line_info_table) { - first_lineno = FIX2INT(rb_iseq_first_lineno(iseq->self)); + if (iseq->body->line_info_table) { + first_lineno = FIX2INT(rb_iseq_first_lineno(iseq)); } str = rb_sprintf("#<%s:%p@%"PRIsVALUE":%d%s>", cname, (void *)self, - iseq->location.path, first_lineno, is_lambda); + iseq->body->location.path, first_lineno, is_lambda); } else { str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq, @@ -2558,8 +2558,8 @@ proc_binding(VALUE self) } if (iseq) { - bind->path = iseq->location.path; - bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq->self)); + bind->path = iseq->body->location.path; + bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq)); } else { bind->path = Qnil; @@ -1305,7 +1305,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) { NODE *tree = 0; VALUE parser; - VALUE iseq; + const rb_iseq_t *iseq; rb_encoding *enc, *lenc; const char *s; char fbuf[MAXPATHLEN]; @@ -1544,7 +1544,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) }); if (opt->dump & DUMP_BIT(insns)) { - rb_io_write(rb_stdout, rb_iseq_disasm(iseq)); + rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq)); rb_io_flush(rb_stdout); return Qtrue; } @@ -1555,7 +1555,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) rb_set_safe_level(opt->safe_level); - return iseq; + return (VALUE)iseq; } struct load_file_arg { @@ -19,8 +19,8 @@ enum { AREF_HASH_THRESHOLD = 10 }; -VALUE rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func); -VALUE rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func); +const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func); +const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func); VALUE rb_cStruct; static ID id_members, id_back_members; @@ -287,18 +287,18 @@ static void define_aref_method(VALUE nstr, VALUE name, VALUE off) { rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_thread_t *, rb_control_frame_t *); - VALUE iseqval = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref); + const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref); - rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, METHOD_VISI_PUBLIC); + rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC); } static void define_aset_method(VALUE nstr, VALUE name, VALUE off) { rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_thread_t *, rb_control_frame_t *); - VALUE iseqval = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset); + const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset); - rb_add_method_iseq(nstr, SYM2ID(name), iseqval, NULL, METHOD_VISI_PUBLIC); + rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC); } static VALUE @@ -5226,7 +5226,7 @@ rb_check_deadlock(rb_vm_t *vm) static void update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass) { - VALUE coverage = GET_THREAD()->cfp->iseq->coverage; + VALUE coverage = GET_THREAD()->cfp->iseq->body->coverage; if (coverage && RBASIC(coverage)->klass == 0) { long line = rb_sourceline() - 1; long count; @@ -247,12 +247,9 @@ vm_stat(int argc, VALUE *argv, VALUE self) /* control stack frame */ static void -vm_set_top_stack(rb_thread_t *th, VALUE iseqval) +vm_set_top_stack(rb_thread_t *th, const rb_iseq_t *iseq) { - rb_iseq_t *iseq; - GetISeqPtr(iseqval, iseq); - - if (iseq->type != ISEQ_TYPE_TOP) { + if (iseq->body->type != ISEQ_TYPE_TOP) { rb_raise(rb_eTypeError, "Not a toplevel InstructionSequence"); } @@ -260,37 +257,33 @@ vm_set_top_stack(rb_thread_t *th, VALUE iseqval) vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH, th->top_self, VM_ENVVAL_BLOCK_PTR(0), (VALUE)vm_cref_new_toplevel(th), /* cref or me */ - iseq->iseq_encoded, th->cfp->sp, iseq->local_size, iseq->stack_max); + iseq->body->iseq_encoded, th->cfp->sp, iseq->body->local_size, iseq->body->stack_max); } static void -vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const rb_cref_t *cref, rb_block_t *base_block) +vm_set_eval_stack(rb_thread_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, rb_block_t *base_block) { - rb_iseq_t *iseq; - GetISeqPtr(iseqval, iseq); - vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH, base_block->self, VM_ENVVAL_PREV_EP_PTR(base_block->ep), (VALUE)cref, /* cref or me */ - iseq->iseq_encoded, - th->cfp->sp, iseq->local_size, iseq->stack_max); + iseq->body->iseq_encoded, + th->cfp->sp, iseq->body->local_size, iseq->body->stack_max); } static void -vm_set_main_stack(rb_thread_t *th, VALUE iseqval) +vm_set_main_stack(rb_thread_t *th, const rb_iseq_t *iseq) { VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); rb_binding_t *bind; - rb_iseq_t *iseq; rb_env_t *env; GetBindingPtr(toplevel_binding, bind); GetEnvPtr(bind->env, env); - vm_set_eval_stack(th, iseqval, 0, &env->block); + + vm_set_eval_stack(th, iseq, 0, &env->block); /* save binding */ - GetISeqPtr(iseqval, iseq); - if (bind && iseq->local_size > 0) { + if (bind && iseq->body->local_size > 0) { bind->env = vm_make_env_object(th, th->cfp); } } @@ -425,7 +418,7 @@ env_mark(void * const ptr) rb_gc_mark((VALUE)env->block.iseq); } else { - RUBY_MARK_UNLESS_NULL(env->block.iseq->self); + RUBY_MARK_UNLESS_NULL((VALUE)env->block.iseq); } } RUBY_MARK_LEAVE("env"); @@ -536,7 +529,7 @@ vm_make_env_each(rb_thread_t *const th, rb_control_frame_t *const cfp) local_size = 1 /* cref/me */; } else { - local_size = cfp->iseq->local_size; + local_size = cfp->iseq->body->local_size; } /* @@ -638,8 +631,8 @@ collect_local_variables_in_iseq(const rb_iseq_t *iseq, const struct local_var_li { int i; if (!iseq) return 0; - for (i = 0; i < iseq->local_table_size; i++) { - local_var_list_add(vars, iseq->local_table[i]); + for (i = 0; i < iseq->body->local_table_size; i++) { + local_var_list_add(vars, iseq->body->local_table[i]); } return 1; } @@ -756,7 +749,7 @@ rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) bindval = rb_binding_alloc(rb_cBinding); GetBindingPtr(bindval, bind); bind->env = envval; - bind->path = ruby_level_cfp->iseq->location.path; + bind->path = ruby_level_cfp->iseq->body->location.path; bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp); return bindval; @@ -765,11 +758,11 @@ rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) VALUE * rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) { - VALUE envval = bind->env, path = bind->path, iseqval; + VALUE envval = bind->env, path = bind->path; rb_env_t *env; rb_block_t *base_block; rb_thread_t *th = GET_THREAD(); - const rb_iseq_t *base_iseq; + const rb_iseq_t *base_iseq, *iseq; NODE *node = 0; ID minibuf[4], *dyns = minibuf; VALUE idtmp = 0; @@ -788,17 +781,16 @@ rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) node = NEW_NODE(NODE_SCOPE, dyns, 0, 0); if (base_iseq) { - iseqval = rb_iseq_new(node, base_iseq->location.label, path, path, - base_iseq->self, ISEQ_TYPE_EVAL); + iseq = rb_iseq_new(node, base_iseq->body->location.label, path, path, base_iseq, ISEQ_TYPE_EVAL); } else { VALUE tempstr = rb_str_new2("<temp>"); - iseqval = rb_iseq_new_top(node, tempstr, tempstr, tempstr, Qfalse); + iseq = rb_iseq_new_top(node, tempstr, tempstr, tempstr, NULL); } node->u1.tbl = 0; /* reset table */ ALLOCV_END(idtmp); - vm_set_eval_stack(th, iseqval, 0, base_block); + vm_set_eval_stack(th, iseq, 0, base_block); bind->env = vm_make_env_object(th, th->cfp); vm_pop_frame(th); GetEnvPtr(bind->env, env); @@ -821,7 +813,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, VALUE ret; const rb_iseq_t *iseq = block->iseq; const rb_control_frame_t *cfp; - int i, opt_pc, arg_size = iseq->param.size; + int i, opt_pc, arg_size = iseq->body->param.size; int type = block_proc_is_lambda(block->proc) ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK; const rb_callable_method_entry_t *me = th->passed_bmethod_me; th->passed_bmethod_me = NULL; @@ -839,9 +831,9 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_BMETHOD, self, VM_ENVVAL_PREV_EP_PTR(block->ep), (VALUE)me, /* cref or method (TODO: can we ignore cref?) */ - iseq->iseq_encoded + opt_pc, - cfp->sp + arg_size, iseq->local_size - arg_size, - iseq->stack_max); + iseq->body->iseq_encoded + opt_pc, + cfp->sp + arg_size, iseq->body->local_size - arg_size, + iseq->body->stack_max); RUBY_DTRACE_METHOD_ENTRY_HOOK(th, me->owner, me->called_id); EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, self, me->called_id, me->owner, Qnil); @@ -850,9 +842,9 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block, vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH, self, VM_ENVVAL_PREV_EP_PTR(block->ep), (VALUE)cref, /* cref or method */ - iseq->iseq_encoded + opt_pc, - cfp->sp + arg_size, iseq->local_size - arg_size, - iseq->stack_max); + iseq->body->iseq_encoded + opt_pc, + cfp->sp + arg_size, iseq->body->local_size - arg_size, + iseq->body->stack_max); } ret = vm_exec(th); @@ -1021,7 +1013,7 @@ rb_sourcefilename(void) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp) { - return cfp->iseq->location.path; + return cfp->iseq->body->location.path; } else { return Qnil; @@ -1035,7 +1027,7 @@ rb_sourcefile(void) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp) { - return RSTRING_PTR(cfp->iseq->location.path); + return RSTRING_PTR(cfp->iseq->body->location.path); } else { return 0; @@ -1489,7 +1481,7 @@ vm_exec(rb_thread_t *th) struct iseq_catch_table_entry *entry; struct iseq_catch_table *ct; unsigned long epc, cont_pc, cont_sp; - VALUE catch_iseqval; + const rb_iseq_t *catch_iseq; rb_control_frame_t *cfp; VALUE type; const rb_control_frame_t *escape_cfp; @@ -1497,7 +1489,8 @@ vm_exec(rb_thread_t *th) err = (struct vm_throw_data *)th->errinfo; exception_handler: - cont_pc = cont_sp = catch_iseqval = 0; + cont_pc = cont_sp = 0; + catch_iseq = NULL; while (th->cfp->pc == 0 || th->cfp->iseq == 0) { if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) { @@ -1512,7 +1505,7 @@ vm_exec(rb_thread_t *th) } cfp = th->cfp; - epc = cfp->pc - cfp->iseq->iseq_encoded; + epc = cfp->pc - cfp->iseq->body->iseq_encoded; escape_cfp = NULL; if (state == TAG_BREAK || state == TAG_RETURN) { @@ -1525,19 +1518,19 @@ vm_exec(rb_thread_t *th) THROW_DATA_STATE_SET(err, state = TAG_BREAK); } else { - ct = cfp->iseq->catch_table; + ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { - catch_iseqval = entry->iseq; + catch_iseq = entry->iseq; cont_pc = entry->cont; cont_sp = entry->sp; break; } } } - if (!catch_iseqval) { + if (!catch_iseq) { th->errinfo = Qnil; result = THROW_DATA_VAL(err); hook_before_rewind(th, th->cfp); @@ -1561,14 +1554,14 @@ vm_exec(rb_thread_t *th) } if (state == TAG_RAISE) { - ct = cfp->iseq->catch_table; + ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_RESCUE || entry->type == CATCH_TYPE_ENSURE) { - catch_iseqval = entry->iseq; + catch_iseq = entry->iseq; cont_pc = entry->cont; cont_sp = entry->sp; break; @@ -1577,13 +1570,13 @@ vm_exec(rb_thread_t *th) } } else if (state == TAG_RETRY) { - ct = cfp->iseq->catch_table; + ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { - catch_iseqval = entry->iseq; + catch_iseq = entry->iseq; cont_pc = entry->cont; cont_sp = entry->sp; break; @@ -1592,7 +1585,7 @@ vm_exec(rb_thread_t *th) const rb_control_frame_t *escape_cfp; escape_cfp = THROW_DATA_CATCH_FRAME(err); if (cfp == escape_cfp) { - cfp->pc = cfp->iseq->iseq_encoded + entry->cont; + cfp->pc = cfp->iseq->body->iseq_encoded + entry->cont; th->errinfo = Qnil; goto vm_loop_start; } @@ -1604,19 +1597,19 @@ vm_exec(rb_thread_t *th) type = CATCH_TYPE_BREAK; search_restart_point: - ct = cfp->iseq->catch_table; + ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { - catch_iseqval = entry->iseq; + catch_iseq = entry->iseq; cont_pc = entry->cont; cont_sp = entry->sp; break; } else if (entry->type == type) { - cfp->pc = cfp->iseq->iseq_encoded + entry->cont; + cfp->pc = cfp->iseq->body->iseq_encoded + entry->cont; cfp->sp = vm_base_ptr(cfp) + entry->sp; if (state != TAG_REDO) { @@ -1642,13 +1635,13 @@ vm_exec(rb_thread_t *th) goto search_restart_point; } else { - ct = cfp->iseq->catch_table; + ct = cfp->iseq->body->catch_table; if (ct) for (i = 0; i < ct->size; i++) { entry = &ct->entries[i]; if (entry->start < epc && entry->end >= epc) { if (entry->type == CATCH_TYPE_ENSURE) { - catch_iseqval = entry->iseq; + catch_iseq = entry->iseq; cont_pc = entry->cont; cont_sp = entry->sp; break; @@ -1657,14 +1650,10 @@ vm_exec(rb_thread_t *th) } } - if (catch_iseqval != 0) { - /* found catch table */ - rb_iseq_t *catch_iseq; - + if (catch_iseq != 0) { /* found catch table */ /* enter catch scope */ - GetISeqPtr(catch_iseqval, catch_iseq); cfp->sp = vm_base_ptr(cfp) + cont_sp; - cfp->pc = cfp->iseq->iseq_encoded + cont_pc; + cfp->pc = cfp->iseq->body->iseq_encoded + cont_pc; /* push block frame */ cfp->sp[0] = (VALUE)err; @@ -1672,10 +1661,10 @@ vm_exec(rb_thread_t *th) cfp->self, VM_ENVVAL_PREV_EP_PTR(cfp->ep), 0, /* cref or me */ - catch_iseq->iseq_encoded, + catch_iseq->body->iseq_encoded, cfp->sp + 1 /* push value */, - catch_iseq->local_size - 1, - catch_iseq->stack_max); + catch_iseq->body->local_size - 1, + catch_iseq->body->stack_max); state = 0; th->state = 0; @@ -1706,28 +1695,23 @@ vm_exec(rb_thread_t *th) /* misc */ VALUE -rb_iseq_eval(VALUE iseqval) +rb_iseq_eval(const rb_iseq_t *iseq) { rb_thread_t *th = GET_THREAD(); VALUE val; - - vm_set_top_stack(th, iseqval); - + vm_set_top_stack(th, iseq); val = vm_exec(th); - RB_GC_GUARD(iseqval); /* prohibit tail call optimization */ return val; } VALUE -rb_iseq_eval_main(VALUE iseqval) +rb_iseq_eval_main(const rb_iseq_t *iseq) { rb_thread_t *th = GET_THREAD(); VALUE val; - vm_set_main_stack(th, iseqval); - + vm_set_main_stack(th, iseq); val = vm_exec(th); - RB_GC_GUARD(iseqval); /* prohibit tail call optimization */ return val; } @@ -1770,7 +1754,7 @@ rb_thread_current_status(const rb_thread_t *th) const rb_iseq_t *iseq = cfp->iseq; int line_no = rb_vm_get_sourceline(cfp); str = rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"'", - iseq->location.path, line_no, iseq->location.label); + iseq->body->location.path, line_no, iseq->body->location.label); } } else if ((me = rb_vm_frame_method_entry(cfp)) && me->def->original_id) { @@ -1788,10 +1772,10 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, { rb_thread_t *th = GET_THREAD(); const rb_control_frame_t *reg_cfp = th->cfp; - volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); + const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); VALUE val; - vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH, + vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH, recv, VM_ENVVAL_BLOCK_PTR(blockptr), (VALUE)vm_cref_new_toplevel(th), /* cref or me */ 0, reg_cfp->sp, 1, 0); @@ -2065,12 +2049,9 @@ rb_thread_mark(void *ptr) rb_gc_mark_values((long)(sp - p), p); while (cfp != limit_cfp) { - const rb_iseq_t *iseq = cfp->iseq; rb_gc_mark(cfp->proc); rb_gc_mark(cfp->self); - if (iseq) { - rb_gc_mark(RUBY_VM_NORMAL_ISEQ_P(iseq) ? iseq->self : (VALUE)iseq); - } + rb_gc_mark((VALUE)cfp->iseq); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } } @@ -2287,11 +2268,11 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, visi = METHOD_VISI_PUBLIC; } - rb_add_method_iseq(klass, id, iseqval, cref, visi); + rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, visi); if (!is_singleton && scope_visi->module_func) { klass = rb_singleton_class(klass); - rb_add_method_iseq(klass, id, iseqval, cref, METHOD_VISI_PUBLIC); + rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, METHOD_VISI_PUBLIC); } } @@ -2755,9 +2736,8 @@ Init_VM(void) rb_vm_t *vm = ruby_current_vm; rb_thread_t *th = GET_THREAD(); VALUE filename = rb_str_new2("<main>"); - volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); + const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); volatile VALUE th_self; - rb_iseq_t *iseq; /* create vm object */ vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm); @@ -2774,10 +2754,9 @@ Init_VM(void) rb_vm_living_threads_insert(vm, th); - rb_gc_register_mark_object(iseqval); - GetISeqPtr(iseqval, iseq); + rb_gc_register_mark_object((VALUE)iseq); th->cfp->iseq = iseq; - th->cfp->pc = iseq->iseq_encoded; + th->cfp->pc = iseq->body->iseq_encoded; th->cfp->self = th->top_self; th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, NULL); @@ -2800,7 +2779,7 @@ rb_vm_set_progname(VALUE filename) rb_thread_t *th = GET_VM()->main_thread; rb_control_frame_t *cfp = (void *)(th->stack + th->stack_size); --cfp; - RB_OBJ_WRITE(cfp->iseq->self, &cfp->iseq->location.path, filename); + RB_OBJ_WRITE(cfp->iseq, &cfp->iseq->body->location.path, filename); } #if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE @@ -2893,7 +2872,7 @@ rb_ruby_debug_ptr(void) } /* iseq.c */ -VALUE rb_insn_operand_intern(rb_iseq_t *iseq, +VALUE rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE insn, int op_no, VALUE op, int len, size_t pos, VALUE *pnop, VALUE child); @@ -384,10 +384,10 @@ static void args_setup_kw_parameters(VALUE* const passed_values, const int passed_keyword_len, const VALUE *const passed_keywords, const rb_iseq_t * const iseq, VALUE * const locals) { - const ID *acceptable_keywords = iseq->param.keyword->table; - const int req_key_num = iseq->param.keyword->required_num; - const int key_num = iseq->param.keyword->num; - const VALUE * const default_values = iseq->param.keyword->default_values; + const ID *acceptable_keywords = iseq->body->param.keyword->table; + const int req_key_num = iseq->body->param.keyword->required_num; + const int key_num = iseq->body->param.keyword->num; + const VALUE * const default_values = iseq->body->param.keyword->default_values; VALUE missing = 0; int i, di, found = 0; int unspecified_bits = 0; @@ -438,7 +438,7 @@ args_setup_kw_parameters(VALUE* const passed_values, const int passed_keyword_le } } - if (iseq->param.flags.has_kwrest) { + if (iseq->body->param.flags.has_kwrest) { const int rest_hash_index = key_num + 1; locals[rest_hash_index] = make_unused_kw_hash(passed_keywords, passed_keyword_len, passed_values, FALSE); } @@ -502,8 +502,8 @@ static int setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, rb_call_info_t * const ci, VALUE * const locals, const enum arg_setup_type arg_setup_type) { - const int min_argc = iseq->param.lead_num + iseq->param.post_num; - const int max_argc = (iseq->param.flags.has_rest == FALSE) ? min_argc + iseq->param.opt_num : UNLIMITED_ARGUMENTS; + const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num; + const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS; int opt_pc = 0; int given_argc; struct args_info args_body, *args; @@ -516,16 +516,16 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r * * [pushed values] [uninitialized values] * <- ci->argc --> - * <- iseq->param.size------------------> + * <- iseq->body->param.size------------> * ^ locals ^ sp * * => * [pushed values] [initialized values ] * <- ci->argc --> - * <- iseq->param.size------------------> + * <- iseq->body->param.size------------> * ^ locals ^ sp */ - for (i=ci->argc; i<iseq->param.size; i++) { + for (i=ci->argc; i<iseq->body->param.size; i++) { locals[i] = Qnil; } th->cfp->sp = &locals[i]; @@ -537,7 +537,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r args->argv = locals; if (ci->kw_arg) { - if (iseq->param.flags.has_kw) { + if (iseq->body->param.flags.has_kw) { int kw_len = ci->kw_arg->keyword_len; /* copy kw_argv */ args->kw_argv = ALLOCA_N(VALUE, kw_len); @@ -568,17 +568,17 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r break; /* do nothing special */ case arg_setup_block: if (given_argc == 1 && - (min_argc > 0 || iseq->param.opt_num > 1 || - iseq->param.flags.has_kw || iseq->param.flags.has_kwrest) && - !iseq->param.flags.ambiguous_param0 && + (min_argc > 0 || iseq->body->param.opt_num > 1 || + iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) && + !iseq->body->param.flags.ambiguous_param0 && args_check_block_arg0(args, th)) { given_argc = RARRAY_LENINT(args->rest); } break; case arg_setup_lambda: if (given_argc == 1 && - given_argc != iseq->param.lead_num && - !iseq->param.flags.has_rest && + given_argc != iseq->body->param.lead_num && + !iseq->body->param.flags.has_rest && args_check_block_arg0(args, th)) { given_argc = RARRAY_LENINT(args->rest); } @@ -603,7 +603,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r } if (given_argc > min_argc && - (iseq->param.flags.has_kw || iseq->param.flags.has_kwrest) && + (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) && args->kw_argv == NULL) { if (args_pop_keyword_hash(args, &keyword_hash, th)) { given_argc--; @@ -621,25 +621,25 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r } } - if (iseq->param.flags.has_lead) { - args_setup_lead_parameters(args, iseq->param.lead_num, locals + 0); + if (iseq->body->param.flags.has_lead) { + args_setup_lead_parameters(args, iseq->body->param.lead_num, locals + 0); } - if (iseq->param.flags.has_post) { - args_setup_post_parameters(args, iseq->param.post_num, locals + iseq->param.post_start); + if (iseq->body->param.flags.has_post) { + args_setup_post_parameters(args, iseq->body->param.post_num, locals + iseq->body->param.post_start); } - if (iseq->param.flags.has_opt) { - int opt = args_setup_opt_parameters(args, iseq->param.opt_num, locals + iseq->param.lead_num); - opt_pc = (int)iseq->param.opt_table[opt]; + if (iseq->body->param.flags.has_opt) { + int opt = args_setup_opt_parameters(args, iseq->body->param.opt_num, locals + iseq->body->param.lead_num); + opt_pc = (int)iseq->body->param.opt_table[opt]; } - if (iseq->param.flags.has_rest) { - args_setup_rest_parameter(args, locals + iseq->param.rest_start); + if (iseq->body->param.flags.has_rest) { + args_setup_rest_parameter(args, locals + iseq->body->param.rest_start); } - if (iseq->param.flags.has_kw) { - VALUE * const klocals = locals + iseq->param.keyword->bits_start - iseq->param.keyword->num; + if (iseq->body->param.flags.has_kw) { + VALUE * const klocals = locals + iseq->body->param.keyword->bits_start - iseq->body->param.keyword->num; if (args->kw_argv != NULL) { args_setup_kw_parameters(args->kw_argv, args->ci->kw_arg->keyword_len, args->ci->kw_arg->keywords, iseq, klocals); @@ -660,18 +660,18 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, r args_setup_kw_parameters(NULL, 0, NULL, iseq, klocals); } } - else if (iseq->param.flags.has_kwrest) { - args_setup_kw_rest_parameter(keyword_hash, locals + iseq->param.keyword->rest_start); + else if (iseq->body->param.flags.has_kwrest) { + args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start); } - if (iseq->param.flags.has_block) { - args_setup_block_parameter(th, ci, locals + iseq->param.block_start); + if (iseq->body->param.flags.has_block) { + args_setup_block_parameter(th, ci, locals + iseq->body->param.block_start); } #if 0 { int i; - for (i=0; i<iseq->param.size; i++) { + for (i=0; i<iseq->body->param.size; i++) { fprintf(stderr, "local[%d] = %p\n", i, (void *)locals[i]); } } @@ -691,7 +691,7 @@ raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc) if (iseq) { vm_push_frame(th, iseq, VM_FRAME_MAGIC_DUMMY, Qnil /* self */, VM_ENVVAL_BLOCK_PTR(0) /* specval*/, Qfalse /* me or cref */, - iseq->iseq_encoded, th->cfp->sp, 1 /* local_size (cref/me) */, 0 /* stack_max */); + iseq->body->iseq_encoded, th->cfp->sp, 1 /* local_size (cref/me) */, 0 /* stack_max */); at = rb_vm_backtrace_object(); vm_pop_frame(th); } diff --git a/vm_backtrace.c b/vm_backtrace.c index aabc949f64..077ed5049f 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -31,7 +31,7 @@ id2str(ID id) inline static int calc_lineno(const rb_iseq_t *iseq, const VALUE *pc) { - return rb_iseq_line_no(iseq, pc - iseq->iseq_encoded); + return rb_iseq_line_no(iseq, pc - iseq->body->iseq_encoded); } int @@ -87,7 +87,7 @@ location_mark_entry(rb_backtrace_location_t *fi) switch (fi->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - rb_gc_mark(fi->body.iseq.iseq->self); + rb_gc_mark((VALUE)fi->body.iseq.iseq); break; case LOCATION_TYPE_CFUNC: case LOCATION_TYPE_IFUNC: @@ -157,7 +157,7 @@ location_label(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->location.label; + return loc->body.iseq.iseq->body->location.label; case LOCATION_TYPE_CFUNC: return rb_id2str(loc->body.cfunc.mid); case LOCATION_TYPE_IFUNC: @@ -206,7 +206,7 @@ location_base_label(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->location.base_label; + return loc->body.iseq.iseq->body->location.base_label; case LOCATION_TYPE_CFUNC: return rb_id2str(loc->body.cfunc.mid); case LOCATION_TYPE_IFUNC: @@ -233,7 +233,7 @@ location_path(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->location.path; + return loc->body.iseq.iseq->body->location.path; case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { return location_path(loc->body.cfunc.prev_loc); @@ -266,7 +266,7 @@ location_absolute_path(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->location.absolute_path; + return loc->body.iseq.iseq->body->location.absolute_path; case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { return location_absolute_path(loc->body.cfunc.prev_loc); @@ -315,20 +315,20 @@ location_to_str(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: - file = loc->body.iseq.iseq->location.path; - name = loc->body.iseq.iseq->location.label; + file = loc->body.iseq.iseq->body->location.path; + name = loc->body.iseq.iseq->body->location.label; lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc); loc->type = LOCATION_TYPE_ISEQ_CALCED; break; case LOCATION_TYPE_ISEQ_CALCED: - file = loc->body.iseq.iseq->location.path; + file = loc->body.iseq.iseq->body->location.path; lineno = loc->body.iseq.lineno.lineno; - name = loc->body.iseq.iseq->location.label; + name = loc->body.iseq.iseq->body->location.label; break; case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { - file = loc->body.cfunc.prev_loc->body.iseq.iseq->location.path; + file = loc->body.cfunc.prev_loc->body.iseq.iseq->body->location.path; lineno = location_lineno(loc->body.cfunc.prev_loc); } else { @@ -693,8 +693,8 @@ oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp) const rb_iseq_t *iseq = cfp->iseq; const VALUE *pc = cfp->pc; struct oldbt_arg *arg = (struct oldbt_arg *)ptr; - VALUE file = arg->filename = iseq->location.path; - VALUE name = iseq->location.label; + VALUE file = arg->filename = iseq->body->location.path; + VALUE name = iseq->body->location.label; int lineno = arg->lineno = calc_lineno(iseq, pc); (arg->func)(arg->data, file, lineno, name); @@ -1111,7 +1111,7 @@ collect_caller_bindings_iseq(void *arg, const rb_control_frame_t *cfp) rb_ary_store(frame, CALLER_BINDING_SELF, cfp->self); rb_ary_store(frame, CALLER_BINDING_CLASS, get_klass(cfp)); rb_ary_store(frame, CALLER_BINDING_BINDING, GC_GUARDED_PTR(cfp)); /* create later */ - rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? cfp->iseq->self : Qnil); + rb_ary_store(frame, CALLER_BINDING_ISEQ, cfp->iseq ? (VALUE)cfp->iseq : Qnil); rb_ary_store(frame, CALLER_BINDING_CFP, GC_GUARDED_PTR(cfp)); rb_ary_push(data->ary, frame); @@ -1231,7 +1231,9 @@ VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index) { VALUE frame = frame_get(dc, index); - return rb_ary_entry(frame, CALLER_BINDING_ISEQ); + VALUE iseq = rb_ary_entry(frame, CALLER_BINDING_ISEQ); + + return RTEST(iseq) ? rb_iseqw_new((rb_iseq_t *)iseq) : Qnil; } VALUE @@ -1261,7 +1263,7 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) buff[i] = (VALUE)cme; } else { - buff[i] = cfp->iseq->self; + buff[i] = (VALUE)cfp->iseq; } if (cfp->iseq && lines) lines[i] = calc_lineno(cfp->iseq, cfp->pc); @@ -1274,24 +1276,27 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) return i; } -static VALUE +static const rb_iseq_t * frame2iseq(VALUE frame) { - if (frame == Qnil) return Qnil; - - if (RB_TYPE_P(frame, T_DATA)) { - VM_ASSERT(strcmp(rb_objspace_data_type_name(frame), "iseq") == 0); - return frame; - } + if (frame == Qnil) return NULL; if (RB_TYPE_P(frame, T_IMEMO)) { - const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame; - VM_ASSERT(imemo_type(frame) == imemo_ment); - switch (cme->def->type) { - case VM_METHOD_TYPE_ISEQ: - return cme->def->body.iseq.iseqptr->self; + switch (imemo_type(frame)) { + case imemo_iseq: + return (const rb_iseq_t *)frame; + case imemo_ment: + { + const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame; + switch (cme->def->type) { + case VM_METHOD_TYPE_ISEQ: + return cme->def->body.iseq.iseqptr; + default: + return NULL; + } + } default: - return Qnil; + break; } } rb_bug("frame2iseq: unreachable"); @@ -1300,36 +1305,36 @@ frame2iseq(VALUE frame) VALUE rb_profile_frame_path(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_path(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_path(iseq) : Qnil; } VALUE rb_profile_frame_absolute_path(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_absolute_path(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_absolute_path(iseq) : Qnil; } VALUE rb_profile_frame_label(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_label(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_label(iseq) : Qnil; } VALUE rb_profile_frame_base_label(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_base_label(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_base_label(iseq) : Qnil; } VALUE rb_profile_frame_first_lineno(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_first_lineno(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_first_lineno(iseq) : Qnil; } static VALUE @@ -1384,8 +1389,8 @@ rb_profile_frame_singleton_method_p(VALUE frame) VALUE rb_profile_frame_method_name(VALUE frame) { - VALUE iseqv = frame2iseq(frame); - return NIL_P(iseqv) ? Qnil : rb_iseq_method_name(iseqv); + const rb_iseq_t *iseq = frame2iseq(frame); + return iseq ? rb_iseq_method_name(iseq) : Qnil; } VALUE @@ -233,9 +233,6 @@ typedef struct rb_call_info_struct { #define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct((obj), type, (ptr)) #endif -#define GetISeqPtr(obj, ptr) \ - GetCoreDataFromValue((obj), rb_iseq_t, (ptr)) - typedef struct rb_iseq_location_struct { const VALUE path; const VALUE absolute_path; @@ -244,7 +241,7 @@ typedef struct rb_iseq_location_struct { VALUE first_lineno; /* TODO: may be unsigned short */ } rb_iseq_location_t; -struct rb_iseq_struct { +struct rb_iseq_body { /***************/ /* static data */ /***************/ @@ -260,9 +257,7 @@ struct rb_iseq_struct { ISEQ_TYPE_MAIN, ISEQ_TYPE_DEFINED_GUARD } type; /* instruction sequence type */ -#if defined(WORDS_BIGENDIAN) && (SIZEOF_VALUE > SIZEOF_INT) - char dummy[SIZEOF_VALUE - SIZEOF_INT]; /* [Bug #10037][ruby-core:63721] */ -#endif + int stack_max; /* for stack overflow check */ rb_iseq_location_t location; @@ -370,19 +365,24 @@ struct rb_iseq_struct { /* dynamic data */ /****************/ - VALUE self; - /* misc */ rb_num_t flip_cnt; - /* used at compile time */ - struct iseq_compile_data *compile_data; - /* original iseq, before encoding * used for debug/dump (TODO: union with compile_data) */ VALUE *iseq; }; +/* T_IMEMO/iseq */ +/* typedef rb_iseq_t is in method.h */ +struct rb_iseq_struct { + VALUE flags; + struct iseq_compile_data *compile_data; /* used at compile time */ + struct rb_iseq_body *body; + VALUE dummy1; + VALUE dummy2; +}; + enum ruby_special_exceptions { ruby_error_reenter, ruby_error_nomemory, @@ -785,18 +785,18 @@ typedef enum { RUBY_SYMBOL_EXPORT_BEGIN /* node -> iseq */ -VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE, enum iseq_type); -VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, VALUE parent); -VALUE rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path); -VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, enum iseq_type, VALUE); -VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, enum iseq_type, const rb_compile_option_t*); +rb_iseq_t *rb_iseq_new(NODE*, VALUE, VALUE, VALUE, const rb_iseq_t *parent, enum iseq_type); +rb_iseq_t *rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, const rb_iseq_t *parent); +rb_iseq_t *rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path); +rb_iseq_t *rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, enum iseq_type, VALUE); +rb_iseq_t *rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const rb_iseq_t *parent, enum iseq_type, const rb_compile_option_t*); /* src -> iseq */ -VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line); -VALUE rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block); -VALUE rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt); +rb_iseq_t *rb_iseq_compile(VALUE src, VALUE file, VALUE line); +rb_iseq_t *rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block); +rb_iseq_t *rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt); -VALUE rb_iseq_disasm(VALUE self); +VALUE rb_iseq_disasm(const rb_iseq_t *iseq); int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child); const char *ruby_node_name(int node); @@ -946,9 +946,8 @@ rb_block_t *rb_vm_control_frame_block_ptr(const rb_control_frame_t *cfp); #define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \ (!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th))) -#define RUBY_VM_IFUNC_P(ptr) RB_TYPE_P((VALUE)(ptr), T_IMEMO) -#define RUBY_VM_NORMAL_ISEQ_P(ptr) \ - ((ptr) && !RUBY_VM_IFUNC_P(ptr)) +#define RUBY_VM_IFUNC_P(ptr) (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_ifunc) +#define RUBY_VM_NORMAL_ISEQ_P(ptr) (RB_TYPE_P((VALUE)(ptr), T_IMEMO) && imemo_type((VALUE)ptr) == imemo_iseq) #define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self)) #define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \ @@ -972,8 +971,8 @@ NORETURN(void rb_bug_context(const void *, const char *fmt, ...)); /* functions about thread/vm execution */ RUBY_SYMBOL_EXPORT_BEGIN -VALUE rb_iseq_eval(VALUE iseqval); -VALUE rb_iseq_eval_main(VALUE iseqval); +VALUE rb_iseq_eval(const rb_iseq_t *iseq); +VALUE rb_iseq_eval_main(const rb_iseq_t *iseq); RUBY_SYMBOL_EXPORT_END int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp); @@ -39,7 +39,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) const rb_callable_method_entry_t *me; if (cfp->block_iseq != 0 && !RUBY_VM_IFUNC_P(cfp->block_iseq)) { - biseq_name = ""; /* RSTRING(cfp->block_iseq->location.label)->ptr; */ + biseq_name = ""; /* RSTRING(cfp->block_iseq->body->location.label)->ptr; */ } if (ep < 0 || (size_t)ep > th->stack_size) { @@ -99,11 +99,11 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) iseq_name = "<ifunc>"; } else { - pc = cfp->pc - cfp->iseq->iseq_encoded; - iseq_name = RSTRING_PTR(cfp->iseq->location.label); + pc = cfp->pc - cfp->iseq->body->iseq_encoded; + iseq_name = RSTRING_PTR(cfp->iseq->body->location.label); line = rb_vm_get_sourceline(cfp); if (line) { - snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->location.path), line); + snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->body->location.path), line); } } } @@ -233,9 +233,9 @@ static VALUE * vm_base_ptr(rb_control_frame_t *cfp) { rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1; + VALUE *bp = prev_cfp->sp + cfp->iseq->body->local_size + 1; - if (cfp->iseq->type == ISEQ_TYPE_METHOD) { + if (cfp->iseq->body->type == ISEQ_TYPE_METHOD) { bp += 1; } return bp; @@ -266,9 +266,9 @@ vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) name = "<ifunc>"; } else { - argc = iseq->param.lead_num; - local_size = iseq->local_size; - name = RSTRING_PTR(iseq->location.label); + argc = iseq->body->param.lead_num; + local_size = iseq->body->local_size; + name = RSTRING_PTR(iseq->body->location.label); } /* stack trace header */ @@ -335,7 +335,7 @@ rb_vmdebug_debug_print_register(rb_thread_t *th) ptrdiff_t cfpi; if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { - pc = cfp->pc - cfp->iseq->iseq_encoded; + pc = cfp->pc - cfp->iseq->body->iseq_encoded; } if (ep < 0 || (size_t)ep > th->stack_size) { @@ -361,7 +361,7 @@ rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp,VALUE *_pc) const rb_iseq_t *iseq = cfp->iseq; if (iseq != 0) { - ptrdiff_t pc = _pc - iseq->iseq_encoded; + ptrdiff_t pc = _pc - iseq->body->iseq_encoded; int i; for (i=0; i<(int)VM_CFP_CNT(th, cfp); i++) { @@ -20,7 +20,7 @@ static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *a static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv); static inline VALUE vm_yield_with_block(rb_thread_t *th, int argc, const VALUE *argv, const rb_block_t *blockargptr); static VALUE vm_exec(rb_thread_t *th); -static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const rb_cref_t *cref, rb_block_t *base_block); +static void vm_set_eval_stack(rb_thread_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, rb_block_t *base_block); static int vm_collect_local_variables_in_heap(rb_thread_t *th, const VALUE *dfp, const struct local_var_list *vars); static VALUE rb_eUncaughtThrow; @@ -1234,8 +1234,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ if ((state = TH_EXEC_TAG()) == 0) { rb_cref_t *cref = cref_arg; rb_binding_t *bind = 0; - rb_iseq_t *iseq; - volatile VALUE iseqval; + const rb_iseq_t *iseq; VALUE absolute_path = Qnil; VALUE fname; @@ -1282,7 +1281,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ /* make eval iseq */ th->parse_in_eval++; th->mild_compile_error++; - iseqval = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil); + iseq = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil); th->mild_compile_error--; th->parse_in_eval--; @@ -1297,17 +1296,16 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ cref = rb_vm_get_cref(base_block->ep); } } - vm_set_eval_stack(th, iseqval, cref, base_block); + vm_set_eval_stack(th, iseq, cref, base_block); RB_GC_GUARD(crefval); if (0) { /* for debug */ - VALUE disasm = rb_iseq_disasm(iseqval); + VALUE disasm = rb_iseq_disasm(iseq); printf("%s\n", StringValuePtr(disasm)); } /* save new env */ - GetISeqPtr(iseqval, iseq); - if (bind && iseq->local_table_size > 0) { + if (bind && iseq->body->local_table_size > 0) { bind->env = vm_make_env_object(th, th->cfp); } @@ -2050,8 +2048,8 @@ rb_f_local_variables(void) local_var_list_init(&vars); while (cfp) { if (cfp->iseq) { - for (i = 0; i < cfp->iseq->local_table_size; i++) { - local_var_list_add(&vars, cfp->iseq->local_table[i]); + for (i = 0; i < cfp->iseq->body->local_table_size; i++) { + local_var_list_add(&vars, cfp->iseq->body->local_table[i]); } } if (!VM_EP_LEP_P(cfp->ep)) { @@ -2117,7 +2115,7 @@ rb_current_realfilepath(void) rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); - if (cfp != 0) return cfp->iseq->location.absolute_path; + if (cfp != 0) return cfp->iseq->body->location.absolute_path; return Qnil; } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index b3ff4fd0bc..357ed4daa4 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -845,15 +845,15 @@ vm_throw_start(rb_thread_t *const th, rb_control_frame_t *const reg_cfp, enum ru const rb_iseq_t *base_iseq = GET_ISEQ(); escape_cfp = reg_cfp; - while (base_iseq->type != ISEQ_TYPE_BLOCK) { - if (escape_cfp->iseq->type == ISEQ_TYPE_CLASS) { + while (base_iseq->body->type != ISEQ_TYPE_BLOCK) { + if (escape_cfp->iseq->body->type == ISEQ_TYPE_CLASS) { escape_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(escape_cfp); ep = escape_cfp->ep; base_iseq = escape_cfp->iseq; } else { ep = VM_EP_PREV_EP(ep); - base_iseq = base_iseq->parent_iseq; + base_iseq = base_iseq->body->parent_iseq; escape_cfp = rb_vm_search_cf_from_ep(th, escape_cfp, ep); VM_ASSERT(escape_cfp->iseq == base_iseq); } @@ -869,9 +869,9 @@ vm_throw_start(rb_thread_t *const th, rb_control_frame_t *const reg_cfp, enum ru while (escape_cfp < eocfp) { if (escape_cfp->ep == ep) { - const VALUE epc = escape_cfp->pc - escape_cfp->iseq->iseq_encoded; + const VALUE epc = escape_cfp->pc - escape_cfp->iseq->body->iseq_encoded; const rb_iseq_t * const iseq = escape_cfp->iseq; - const struct iseq_catch_table * const ct = iseq->catch_table; + const struct iseq_catch_table * const ct = iseq->body->catch_table; const int ct_size = ct->size; int i; @@ -919,7 +919,7 @@ vm_throw_start(rb_thread_t *const th, rb_control_frame_t *const reg_cfp, enum ru target_lep = lep; } - if (lep == target_lep && escape_cfp->iseq->type == ISEQ_TYPE_CLASS) { + if (lep == target_lep && escape_cfp->iseq->body->type == ISEQ_TYPE_CLASS) { in_class_frame = 1; target_lep = 0; } @@ -944,7 +944,7 @@ vm_throw_start(rb_thread_t *const th, rb_control_frame_t *const reg_cfp, enum ru } } - if (escape_cfp->ep == target_lep && escape_cfp->iseq->type == ISEQ_TYPE_METHOD) { + if (escape_cfp->ep == target_lep && escape_cfp->iseq->body->type == ISEQ_TYPE_METHOD) { goto valid_return; } @@ -1198,9 +1198,9 @@ static VALUE * vm_base_ptr(rb_control_frame_t *cfp) { rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - VALUE *bp = prev_cfp->sp + cfp->iseq->local_size + 1; + VALUE *bp = prev_cfp->sp + cfp->iseq->body->local_size + 1; - if (cfp->iseq->type == ISEQ_TYPE_METHOD) { + if (cfp->iseq->body->type == ISEQ_TYPE_METHOD) { /* adjust `self' */ bp += 1; } @@ -1241,9 +1241,9 @@ vm_callee_setup_block_arg_arg0_splat(rb_control_frame_t *cfp, const rb_iseq_t *i int i; long len = RARRAY_LEN(ary); - CHECK_VM_STACK_OVERFLOW(cfp, iseq->param.lead_num); + CHECK_VM_STACK_OVERFLOW(cfp, iseq->body->param.lead_num); - for (i=0; i<len && i<iseq->param.lead_num; i++) { + for (i=0; i<len && i<iseq->body->param.lead_num; i++) { argv[i] = RARRAY_AREF(ary, i); } @@ -1253,12 +1253,12 @@ vm_callee_setup_block_arg_arg0_splat(rb_control_frame_t *cfp, const rb_iseq_t *i static inline int simple_iseq_p(const rb_iseq_t *iseq) { - return iseq->param.flags.has_opt == FALSE && - iseq->param.flags.has_rest == FALSE && - iseq->param.flags.has_post == FALSE && - iseq->param.flags.has_kw == FALSE && - iseq->param.flags.has_kwrest == FALSE && - iseq->param.flags.has_block == FALSE; + return iseq->body->param.flags.has_opt == FALSE && + iseq->body->param.flags.has_rest == FALSE && + iseq->body->param.flags.has_post == FALSE && + iseq->body->param.flags.has_kw == FALSE && + iseq->body->param.flags.has_kwrest == FALSE && + iseq->body->param.flags.has_block == FALSE; } static inline void @@ -1272,32 +1272,32 @@ vm_callee_setup_block_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t * if (arg_setup_type == arg_setup_block && ci->argc == 1 && - iseq->param.flags.has_lead && - !iseq->param.flags.ambiguous_param0 && + iseq->body->param.flags.has_lead && + !iseq->body->param.flags.ambiguous_param0 && !NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv))) { ci->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0); } - if (ci->argc != iseq->param.lead_num) { + if (ci->argc != iseq->body->param.lead_num) { if (arg_setup_type == arg_setup_block) { - if (ci->argc < iseq->param.lead_num) { + if (ci->argc < iseq->body->param.lead_num) { int i; - CHECK_VM_STACK_OVERFLOW(cfp, iseq->param.lead_num); - for (i=ci->argc; i<iseq->param.lead_num; i++) argv[i] = Qnil; - ci->argc = iseq->param.lead_num; /* fill rest parameters */ + CHECK_VM_STACK_OVERFLOW(cfp, iseq->body->param.lead_num); + for (i=ci->argc; i<iseq->body->param.lead_num; i++) argv[i] = Qnil; + ci->argc = iseq->body->param.lead_num; /* fill rest parameters */ } - else if (ci->argc > iseq->param.lead_num) { - ci->argc = iseq->param.lead_num; /* simply truncate arguments */ + else if (ci->argc > iseq->body->param.lead_num) { + ci->argc = iseq->body->param.lead_num; /* simply truncate arguments */ } } else if (arg_setup_type == arg_setup_lambda && ci->argc == 1 && !NIL_P(arg0 = vm_callee_setup_block_arg_arg0_check(argv)) && - RARRAY_LEN(arg0) == iseq->param.lead_num) { + RARRAY_LEN(arg0) == iseq->body->param.lead_num) { ci->argc = vm_callee_setup_block_arg_arg0_splat(cfp, iseq, argv, arg0); } else { - argument_arity_error(th, iseq, ci->argc, iseq->param.lead_num, iseq->param.lead_num); + argument_arity_error(th, iseq, ci->argc, iseq->body->param.lead_num, iseq->body->param.lead_num); } } @@ -1316,8 +1316,8 @@ vm_callee_setup_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq, CALLER_SETUP_ARG(cfp, ci); /* splat arg */ - if (ci->argc != iseq->param.lead_num) { - argument_arity_error(th, iseq, ci->argc, iseq->param.lead_num, iseq->param.lead_num); + if (ci->argc != iseq->body->param.lead_num) { + argument_arity_error(th, iseq, ci->argc, iseq->body->param.lead_num, iseq->body->param.lead_num); } ci->aux.opt_pc = 0; @@ -1365,16 +1365,16 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info VALUE *argv = cfp->sp - ci->argc; const rb_callable_method_entry_t *me = ci->me; const rb_iseq_t *iseq = def_iseq_ptr(me->def); - VALUE *sp = argv + iseq->param.size; + VALUE *sp = argv + iseq->body->param.size; /* clear local variables (arg_size...local_size) */ - for (i = iseq->param.size, local_size = iseq->local_size; i < local_size; i++) { + for (i = iseq->body->param.size, local_size = iseq->body->local_size; i < local_size; i++) { *sp++ = Qnil; } vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, VM_ENVVAL_BLOCK_PTR(ci->blockptr), (VALUE)me, - iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, iseq->stack_max); + iseq->body->iseq_encoded + ci->aux.opt_pc, sp, 0, iseq->body->stack_max); cfp->sp = argv - 1 /* recv */; return Qundef; @@ -1402,18 +1402,18 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in sp++; /* copy arguments */ - for (i=0; i < iseq->param.size; i++) { + for (i=0; i < iseq->body->param.size; i++) { *sp++ = src_argv[i]; } /* clear local variables */ - for (i = 0; i < iseq->local_size - iseq->param.size; i++) { + for (i = 0; i < iseq->body->local_size - iseq->body->param.size; i++) { *sp++ = Qnil; } vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag, ci->recv, VM_ENVVAL_BLOCK_PTR(ci->blockptr), (VALUE)me, - iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, iseq->stack_max); + iseq->body->iseq_encoded + ci->aux.opt_pc, sp, 0, iseq->body->stack_max); cfp->sp = sp_orig; return Qundef; @@ -1869,8 +1869,9 @@ current_method_entry(rb_thread_t *th, rb_control_frame_t *cfp) { rb_control_frame_t *top_cfp = cfp; - if (cfp->iseq && cfp->iseq->type == ISEQ_TYPE_BLOCK) { - const rb_iseq_t *local_iseq = cfp->iseq->local_iseq; + if (cfp->iseq && cfp->iseq->body->type == ISEQ_TYPE_BLOCK) { + const rb_iseq_t *local_iseq = cfp->iseq->body->local_iseq; + do { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { @@ -2306,7 +2307,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci { const rb_block_t *block = VM_CF_BLOCK_PTR(reg_cfp); const rb_iseq_t *iseq; - VALUE type = GET_ISEQ()->local_iseq->type; + VALUE type = GET_ISEQ()->body->local_iseq->body->type; if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) { rb_vm_localjump_error("no block given (yield)", Qnil, 0); @@ -2315,7 +2316,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci if (!RUBY_VM_IFUNC_P(iseq)) { int opt_pc; - const int arg_size = iseq->param.size; + const int arg_size = iseq->body->param.size; int is_lambda = block_proc_is_lambda(block->proc); VALUE * const rsp = GET_SP() - ci->argc; @@ -2327,9 +2328,9 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci is_lambda ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK, block->self, VM_ENVVAL_PREV_EP_PTR(block->ep), 0, - iseq->iseq_encoded + opt_pc, + iseq->body->iseq_encoded + opt_pc, rsp + arg_size, - iseq->local_size - arg_size, iseq->stack_max); + iseq->body->local_size - arg_size, iseq->body->stack_max); return Qundef; } diff --git a/vm_method.c b/vm_method.c index 0ae14c833a..1364e5a4a5 100644 --- a/vm_method.c +++ b/vm_method.c @@ -254,7 +254,7 @@ method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { - VALUE location = rb_ary_new3(2, cfp->iseq->location.path, INT2FIX(line)); + VALUE location = rb_ary_new3(2, cfp->iseq->body->location.path, INT2FIX(line)); RB_OBJ_WRITE(me, &def->body.attr.location, rb_ary_freeze(location)); } else { @@ -296,7 +296,7 @@ method_definition_reset(const rb_method_entry_t *me) switch(def->type) { case VM_METHOD_TYPE_ISEQ: - RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.iseqptr->self); + RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.iseqptr); RB_OBJ_WRITTEN(me, Qundef, def->body.iseq.cref); break; case VM_METHOD_TYPE_ATTRSET: @@ -512,9 +512,9 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil default: break; } - if (iseq && !NIL_P(iseq->location.path)) { - int line = iseq->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq->self)) : 0; - rb_compile_warning(RSTRING_PTR(iseq->location.path), line, + if (iseq && !NIL_P(iseq->body->location.path)) { + int line = iseq->body->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq)) : 0; + rb_compile_warning(RSTRING_PTR(iseq->body->location.path), line, "previous definition of %"PRIsVALUE" was here", rb_id2str(old_def->original_id)); } @@ -583,19 +583,16 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_ } void -rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_visibility_t visi) +rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi) { - rb_iseq_t *iseq; struct { /* should be same fields with rb_method_iseq_struct */ - rb_iseq_t *iseqptr; + const rb_iseq_t *iseqptr; rb_cref_t *cref; } iseq_body; - GetISeqPtr(iseqval, iseq); iseq_body.iseqptr = iseq; iseq_body.cref = cref; rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, &iseq_body, visi); - RB_GC_GUARD(iseqval); } static rb_method_entry_t * diff --git a/vm_trace.c b/vm_trace.c index b46437038c..529cb720df 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -750,7 +750,7 @@ fill_path_and_lineno(rb_trace_arg_t *trace_arg) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp); if (cfp) { - trace_arg->path = cfp->iseq->location.path; + trace_arg->path = cfp->iseq->body->location.path; trace_arg->lineno = rb_vm_get_sourceline(cfp); } else { |