From d3aad1592213ed2c6ade84b09119c9fce46d185e Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 6 Dec 2018 10:52:27 +0000 Subject: Return same ISeq object for one src. * iseq.c: before this patch, RubyVM::InstructionSequence.of(src) (ISeq in short) returns different ISeq (wrapper) objects point to one ISeq internal object. This patch changes this behavior to cache created ISeq (wrapper) objects and return same ISeq object for an internal ISeq object. * iseq.h (ISEQ_EXECUTABLE_P): introduced to check executable ISeq objects. * iseq.h (ISEQ_COMPILE_DATA_ALLOC): reordr setting flag line to avoid ISEQ_USE_COMPILE_DATA but compiled_data == NULL case. * vm_core.h (rb_iseq_t): introduce `rb_iseq_t::wrapper` and `rb_iseq_t::aux::exec`. Move `rb_iseq_t::local_hooks` to `rb_iseq_t::aux::exec::local_hooks`. * test/ruby/test_iseq.rb: add ISeq.of() tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66246 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- iseq.c | 86 +++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 35 deletions(-) (limited to 'iseq.c') diff --git a/iseq.c b/iseq.c index 8e890d4a67..36568f0ce0 100644 --- a/iseq.c +++ b/iseq.c @@ -112,8 +112,8 @@ rb_iseq_free(const rb_iseq_t *iseq) ruby_xfree(body); } - if (iseq->local_hooks) { - rb_hook_list_free(iseq->local_hooks); + if (ISEQ_EXECUTABLE_P(iseq) && iseq->aux.exec.local_hooks) { + rb_hook_list_free(iseq->aux.exec.local_hooks); } RUBY_FREE_LEAVE("iseq"); @@ -211,6 +211,8 @@ rb_iseq_mark(const rb_iseq_t *iseq) { RUBY_MARK_ENTER("iseq"); + RUBY_MARK_UNLESS_NULL(iseq->wrapper); + if (iseq->body) { const struct rb_iseq_constant_body *const body = iseq->body; @@ -252,18 +254,23 @@ rb_iseq_mark(const rb_iseq_t *iseq) } } - if (iseq->local_hooks) { - rb_hook_list_mark(iseq->local_hooks); - } - - if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) { + if (FL_TEST_RAW(iseq, ISEQ_NOT_LOADED_YET)) { rb_gc_mark(iseq->aux.loader.obj); } - else if (ISEQ_COMPILE_DATA(iseq) != NULL) { + else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) { const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq); - 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); + VM_ASSERT(compile_data != NULL); + + 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); + } + else { + /* executable */ + VM_ASSERT(ISEQ_EXECUTABLE_P(iseq)); + if (iseq->aux.exec.local_hooks) { + rb_hook_list_mark(iseq->aux.exec.local_hooks); + } } RUBY_MARK_LEAVE("iseq"); @@ -519,7 +526,7 @@ rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body) void rb_iseq_init_trace(rb_iseq_t *iseq) { - iseq->aux.global_trace_events = 0; + iseq->aux.exec.global_trace_events = 0; if (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS) { rb_iseq_trace_set(iseq, ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS); } @@ -1037,14 +1044,22 @@ static const rb_data_type_t iseqw_data_type = { static VALUE iseqw_new(const rb_iseq_t *iseq) { - union { const rb_iseq_t *in; void *out; } deconst; - VALUE obj; + if (iseq->wrapper) { + return iseq->wrapper; + } + else { + union { const rb_iseq_t *in; void *out; } deconst; + VALUE obj; + deconst.in = iseq; + obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out); + RB_OBJ_WRITTEN(obj, Qundef, iseq); - deconst.in = iseq; - obj = TypedData_Wrap_Struct(rb_cISeq, &iseqw_data_type, deconst.out); - RB_OBJ_WRITTEN(obj, Qundef, iseq); + /* cache a wrapper object */ + RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj); + RB_OBJ_FREEZE((VALUE)iseq); - return obj; + return obj; + } } VALUE @@ -1676,7 +1691,7 @@ rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t res struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos); if (entry) { entry->events &= ~reset; - if (!(entry->events & iseq->aux.global_trace_events)) { + if (!(entry->events & iseq->aux.exec.global_trace_events)) { void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos); rb_iseq_trace_flag_cleared(iseq, pos); } @@ -2990,7 +3005,7 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, const struct rb_iseq_constant_body *const body = iseq->body; VALUE *iseq_encoded = (VALUE *)body->iseq_encoded; - VM_ASSERT((iseq->flags & ISEQ_USE_COMPILE_DATA) == 0); + VM_ASSERT(ISEQ_EXECUTABLE_P(iseq)); for (pc=0; pciseq_size;) { const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pc); @@ -3008,14 +3023,14 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, if (pc_events & target_events) { n++; } - pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.global_trace_events)); + pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events)); } if (n > 0) { - if (iseq->local_hooks == NULL) { - ((rb_iseq_t *)iseq)->local_hooks = RB_ZALLOC(rb_hook_list_t); + if (iseq->aux.exec.local_hooks == NULL) { + ((rb_iseq_t *)iseq)->aux.exec.local_hooks = RB_ZALLOC(rb_hook_list_t); } - rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->local_hooks, tpval, target_line); + rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->aux.exec.local_hooks, tpval, target_line); } return n; @@ -3055,25 +3070,25 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval) { int n = 0; - if (iseq->local_hooks) { + if (iseq->aux.exec.local_hooks) { unsigned int pc; const struct rb_iseq_constant_body *const body = iseq->body; VALUE *iseq_encoded = (VALUE *)body->iseq_encoded; rb_event_flag_t local_events = 0; - rb_hook_list_remove_tracepoint(iseq->local_hooks, tpval); - local_events = iseq->local_hooks->events; + rb_hook_list_remove_tracepoint(iseq->aux.exec.local_hooks, tpval); + local_events = iseq->aux.exec.local_hooks->events; if (local_events == 0) { - if (iseq->local_hooks->running == 0) { - rb_hook_list_free(iseq->local_hooks); + if (iseq->aux.exec.local_hooks->running == 0) { + rb_hook_list_free(iseq->aux.exec.local_hooks); } - ((rb_iseq_t *)iseq)->local_hooks = NULL; + ((rb_iseq_t *)iseq)->aux.exec.local_hooks = NULL; } for (pc = 0; pciseq_size;) { rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc); - pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.global_trace_events)); + pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events)); } } return n; @@ -3106,10 +3121,11 @@ rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval) void rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events) { - if (iseq->aux.global_trace_events == turnon_events) { + if (iseq->aux.exec.global_trace_events == turnon_events) { return; } - if (iseq->flags & ISEQ_USE_COMPILE_DATA) { + + if (!ISEQ_EXECUTABLE_P(iseq)) { /* this is building ISeq */ return; } @@ -3118,8 +3134,8 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events) const struct rb_iseq_constant_body *const body = iseq->body; VALUE *iseq_encoded = (VALUE *)body->iseq_encoded; rb_event_flag_t enabled_events; - rb_event_flag_t local_events = iseq->local_hooks ? iseq->local_hooks->events : 0; - ((rb_iseq_t *)iseq)->aux.global_trace_events = turnon_events; + rb_event_flag_t local_events = iseq->aux.exec.local_hooks ? iseq->aux.exec.local_hooks->events : 0; + ((rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events; enabled_events = turnon_events | local_events; for (pc=0; pciseq_size;) { -- cgit v1.2.3