1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Rewrite Kernel#tap with Ruby (#3281)

* Rewrite Kernel#tap with Ruby

This was good for VM too, but of course my intention is to unblock JIT's inlining of a block over yield
(inlining invokeyield has not been committed though).

* Fix test_settracefunc

About the :tap deletions, the :tap events are actually traced (we already have a TracePoint test for builtin methods),
but it's filtered out by tp.path == "xyzzy" (it became "<internal:kernel>"). We could trace tp.path == "<internal:kernel>"
cases too, but the lineno is impacted by kernel.rb changes and I didn't want to make it fragile for kernel.rb lineno changes.
This commit is contained in:
Takashi Kokubun 2020-07-03 09:52:35 -07:00 committed by GitHub
parent e8010c7401
commit f3a0d7a203
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2020-07-04 01:53:09 +09:00
Merged-By: k0kubun <takashikkbn@gmail.com>
4 changed files with 32 additions and 38 deletions

6
benchmark/kernel_tap.yml Normal file
View file

@ -0,0 +1,6 @@
prelude: |
obj = Object.new
x = nil
benchmark:
kernel_tap: obj.tap { |o| x = o }
loop_count: 20000000

View file

@ -48,6 +48,28 @@ module Kernel
Primitive.rb_obj_clone2(freeze)
end
#
# call-seq:
# obj.tap {|x| block } -> obj
#
# Yields self to the block, and then returns self.
# The primary purpose of this method is to "tap into" a method chain,
# in order to perform operations on intermediate results within the chain.
#
# (1..10) .tap {|x| puts "original: #{x}" }
# .to_a .tap {|x| puts "array: #{x}" }
# .select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
# .map {|x| x*x } .tap {|x| puts "squares: #{x}" }
#
#--
# \private
#++
#
def tap
yield(self)
self
end
module_function
#

View file

@ -938,31 +938,6 @@ rb_class_search_ancestor(VALUE cl, VALUE c)
return class_search_ancestor(cl, RCLASS_ORIGIN(c));
}
/**
* call-seq:
* obj.tap {|x| block } -> obj
*
* Yields self to the block, and then returns self.
* The primary purpose of this method is to "tap into" a method chain,
* in order to perform operations on intermediate results within the chain.
*
* (1..10) .tap {|x| puts "original: #{x}" }
* .to_a .tap {|x| puts "array: #{x}" }
* .select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
* .map {|x| x*x } .tap {|x| puts "squares: #{x}" }
*
*--
* \private
*++
*/
VALUE
rb_obj_tap(VALUE obj)
{
rb_yield(obj);
return obj;
}
/*
* Document-method: inherited
@ -4638,7 +4613,6 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
rb_define_global_function("sprintf", f_sprintf, -1);
rb_define_global_function("format", f_sprintf, -1);

View file

@ -485,8 +485,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
[:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing],
[:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self],
[:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
[:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
@ -512,8 +510,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing],
[:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing],
[:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy],
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
@ -610,8 +606,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
[:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing],
[:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self],
[:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
[:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
@ -637,8 +631,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing],
[:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing],
[:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy],
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
@ -1685,7 +1677,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
TracePoint.new(:return, &capture_events).enable{
o.alias_m
}
assert_equal [[:return, :m, :alias_m]], events
assert_equal [[:return, :tap, :tap], [:return, :m, :alias_m]], events
events.clear
o = Class.new{
@ -1709,13 +1701,13 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.clear
o = Class.new{
alias alias_tap tap
define_method(:m){alias_tap{return}}
alias alias_singleton_class singleton_class
define_method(:m){alias_singleton_class}
}.new
TracePoint.new(:c_return, &capture_events).enable{
o.m
}
assert_equal [[:c_return, :tap, :alias_tap]], events
assert_equal [[:c_return, :singleton_class, :alias_singleton_class]], events
events.clear
c = Class.new{