aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-30 02:28:59 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-30 02:28:59 +0000
commit6fd18ca51bbce302865d23632b15af53d3e8f11b (patch)
treeadd72ea5a4f487a58f983d11633b879d0f43b100
parentd8eb5ade4f9bbc083b1cf93717fe97098411bec7 (diff)
downloadruby-6fd18ca51bbce302865d23632b15af53d3e8f11b.tar.gz
forwardable.rb: adjust backtrace by tail call
* lib/forwardable.rb (def_instance_delegator): adjust backtrace of method body by tail call optimization. adjusting the delegated target is still done by deleting backtrace. * lib/forwardable.rb (def_single_delegator): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53383 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog8
-rw-r--r--lib/forwardable.rb46
-rw-r--r--test/test_forwardable.rb2
3 files changed, 38 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index b535efeb4f..d3118cf40d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Wed Dec 30 11:28:57 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/forwardable.rb (def_instance_delegator): adjust backtrace of
+ method body by tail call optimization. adjusting the delegated
+ target is still done by deleting backtrace.
+
+ * lib/forwardable.rb (def_single_delegator): ditto.
+
Wed Dec 30 11:18:42 2015 Elliot Winkler <elliot.winkler@gmail.com>
* lib/forwardable.rb (def_instance_delegator) fix delegating to
diff --git a/lib/forwardable.rb b/lib/forwardable.rb
index f27437af82..390e1460cf 100644
--- a/lib/forwardable.rb
+++ b/lib/forwardable.rb
@@ -182,23 +182,28 @@ module Forwardable
accessor = "#{accessor}()"
end
- line_no = __LINE__; str = %{
+ line_no = __LINE__; str = %{proc do
def #{ali}(*args, &block)
begin
- #{accessor}.__send__(:#{method}, *args, &block)
- rescue ::Exception
- $@.delete_if{|s| ::Forwardable::FILE_REGEXP =~ s} unless ::Forwardable::debug
- ::Kernel::raise
- end
+ #{accessor}
+ ensure
+ $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug
+ end.__send__(:#{method}, *args, &block)
end
- }
+ end}
+
+ gen = RubyVM::InstructionSequence
+ .compile(str, __FILE__, __FILE__, line_no,
+ trace_instruction: false,
+ tailcall_optimization: true)
+ .eval
+
# If it's not a class or module, it's an instance
begin
- module_eval(str, __FILE__, line_no)
+ module_eval(&gen)
rescue
- instance_eval(str, __FILE__, line_no)
+ instance_eval(&gen)
end
-
end
alias delegate instance_delegate
@@ -278,18 +283,23 @@ module SingleForwardable
accessor = "#{accessor}()"
end
- line_no = __LINE__; str = %{
+ line_no = __LINE__; str = %{proc do
def #{ali}(*args, &block)
begin
- #{accessor}.__send__(:#{method}, *args, &block)
- rescue ::Exception
- $@.delete_if{|s| ::Forwardable::FILE_REGEXP =~ s} unless ::Forwardable::debug
- ::Kernel::raise
- end
+ #{accessor}
+ ensure
+ $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} if $@ and !::Forwardable::debug
+ end.__send__(:#{method}, *args, &block)
end
- }
+ end}
+
+ gen = RubyVM::InstructionSequence
+ .compile(str, __FILE__, __FILE__, line_no,
+ trace_instruction: false,
+ tailcall_optimization: true)
+ .eval
- instance_eval(str, __FILE__, line_no)
+ instance_eval(&gen)
end
alias delegate single_delegate
diff --git a/test/test_forwardable.rb b/test/test_forwardable.rb
index a474e4ad76..550280de19 100644
--- a/test/test_forwardable.rb
+++ b/test/test_forwardable.rb
@@ -187,6 +187,7 @@ class TestForwardable < Test::Unit::TestCase
extend Forwardable
def_delegator :bar, :baz
+ def_delegator :caller, :itself, :c
class Exception
end
@@ -197,6 +198,7 @@ class TestForwardable < Test::Unit::TestCase
Foo.new.baz
}
assert_not_match(/\/forwardable\.rb/, e.backtrace[0])
+ assert_equal(caller(0, 1)[0], Foo.new.c[0])
end
class Foo2 < BasicObject