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

ruby-changes:62116

From: Takashi <ko1@a...>
Date: Sat, 4 Jul 2020 10:02:59 +0900 (JST)
Subject: [ruby-changes:62116] 24fa37d87a (master): Make Kernel#then, #yield_self, #frozen? builtin (#3283)

https://git.ruby-lang.org/ruby.git/commit/?id=24fa37d87a

From 24fa37d87a24dc932c1d778bcaf91204f5c12a76 Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Fri, 3 Jul 2020 18:02:43 -0700
Subject: Make Kernel#then, #yield_self, #frozen? builtin (#3283)

* Make Kernel#then, #yield_self, #frozen? builtin

* Fix test_jit

diff --git a/benchmark/kernel_then.yml b/benchmark/kernel_then.yml
new file mode 100644
index 0000000..85f7341
--- /dev/null
+++ b/benchmark/kernel_then.yml
@@ -0,0 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/kernel_then.yml#L1
+benchmark:
+  kernel_then: 1.then { |i| i + 1 }
+  kernel_then_enum: 1.then
+  kernel_yield_self: 1.yield_self { |i| i + 1 }
+  kernel_yield_self_enum: 1.yield_self
+loop_count: 20000000
diff --git a/benchmark/mjit_class.yml b/benchmark/mjit_class.yml
deleted file mode 100644
index 22f95c2..0000000
--- a/benchmark/mjit_class.yml
+++ /dev/null
@@ -1,11 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/kernel_then.yml#L0
-type: lib/benchmark_driver/runner/mjit
-prelude: |
-  def mjit_class(obj)
-    obj.class
-  end
-
-benchmark:
-  - mjit_class(self)
-  - mjit_class(1)
-
-loop_count: 40000000
diff --git a/benchmark/mjit_kernel.yml b/benchmark/mjit_kernel.yml
new file mode 100644
index 0000000..7720e65
--- /dev/null
+++ b/benchmark/mjit_kernel.yml
@@ -0,0 +1,20 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/mjit_kernel.yml#L1
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+  def mjit_class(obj)
+    obj.class
+  end
+
+  def mjit_frozen?(obj)
+    obj.frozen?
+  end
+
+  str = ""
+  fstr = "".freeze
+
+benchmark:
+  - mjit_class(self)
+  - mjit_class(1)
+  - mjit_frozen?(str)
+  - mjit_frozen?(fstr)
+
+loop_count: 40000000
diff --git a/kernel.rb b/kernel.rb
index 3404053..04a371a 100644
--- a/kernel.rb
+++ b/kernel.rb
@@ -50,6 +50,27 @@ module Kernel https://github.com/ruby/ruby/blob/trunk/kernel.rb#L50
 
   #
   #  call-seq:
+  #     obj.frozen?    -> true or false
+  #
+  #  Returns the freeze status of <i>obj</i>.
+  #
+  #     a = [ "a", "b", "c" ]
+  #     a.freeze    #=> ["a", "b", "c"]
+  #     a.frozen?   #=> true
+  #--
+  # Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby.
+  # \param[in] obj  the object to be determines
+  # \retval Qtrue if frozen
+  # \retval Qfalse if not frozen
+  #++
+  #
+  def frozen?
+    Primitive.attr! 'inline'
+    Primitive.cexpr! 'rb_obj_frozen_p(self)'
+  end
+
+  #
+  #  call-seq:
   #     obj.tap {|x| block }    -> obj
   #
   #  Yields self to the block, and then returns self.
@@ -70,6 +91,63 @@ module Kernel https://github.com/ruby/ruby/blob/trunk/kernel.rb#L91
     self
   end
 
+  #
+  #  call-seq:
+  #     obj.then {|x| block }          -> an_object
+  #
+  #  Yields self to the block and returns the result of the block.
+  #
+  #     3.next.then {|x| x**x }.to_s             #=> "256"
+  #
+  #  Good usage for +then+ is value piping in method chains:
+  #
+  #     require 'open-uri'
+  #     require 'json'
+  #
+  #     construct_url(arguments).
+  #       then {|url| open(url).read }.
+  #       then {|response| JSON.parse(response) }
+  #
+  #  When called without block, the method returns +Enumerator+,
+  #  which can be used, for example, for conditional
+  #  circuit-breaking:
+  #
+  #     # meets condition, no-op
+  #     1.then.detect(&:odd?)            # => 1
+  #     # does not meet condition, drop value
+  #     2.then.detect(&:odd?)            # => nil
+  #
+  def then
+    unless Primitive.block_given_p
+      return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
+    end
+    yield(self)
+  end
+
+  #
+  #  call-seq:
+  #     obj.yield_self {|x| block }    -> an_object
+  #
+  #  Yields self to the block and returns the result of the block.
+  #
+  #     "my string".yield_self {|s| s.upcase }   #=> "MY STRING"
+  #
+  #  Good usage for +then+ is value piping in method chains:
+  #
+  #     require 'open-uri'
+  #     require 'json'
+  #
+  #     construct_url(arguments).
+  #       then {|url| open(url).read }.
+  #       then {|response| JSON.parse(response) }
+  #
+  def yield_self
+    unless Primitive.block_given_p
+      return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
+    end
+    yield(self)
+  end
+
   module_function
 
   #
diff --git a/object.c b/object.c
index 4718fad..a684927 100644
--- a/object.c
+++ b/object.c
@@ -597,41 +597,10 @@ rb_obj_size(VALUE self, VALUE args, VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L597
     return LONG2FIX(1);
 }
 
-/*
- *  call-seq:
- *     obj.then {|x| block }          -> an_object
- *     obj.yield_self {|x| block }    -> an_object
- *
- *  Yields self to the block and returns the result of the block.
- *
- *     3.next.then {|x| x**x }.to_s             #=> "256"
- *     "my string".yield_self {|s| s.upcase }   #=> "MY STRING"
- *
- *  Good usage for +then+ is value piping in method chains:
- *
- *     require 'open-uri'
- *     require 'json'
- *
- *     construct_url(arguments).
- *       then {|url| open(url).read }.
- *       then {|response| JSON.parse(response) }
- *
- *  When called without block, the method returns +Enumerator+,
- *  which can be used, for example, for conditional
- *  circuit-breaking:
- *
- *     # meets condition, no-op
- *     1.then.detect(&:odd?)            # => 1
- *     # does not meet condition, drop value
- *     2.then.detect(&:odd?)            # => nil
- *
- */
-
 static VALUE
-rb_obj_yield_self(VALUE obj)
+block_given_p(rb_execution_context_t *ec, VALUE self)
 {
-    RETURN_SIZED_ENUMERATOR(obj, 0, 0, rb_obj_size);
-    return rb_yield_values2(1, &obj);
+    return rb_block_given_p() ? Qtrue : Qfalse;
 }
 
 /**
@@ -1321,23 +1290,6 @@ rb_obj_freeze(VALUE obj) https://github.com/ruby/ruby/blob/trunk/object.c#L1290
     return obj;
 }
 
-/**
- *  call-seq:
- *     obj.frozen?    -> true or false
- *
- *  Returns the freeze status of <i>obj</i>.
- *
- *     a = [ "a", "b", "c" ]
- *     a.freeze    #=> ["a", "b", "c"]
- *     a.frozen?   #=> true
- *--
- * Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby.
- * \param[in] obj  the object to be determines
- * \retval Qtrue if frozen
- * \retval Qfalse if not frozen
- *++
- */
-
 VALUE
 rb_obj_frozen_p(VALUE obj)
 {
@@ -4581,8 +4533,6 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4533
     rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
     rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
     rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0);
-    rb_define_method(rb_mKernel, "yield_self", rb_obj_yield_self, 0);
-    rb_define_method(rb_mKernel, "then", rb_obj_yield_self, 0);
     rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
     rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1);
     rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_clone, -1);
@@ -4594,7 +4544,6 @@ InitVM_Object(void) https://github.com/ruby/ruby/blob/trunk/object.c#L4544
     rb_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted, 0);
     rb_define_method(rb_mKernel, "trust", rb_obj_trust, 0);
     rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
-    rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
 
     rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
     rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 339bfa2..f929a8c 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -372,7 +372,7 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L372
   end
 
   def test_compile_insn_send
-    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send])
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send])
     begin;
       print proc { yield_self { 1 } }.call
     end;
-- 
cgit v0.10.2


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

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