Skip to content

Instantly share code, notes, and snippets.

@methodmissing
Created January 6, 2010 23:21
Show Gist options
  • Select an option

  • Save methodmissing/270794 to your computer and use it in GitHub Desktop.

Select an option

Save methodmissing/270794 to your computer and use it in GitHub Desktop.
diff --git a/eval.c b/eval.c
index 057afd9..aa50cb5 100644
--- a/eval.c
+++ b/eval.c
@@ -371,69 +371,10 @@ struct cache_entry { /* method hash table. */
static struct cache_entry cache[CACHE_SIZE];
static int ruby_running = 0;
-void
-rb_clear_cache()
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- ent->mid = 0;
- ent++;
- }
-}
-
-static void
-rb_clear_cache_for_undef(klass, id)
- VALUE klass;
- ID id;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->mid == id &&
- (ent->klass == klass ||
- RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl)) {
- ent->mid = 0;
- }
- ent++;
- }
-}
-
-static void
-rb_clear_cache_by_id(id)
- ID id;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->mid == id) {
- ent->mid = 0;
- }
- ent++;
- }
-}
-
-void
-rb_clear_cache_by_class(klass)
- VALUE klass;
-{
- struct cache_entry *ent, *end;
-
- if (!ruby_running) return;
- ent = cache; end = ent + CACHE_SIZE;
- while (ent < end) {
- if (ent->klass == klass || ent->origin == klass) {
- ent->mid = 0;
- }
- ent++;
- }
-}
+void rb_clear_cache();
+static void rb_clear_cache_for_undef(VALUE klass, ID id);
+static void rb_clear_cache_by_id(ID id);
+void rb_clear_cache_by_class(VALUE klass);
static ID init, eqq, each, aref, aset, match, missing;
static ID added, singleton_added;
@@ -1213,6 +1154,73 @@ static VALUE trace_func = 0;
static int tracing = 0;
static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE));
+void
+rb_clear_cache()
+{
+ struct cache_entry *ent, *end;
+ if (!ruby_running) return;
+ EXEC_EVENT_HOOK(RUBY_EVENT_METHOD_CACHE_CLEARED, ruby_current_node,
+ ruby_frame->self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ ent->mid = 0;
+ ent++;
+ }
+}
+
+static void
+rb_clear_cache_for_undef(klass, id)
+ VALUE klass;
+ ID id;
+{
+ struct cache_entry *ent, *end;
+
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->mid == id &&
+ (ent->klass == klass ||
+ RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl)) {
+ ent->mid = 0;
+ }
+ ent++;
+ }
+}
+
+static void
+rb_clear_cache_by_id(id)
+ ID id;
+{
+ struct cache_entry *ent, *end;
+
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->mid == id) {
+ ent->mid = 0;
+ }
+ ent++;
+ }
+}
+
+void
+rb_clear_cache_by_class(klass)
+ VALUE klass;
+{
+ struct cache_entry *ent, *end;
+
+ if (!ruby_running) return;
+ ent = cache; end = ent + CACHE_SIZE;
+ while (ent < end) {
+ if (ent->klass == klass || ent->origin == klass) {
+ ent->mid = 0;
+ }
+ ent++;
+ }
+}
+
static void
#ifdef HAVE_STDARG_PROTOTYPES
warn_printf(const char *fmt, ...)
@@ -2740,6 +2748,8 @@ get_event_name(rb_event_t event)
return "c-return";
case RUBY_EVENT_RAISE:
return "raise";
+ case RUBY_EVENT_METHOD_CACHE_CLEARED:
+ return "method-cache-cleared";
default:
return "unknown";
}
diff --git a/node.h b/node.h
index 1242be5..d7edbdb 100644
--- a/node.h
+++ b/node.h
@@ -359,16 +359,17 @@ VALUE rb_gvar_defined _((struct global_entry *));
typedef unsigned int rb_event_t;
-#define RUBY_EVENT_NONE 0x00
-#define RUBY_EVENT_LINE 0x01
-#define RUBY_EVENT_CLASS 0x02
-#define RUBY_EVENT_END 0x04
-#define RUBY_EVENT_CALL 0x08
-#define RUBY_EVENT_RETURN 0x10
-#define RUBY_EVENT_C_CALL 0x20
-#define RUBY_EVENT_C_RETURN 0x40
-#define RUBY_EVENT_RAISE 0x80
-#define RUBY_EVENT_ALL 0xff
+#define RUBY_EVENT_NONE 0x00
+#define RUBY_EVENT_LINE 0x01
+#define RUBY_EVENT_CLASS 0x02
+#define RUBY_EVENT_END 0x04
+#define RUBY_EVENT_CALL 0x08
+#define RUBY_EVENT_RETURN 0x10
+#define RUBY_EVENT_C_CALL 0x20
+#define RUBY_EVENT_C_RETURN 0x40
+#define RUBY_EVENT_RAISE 0x80
+#define RUBY_EVENT_METHOD_CACHE_CLEARED 0x81
+#define RUBY_EVENT_ALL 0xff
typedef void (*rb_event_hook_func_t) _((rb_event_t,NODE*,VALUE,ID,VALUE));
NODE *rb_copy_node_scope _((NODE *, NODE *));
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 14d6679..a5bd3cc 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -33,6 +33,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
rescue
end
eval("class Foo; end")
+ Foo.__send__ :include, Comparable
set_trace_func nil
assert_equal(["line", 19, :test_event, TestSetTraceFunc],
@@ -122,8 +123,28 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal(["c-return", 35, :eval, Kernel],
events.shift) # eval(<<EOF)
assert_equal(["line", 36, :test_event, TestSetTraceFunc],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-call", 36, :__send__, Kernel],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-call", 36, :include, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-call", 36, :append_features, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["method-cache-cleared", 36, :append_features, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-return", 36, :append_features, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-call", 36, :included, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-return", 36, :included, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-return", 36, :include, Module],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["c-return", 36, :__send__, Kernel],
+ events.shift) # Foo.__send__ :include, Comparable
+ assert_equal(["line", 37, :test_event, TestSetTraceFunc],
events.shift) # set_trace_func nil
- assert_equal(["c-call", 36, :set_trace_func, Kernel],
+ assert_equal(["c-call", 37, :set_trace_func, Kernel],
events.shift) # set_trace_func nil
assert_equal([], events)
@@ -131,8 +152,8 @@ class TestSetTraceFunc < Test::Unit::TestCase
set_trace_func(nil)
assert_equal(["line", 11, :bar, TestSetTraceFunc], events.shift)
assert_equal(["return", 11, :bar, TestSetTraceFunc], events.shift)
- assert_equal(["line", 131, :test_event, TestSetTraceFunc], events.shift)
- assert_equal(["c-call", 131, :set_trace_func, Kernel], events.shift)
+ assert_equal(["line", 152, :test_event, TestSetTraceFunc], events.shift)
+ assert_equal(["c-call", 152, :set_trace_func, Kernel], events.shift)
assert_equal([], events)
end
end
methodmissing:rubyenterpriseedition187-248 lourens$ ./miniruby subject.rb
["subject.rb:15 Module#append_features", "subject.rb:20 Module#extend_object"]
invalidations = []
set_trace_func(Proc.new { |event, file, lineno, mid, bidning, klass|
invalidations << "#{file}:#{lineno} #{klass}##{mid}" if event == 'method-cache-cleared'
})
module A
def to_s; 'A'; end
end
module B
def to_s; 'B'; end
end
class Test
include A
undef to_s
end
t = Test.new
t.extend B
t.to_s
set_trace_func(nil)
puts invalidations.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment