From 7deeb9c1b608101b3ce04792aaeac1726bddcdbe Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Fri, 24 Jun 2011 09:52:47 -0700 Subject: [PATCH] Eliminate usage of ObjectSpace._id2ref Two reasons not to use _id2ref: 1) It's slow on other ruby implementations 2) It introduces a hidden bug because _id2ref can return any random future object since object ids are recycled --- lib/rr/injections/double_injection.rb | 15 +++++++++++---- lib/rr/injections/method_missing_injection.rb | 9 +++++++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/rr/injections/double_injection.rb b/lib/rr/injections/double_injection.rb index 3c106c87..0ce4e13e 100644 --- a/lib/rr/injections/double_injection.rb +++ b/lib/rr/injections/double_injection.rb @@ -119,11 +119,15 @@ def bind self end + BoundObjects = {} + def bind_method_that_self_destructs_and_delegates_to_method_missing - subject_class_object_id = subject_class.object_id + id = BoundObjects.size + BoundObjects[id] = subject_class + subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{method_name}(*args, &block) - ObjectSpace._id2ref(#{subject_class_object_id}).class_eval do + ::RR::Injections::DoubleInjection::BoundObjects[#{id}].class_eval do remove_method(:#{method_name}) end method_missing(:#{method_name}, *args, &block) @@ -133,11 +137,14 @@ def #{method_name}(*args, &block) end def bind_method - subject_class_object_id = subject_class.object_id + id = BoundObjects.size + BoundObjects[id] = subject_class + subject_class.class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{method_name}(*args, &block) arguments = MethodArguments.new(args, block) - RR::Injections::DoubleInjection.dispatch_method(self, ObjectSpace._id2ref(#{subject_class_object_id}), :#{method_name}, arguments.arguments, arguments.block) + obj = ::RR::Injections::DoubleInjection::BoundObjects[#{id}] + RR::Injections::DoubleInjection.dispatch_method(self, obj, :#{method_name}, arguments.arguments, arguments.block) end RUBY self diff --git a/lib/rr/injections/method_missing_injection.rb b/lib/rr/injections/method_missing_injection.rb index d8f27428..d0421fb9 100644 --- a/lib/rr/injections/method_missing_injection.rb +++ b/lib/rr/injections/method_missing_injection.rb @@ -51,11 +51,16 @@ def reset end protected + BoundObjects = {} + def bind_method - subject_class_object_id = subject_class.object_id + id = BoundObjects.size + BoundObjects[id] = subject_class + subject_class.class_eval((<<-METHOD), __FILE__, __LINE__ + 1) def method_missing(method_name, *args, &block) - MethodDispatches::MethodMissingDispatch.new(self, ObjectSpace._id2ref(#{subject_class_object_id}), method_name, args, block).call + obj = ::RR::Injections::MethodMissingInjection::BoundObjects[#{id}] + MethodDispatches::MethodMissingDispatch.new(self, obj, method_name, args, block).call end METHOD end