[前][次][番号順一覧][スレッド一覧]

ruby-changes:53785

From: ko1 <ko1@a...>
Date: Tue, 27 Nov 2018 03:16:45 +0900 (JST)
Subject: [ruby-changes:53785] ko1:r66003 (trunk): Support targetting TracePoint [Feature #15289]

ko1	2018-11-27 03:16:39 +0900 (Tue, 27 Nov 2018)

  New Revision: 66003

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66003

  Log:
    Support targetting TracePoint [Feature #15289]
    
    * vm_trace.c (rb_tracepoint_enable_for_target): support targetting
      TracePoint. [Feature #15289]
    
      Tragetting TracePoint is only enabled on specified method, proc
      and so on, example: `tp.enable(target: code)`.
    
      `code` should be consisted of InstructionSeuqnece (iseq)
      (RubyVM::InstructionSeuqnece.of(code) should not return nil)
      If code is a tree of iseq, TracePoint is enabled on all of
      iseqs in a tree.
    
      Enabled tragetting TracePoints can not enabled again with
      and without target.
    
    * vm_core.h (rb_iseq_t): introduce `rb_iseq_t::local_hooks`
      to store local hooks.
      `rb_iseq_t::aux::trace_events` is renamed to
      `global_trace_events` to contrast with `local_hooks`.
    
    * vm_core.h (rb_hook_list_t): add `rb_hook_list_t::running`
      to represent how many Threads/Fibers are used this list.
      If this field is 0, nobody using this hooks and we can
      delete it.
    
      This is why we can remove code from cont.c.
    
    * vm_core.h (rb_vm_t): because of above change, we can eliminate
      `rb_vm_t::trace_running` field.
      Also renamed from `rb_vm_t::event_hooks` to `global_hooks`.
    
    * vm_core.h, vm.c (ruby_vm_event_enabled_global_flags): renamed
      from `ruby_vm_event_enabled_flags.
    
    * vm_core.h, vm.c (ruby_vm_event_local_num): added to count
      enabled targetting TracePoints.
    
    * vm_core.h, vm_trace.c (rb_exec_event_hooks): accepts
      hook list.
    
    * vm_core.h (rb_vm_global_hooks): added for convinience.
    
    * method.h (rb_method_bmethod_t): added to maintain Proc
      and `rb_hook_list_t` for bmethod (defined by define_method).
    
    * prelude.rb (TracePoint#enable): extracet a keyword parameter
      (because it is easy than writing in C).
      It calls `TracePoint#__enable` internal method written in C.
    
    * vm_insnhelper.c (vm_trace): check also iseq->local_hooks.
    
    * vm.c (invoke_bmethod): check def->body.bmethod.hooks.
    
    * vm.c (hook_before_rewind): check iseq->local_hooks
      and def->body.bmethod.hooks before rewind by exception.

  Modified files:
    trunk/cont.c
    trunk/gc.c
    trunk/iseq.c
    trunk/iseq.h
    trunk/method.h
    trunk/mjit_worker.c
    trunk/prelude.rb
    trunk/proc.c
    trunk/test/ruby/test_settracefunc.rb
    trunk/thread.c
    trunk/tool/ruby_vm/views/_mjit_compile_insn.erb
    trunk/tool/ruby_vm/views/_mjit_compile_send.erb
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_insnhelper.c
    trunk/vm_method.c
    trunk/vm_trace.c
Index: prelude.rb
===================================================================
--- prelude.rb	(revision 66002)
+++ prelude.rb	(revision 66003)
@@ -132,6 +132,12 @@ class IO https://github.com/ruby/ruby/blob/trunk/prelude.rb#L132
   end
 end
 
+class TracePoint
+  def enable target: nil, &blk
+    self.__enable target, &blk
+  end
+end
+
 class Binding
   # :nodoc:
   def irb
Index: method.h
===================================================================
--- method.h	(revision 66002)
+++ method.h	(revision 66003)
@@ -147,6 +147,11 @@ typedef struct rb_method_refined_struct https://github.com/ruby/ruby/blob/trunk/method.h#L147
     const VALUE owner;
 } rb_method_refined_t;
 
+typedef struct rb_method_bmethod_struct {
+    const VALUE proc; /* should be marked */
+    struct rb_hook_list_struct *hooks;
+} rb_method_bmethod_t;
+
 enum method_optimized_type {
     OPTIMIZED_METHOD_TYPE_SEND,
     OPTIMIZED_METHOD_TYPE_CALL,
@@ -165,9 +170,9 @@ PACKED_STRUCT_UNALIGNED(struct rb_method https://github.com/ruby/ruby/blob/trunk/method.h#L170
 	rb_method_attr_t attr;
 	rb_method_alias_t alias;
 	rb_method_refined_t refined;
+        rb_method_bmethod_t bmethod;
 
-	const VALUE proc;                 /* should be marked */
-	enum method_optimized_type optimize_type;
+        enum method_optimized_type optimize_type;
     } body;
 
     ID original_id;
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 66002)
+++ vm_core.h	(revision 66003)
@@ -474,7 +474,7 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L474
 /* typedef rb_iseq_t is in method.h */
 struct rb_iseq_struct {
     VALUE flags;
-    VALUE reserved1;
+    struct rb_hook_list_struct *local_hooks;
     struct rb_iseq_constant_body *body;
 
     union { /* 4, 5 words */
@@ -485,7 +485,7 @@ struct rb_iseq_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L485
 	    int index;
 	} loader;
 
-	rb_event_flag_t trace_events;
+	rb_event_flag_t global_trace_events;
     } aux;
 };
 
@@ -577,7 +577,8 @@ void rb_objspace_free(struct rb_objspace https://github.com/ruby/ruby/blob/trunk/vm_core.h#L577
 typedef struct rb_hook_list_struct {
     struct rb_event_hook_struct *hooks;
     rb_event_flag_t events;
-    int need_clean;
+    unsigned int need_clean;
+    unsigned int running;
 } rb_hook_list_t;
 
 typedef struct rb_vm_struct {
@@ -608,8 +609,6 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L609
     unsigned int thread_report_on_exception: 1;
 
     unsigned int safe_level_: 1;
-
-    int trace_running;
     int sleeper;
 
     /* object management */
@@ -634,7 +633,7 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L633
     } trap_list;
 
     /* hook */
-    rb_hook_list_t event_hooks;
+    rb_hook_list_t global_hooks;
 
     /* relation table of ensure - rollback for callcc */
     struct st_table *ensure_rollback_table;
@@ -1694,7 +1693,8 @@ RUBY_SYMBOL_EXPORT_BEGIN https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1693
 RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr;
 RUBY_EXTERN rb_execution_context_t *ruby_current_execution_context_ptr;
 RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags;
-RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_flags;
+RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags;
+RUBY_EXTERN unsigned int    ruby_vm_event_local_num;
 
 RUBY_SYMBOL_EXPORT_END
 
@@ -1805,6 +1805,7 @@ rb_vm_check_ints(rb_execution_context_t https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1805
 }
 
 /* tracer */
+
 struct rb_trace_arg_struct {
     rb_event_flag_t event;
     rb_execution_context_t *ec;
@@ -1822,24 +1823,29 @@ struct rb_trace_arg_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1823
     VALUE path;
 };
 
-void rb_exec_event_hooks(struct rb_trace_arg_struct *trace_arg, int pop_p);
+void rb_hook_list_mark(rb_hook_list_t *hooks);
+void rb_hook_list_free(rb_hook_list_t *hooks);
+void rb_hook_list_connect_tracepoint(VALUE target, rb_hook_list_t *list, VALUE tpval);
+void rb_hook_list_remove_tracepoint(rb_hook_list_t *list, VALUE tpval);
 
-#define EXEC_EVENT_HOOK_ORIG(ec_, flag_, vm_flags_, self_, id_, called_id_, klass_, data_, pop_p_) do { \
+void rb_exec_event_hooks(struct rb_trace_arg_struct *trace_arg, rb_hook_list_t *hooks, int pop_p);
+
+#define EXEC_EVENT_HOOK_ORIG(ec_, hooks_, flag_, self_, id_, called_id_, klass_, data_, pop_p_) do { \
     const rb_event_flag_t flag_arg_ = (flag_); \
-    if (UNLIKELY(vm_flags_ & (flag_arg_))) { \
-	/* defer evaluating the other arguments */ \
-	rb_exec_event_hook_orig(ec_, flag_arg_, self_, id_, called_id_, klass_, data_, pop_p_); \
+    rb_hook_list_t *hooks_arg_ = (hooks_); \
+    if (UNLIKELY((hooks_arg_)->events & (flag_arg_))) { \
+        /* defer evaluating the other arguments */ \
+	rb_exec_event_hook_orig(ec_, hooks_arg_, flag_arg_, self_, id_, called_id_, klass_, data_, pop_p_); \
     } \
 } while (0)
 
 static inline void
-rb_exec_event_hook_orig(rb_execution_context_t *ec, const rb_event_flag_t flag,
-			VALUE self, ID id, ID called_id, VALUE klass, VALUE data, int pop_p)
+rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_event_flag_t flag,
+                        VALUE self, ID id, ID called_id, VALUE klass, VALUE data, int pop_p)
 {
     struct rb_trace_arg_struct trace_arg;
 
-    VM_ASSERT(rb_ec_vm_ptr(ec)->event_hooks.events == ruby_vm_event_flags);
-    VM_ASSERT(rb_ec_vm_ptr(ec)->event_hooks.events & flag);
+    VM_ASSERT((hooks->events & flag) != 0);
 
     trace_arg.event = flag;
     trace_arg.ec = ec;
@@ -1851,14 +1857,21 @@ rb_exec_event_hook_orig(rb_execution_con https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1857
     trace_arg.data = data;
     trace_arg.path = Qundef;
     trace_arg.klass_solved = 0;
-    rb_exec_event_hooks(&trace_arg, pop_p);
+
+    rb_exec_event_hooks(&trace_arg, hooks, pop_p);
+}
+
+static inline rb_hook_list_t *
+rb_vm_global_hooks(const rb_execution_context_t *ec)
+{
+    return &rb_ec_vm_ptr(ec)->global_hooks;
 }
 
 #define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \
-  EXEC_EVENT_HOOK_ORIG(ec_, flag_, ruby_vm_event_flags, self_, id_, called_id_, klass_, data_, 0)
+  EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0)
 
 #define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \
-  EXEC_EVENT_HOOK_ORIG(ec_, flag_, ruby_vm_event_flags, self_, id_, called_id_, klass_, data_, 1)
+  EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1)
 
 RUBY_SYMBOL_EXPORT_BEGIN
 
Index: iseq.c
===================================================================
--- iseq.c	(revision 66002)
+++ iseq.c	(revision 66003)
@@ -111,6 +111,11 @@ rb_iseq_free(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L111
 	compile_data_free(ISEQ_COMPILE_DATA(iseq));
 	ruby_xfree(body);
     }
+
+    if (iseq->local_hooks) {
+        rb_hook_list_free(iseq->local_hooks);
+    }
+
     RUBY_FREE_LEAVE("iseq");
 }
 
@@ -247,6 +252,9 @@ rb_iseq_mark(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L252
 	}
     }
 
+    if (iseq->local_hooks) {
+        rb_hook_list_mark(iseq->local_hooks);
+    }
 
     if (FL_TEST(iseq, ISEQ_NOT_LOADED_YET)) {
 	rb_gc_mark(iseq->aux.loader.obj);
@@ -511,9 +519,9 @@ rb_iseq_insns_info_decode_positions(cons https://github.com/ruby/ruby/blob/trunk/iseq.c#L519
 void
 rb_iseq_init_trace(rb_iseq_t *iseq)
 {
-    iseq->aux.trace_events = 0;
-    if (ruby_vm_event_enabled_flags & ISEQ_TRACE_EVENTS) {
-        rb_iseq_trace_set(iseq, ruby_vm_event_enabled_flags & ISEQ_TRACE_EVENTS);
+    iseq->aux.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);
     }
 }
 
@@ -1668,7 +1676,7 @@ rb_iseq_clear_event_flags(const rb_iseq_ https://github.com/ruby/ruby/blob/trunk/iseq.c#L1676
     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.trace_events)) {
+        if (!(entry->events & iseq->aux.global_trace_events)) {
             void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos);
             rb_iseq_trace_flag_cleared(iseq, pos);
         }
@@ -1939,8 +1947,7 @@ rb_iseq_disasm_insn(VALUE ret, const VAL https://github.com/ruby/ruby/blob/trunk/iseq.c#L1947
 			      events & RUBY_EVENT_B_CALL   ? "Bc" : "",
                               events & RUBY_EVENT_B_RETURN ? "Br" : "",
                               events & RUBY_EVENT_COVERAGE_LINE   ? "Cli" : "",
-                              events & RUBY_EVENT_COVERAGE_BRANCH ? "Cbr" : ""
-                              );
+                              events & RUBY_EVENT_COVERAGE_BRANCH ? "Cbr" : "");
 	}
     }
 
@@ -2137,47 +2144,6 @@ rb_iseq_disasm(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2144
     return rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0));
 }
 
-static VALUE
-rb_iseq_all_children(const rb_iseq_t *iseq)
-{
-    unsigned int i;
-    VALUE *code = rb_iseq_original_iseq(iseq);
-    VALUE all_children = rb_obj_hide(rb_ident_hash_new());
-    VALUE child;
-    const struct rb_iseq_constant_body *const body = iseq->body;
-
-    if (body->catch_table) {
-	for (i = 0; i < body->catch_table->size; i++) {
-	    const struct iseq_catch_table_entry *entry = &body->catch_table->entries[i];
-	    child = (VALUE)entry->iseq;
-	    if (child) {
-		rb_hash_aset(all_children, child, Qtrue);
-	    }
-	}
-    }
-    for (i=0; i<body->iseq_size;) {
-	VALUE insn = code[i];
-	int len = insn_len(insn);
-	const char *types = insn_op_types(insn);
-	int j;
-
-	for (j=0; types[j]; j++) {
-	    switch (types[j]) {
-	      case TS_ISEQ:
-		child = code[i+j+1];
-		if (child) {
-		    rb_hash_aset(all_children, child, Qtrue);
-		}
-		break;
-	      default:
-		break;
-	    }
-	}
-	i += len;
-    }
-    return all_children;
-}
-
 /*
  *  call-seq:
  *     iseq.disasm -> str
@@ -2203,10 +2169,58 @@ iseqw_disasm(VALUE self) https://github.com/ruby/ruby/blob/trunk/iseq.c#L2169
 }
 
 static int
-iseqw_each_child_i(VALUE key, VALUE value, VALUE dummy)
+iseq_iterate_children(const rb_iseq_t *iseq, void (*iter_func)(const rb_iseq_t *child_iseq, void *data), void *data)
 {
-    rb_yield(iseqw_new((const rb_iseq_t *)key));
-    return ST_CONTINUE;
+    unsigned int i;
+    VALUE *code = rb_iseq_original_iseq(iseq);
+    const struct rb_iseq_constant_body *const body = iseq->body;
+    const rb_iseq_t *child;
+    VALUE all_children = rb_obj_hide(rb_ident_hash_new());
+
+    if (body->catch_table) {
+        for (i = 0; i < body->catch_table->size; i++) {
+            const struct iseq_catch_table_entry *entry = &body->catch_table->entries[i];
+            child = entry->iseq;
+            if (child) {
+                if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
+                    rb_hash_aset(all_children, (VALUE)child, Qtrue);
+                    (*iter_func)(child, data);
+                }
+            }
+        }
+    }
+
+    for (i=0; i<body->iseq_size;) {
+        VALUE insn = code[i];
+        int len = insn_len(insn);
+        const char *types = insn_op_types(insn);
+        int j;
+
+        for (j=0; types[j]; j++) {
+            switch (types[j]) {
+              case TS_ISEQ:
+                child = (const rb_iseq_t *)code[i+j+1];
+                if (child) {
+                    if (rb_hash_aref(all_children, (VALUE)child) == Qnil) {
+                        rb_hash_aset(all_children, (VALUE)child, Qtrue);
+                        (*iter_func)(child, data);
+                    }
+                }
+                break;
+              default:
+                break;
+            }
+        }
+        i += len;
+    }
+
+    return RHASH_SIZE(all_children);
+}
+
+static void
+yield_each_children(const rb_iseq_t *child_iseq, void *data)
+{
+    rb_yield(iseqw_new(child_iseq));
 }
 
 /*
@@ -2221,8 +2235,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/iseq.c#L2235
 iseqw_each_child(VALUE self)
 {
     const rb_iseq_t *iseq = iseqw_check(self);
-    VALUE all_children = rb_iseq_all_children(iseq);
-    rb_hash_foreach(all_children, iseqw_each_child_i, Qnil);
+    iseq_iterate_children(iseq, yield_each_children, NULL);
     return self;
 }
 
@@ -2966,12 +2979,111 @@ rb_iseq_trace_flag_cleared(const rb_iseq https://github.com/ruby/ruby/blob/trunk/iseq.c#L2979
     encoded_iseq_trace_instrument(&iseq_encoded[pos], 0);
 }
 
+static int
+iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval)
+{
+    unsigned int pc;
+    int n = 0;
+    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);
+
+    for (pc=0; pc<body->iseq_size;) {
+        rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
+        if (pc_events & turnon_events) {
+            n++;
+        }
+        pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (turnon_events | iseq->aux.global_trace_events));
+    }
+
+    if (n > 0) {
+        if (iseq->local_hooks == NULL) {
+            ((rb_iseq_t *)iseq)->local_hooks = RB_ZALLOC(rb_hook_list_t);
+        }
+        rb_hook_list_connect_tracepoint((VALUE)iseq, iseq->local_hooks, tpval);
+    }
+
+    return n;
+}
+
+struct trace_set_local_events_struct {
+    rb_event_flag_t turnon_events;
+    VALUE tpval;
+    int n;
+};
+
+static void
+iseq_add_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
+{
+    struct trace_set_local_events_struct *data = (struct trace_set_local_events_struct *)p;
+    data->n += iseq_add_local_tracepoint(iseq, data->turnon_events, data->tpval);
+    iseq_iterate_children(iseq, iseq_add_local_tracepoint_i, p);
+}
+
+int
+rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval)
+{
+    struct trace_set_local_events_struct data = {turnon_events, tpval, 0};
+    iseq_add_local_tracepoint_i(iseq, (void *)&data);
+    if (0) rb_funcall(Qnil, rb_intern("puts"), 1, rb_iseq_disasm(iseq)); /* for debug */
+    return data.n;
+}
+
+static int
+iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
+{
+    int n = 0;
+
+    if (iseq->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;
+
+        if (local_events == 0) {
+            if (iseq->local_hooks->running == 0) {
+                rb_hook_list_free(iseq->local_hooks);
+            }
+            ((rb_iseq_t *)iseq)->local_hooks = NULL;
+        }
+
+        for (pc = 0; pc<body->iseq_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));
+        }
+    }
+    return n;
+}
+
+struct trace_clear_local_events_struct {
+    VALUE tpval;
+    int n;
+};
+
+static void
+iseq_remove_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
+{
+    struct trace_clear_local_events_struct *data = (struct trace_clear_local_events_struct *)p;
+    data->n += iseq_remove_local_tracepoint(iseq, data->tpval);
+    iseq_iterate_children(iseq, iseq_remove_local_tracepoint_i, p);
+}
+
+int
+rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval)
+{
+    struct trace_clear_local_events_struct data = {tpval, 0};
+    iseq_remove_local_tracepoint_i(iseq, (void *)&data);
+    return data.n;
+}
+
 void
 rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
 {
-    VM_ASSERT((turnon_events & ~ISEQ_TRACE_EVENTS) == 0);
-
-    if (iseq->aux.trace_events == turnon_events) {
+    if (iseq->aux.global_trace_events == turnon_events) {
 	return;
     }
     if (iseq->flags & ISEQ_USE_COMPILE_DATA) {
@@ -2979,16 +3091,18 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/iseq.c#L3091
 	return;
     }
     else {
-	unsigned int i;
+	unsigned int pc;
 	const struct rb_iseq_constant_body *const body = iseq->body;
 	VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
-	((rb_iseq_t *)iseq)->aux.trace_events = turnon_events;
-
-	for (i=0; i<body->iseq_size;) {
-	    rb_event_flag_t events = rb_iseq_event_flags(iseq, i);
-            i += encoded_iseq_trace_instrument(&iseq_encoded[i], events & turnon_events);
+        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;
+        enabled_events = turnon_events | local_events;
+
+        for (pc=0; pc<body->iseq_size;) {
+	    rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
+            pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events);
 	}
-	/* clear for debugging: ISEQ_ORIGINAL_ISEQ_CLEAR(iseq); */
     }
 }
 
@@ -3013,7 +3127,7 @@ rb_iseq_trace_set_all(rb_event_flag_t tu https://github.com/ruby/ruby/blob/trunk/iseq.c#L3127
 }
 
 /* This is exported since Ruby 2.5 but not internally used for now. If you're going to use this, please
-   update `ruby_vm_event_enabled_flags` and set `mjit_call_p = FALSE` as well to cancel MJIT code. */
+   update `ruby_vm_event_enabled_global_flags` and set `mjit_call_p = FALSE` as well to cancel MJIT code. */
 void
 rb_iseq_trace_on_all(void)
 {
Index: iseq.h
===================================================================
--- iseq.h	(revision 66002)
+++ iseq.h	(revision 66003)
@@ -148,6 +148,8 @@ void rb_ibf_load_iseq_complete(rb_iseq_t https://github.com/ruby/ruby/blob/trunk/iseq.h#L148
 const rb_iseq_t *rb_iseq_ibf_load(VALUE str);
 VALUE rb_iseq_ibf_load_extra_data(VALUE str);
 void rb_iseq_init_trace(rb_iseq_t *iseq);
+int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval);
+int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
 
 #if VM_INSN_INFO_TABLE_IMPL == 2
 unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body);
Index: proc.c
===================================================================
--- proc.c	(revision 66002)
+++ proc.c	(revision 66003)
@@ -2342,7 +2342,7 @@ rb_method_entry_min_max_arity(const rb_m https://github.com/ruby/ruby/blob/trunk/proc.c#L2342
 	def = def->body.alias.original_me->def;
 	goto again;
       case VM_METHOD_TYPE_BMETHOD:
-	return rb_proc_min_max_arity(def->body.proc, max);
+	return rb_proc_min_max_arity(def->body.bmethod.proc, max);
       case VM_METHOD_TYPE_ISEQ:
 	return rb_iseq_min_max_arity(rb_iseq_check(def->body.iseq.iseqptr), max);
       case VM_METHOD_TYPE_UNDEF:
@@ -2478,8 +2478,8 @@ rb_obj_method_arity(VALUE obj, ID id) https://github.com/ruby/ruby/blob/trunk/proc.c#L2478
     return rb_mod_method_arity(CLASS_OF(obj), id);
 }
 
-static inline const rb_method_definition_t *
-method_def(VALUE method)
+const rb_method_definition_t *
+rb_method_def(VALUE method)
 {
     const struct METHOD *data;
 
@@ -2494,7 +2494,7 @@ method_def_iseq(const rb_method_definiti https://github.com/ruby/ruby/blob/trunk/proc.c#L2494
       case VM_METHOD_TYPE_ISEQ:
 	return rb_iseq_check(def->body.iseq.iseqptr);
       case VM_METHOD_TYPE_BMETHOD:
-	return rb_proc_get_iseq(def->body.proc, 0);
+	return rb_proc_get_iseq(def->body.bmethod.proc, 0);
       case VM_METHOD_TYPE_ALIAS:
 	return meth (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]