summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorS.H <gamelinks007@gmail.com>2020-03-17 19:37:07 +0900
committerGitHub <noreply@github.com>2020-03-17 19:37:07 +0900
commit290d608637e37323bb6eeda1b1466519f16308a5 (patch)
treea15dfc4dd8299b936999e8ddc3c5f70729858a71
parentd514ba8e17106c6d159c3902ac5456d6269731f8 (diff)
support builtin for Kernel#clone
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2954 Merged-By: nobu <nobu@ruby-lang.org>
-rw-r--r--.document1
-rw-r--r--benchmark/kernel_clone.yml6
-rw-r--r--common.mk4
-rw-r--r--inits.c1
-rw-r--r--kernel.rb29
-rw-r--r--object.c51
6 files changed, 59 insertions, 33 deletions
diff --git a/.document b/.document
index a5018a6cdc..1cb2722327 100644
--- a/.document
+++ b/.document
@@ -14,6 +14,7 @@ array.rb
ast.rb
gc.rb
io.rb
+kernel.rb
pack.rb
trace_point.rb
warning.rb
diff --git a/benchmark/kernel_clone.yml b/benchmark/kernel_clone.yml
new file mode 100644
index 0000000000..069b23abcd
--- /dev/null
+++ b/benchmark/kernel_clone.yml
@@ -0,0 +1,6 @@
+prelude: "object = Object.new"
+benchmark:
+ clone: "object.clone"
+ clone_true: "object.clone(freeze: true)"
+ clone_false: "object.clone(freeze: false)"
+loop_count: 10000
diff --git a/common.mk b/common.mk
index 60e72047e2..8182eb7865 100644
--- a/common.mk
+++ b/common.mk
@@ -1003,6 +1003,7 @@ BUILTIN_RB_SRCS = \
$(srcdir)/trace_point.rb \
$(srcdir)/warning.rb \
$(srcdir)/array.rb \
+ $(srcdir)/kernel.rb \
$(srcdir)/prelude.rb \
$(srcdir)/gem_prelude.rb \
$(empty)
@@ -2848,6 +2849,7 @@ miniinit.$(OBJEXT): {$(VPATH)}intern.h
miniinit.$(OBJEXT): {$(VPATH)}internal.h
miniinit.$(OBJEXT): {$(VPATH)}io.rb
miniinit.$(OBJEXT): {$(VPATH)}iseq.h
+miniinit.$(OBJEXT): {$(VPATH)}kernel.rb
miniinit.$(OBJEXT): {$(VPATH)}method.h
miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
@@ -3101,6 +3103,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/variable.h
object.$(OBJEXT): $(top_srcdir)/internal/vm.h
object.$(OBJEXT): $(top_srcdir)/internal/warnings.h
object.$(OBJEXT): {$(VPATH)}assert.h
+object.$(OBJEXT): {$(VPATH)}builtin.h
object.$(OBJEXT): {$(VPATH)}config.h
object.$(OBJEXT): {$(VPATH)}constant.h
object.$(OBJEXT): {$(VPATH)}defines.h
@@ -3109,6 +3112,7 @@ object.$(OBJEXT): {$(VPATH)}id.h
object.$(OBJEXT): {$(VPATH)}id_table.h
object.$(OBJEXT): {$(VPATH)}intern.h
object.$(OBJEXT): {$(VPATH)}internal.h
+object.$(OBJEXT): {$(VPATH)}kernel.rbinc
object.$(OBJEXT): {$(VPATH)}missing.h
object.$(OBJEXT): {$(VPATH)}object.c
object.$(OBJEXT): {$(VPATH)}onigmo.h
diff --git a/inits.c b/inits.c
index 39cbe5f8ba..dae5e1ff41 100644
--- a/inits.c
+++ b/inits.c
@@ -84,6 +84,7 @@ rb_call_inits(void)
BUILTIN(pack);
BUILTIN(warning);
BUILTIN(array);
+ BUILTIN(kernel);
Init_builtin_prelude();
}
#undef CALL
diff --git a/kernel.rb b/kernel.rb
new file mode 100644
index 0000000000..46d9438f85
--- /dev/null
+++ b/kernel.rb
@@ -0,0 +1,29 @@
+module Kernel
+ #
+ # call-seq:
+ # obj.clone(freeze: true) -> an_object
+ #
+ # Produces a shallow copy of <i>obj</i>---the instance variables of
+ # <i>obj</i> are copied, but not the objects they reference.
+ # #clone copies the frozen (unless +:freeze+ keyword argument is
+ # given with a false value) state of <i>obj</i>. See
+ # also the discussion under Object#dup.
+ #
+ # class Klass
+ # attr_accessor :str
+ # end
+ # s1 = Klass.new #=> #<Klass:0x401b3a38>
+ # s1.str = "Hello" #=> "Hello"
+ # s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
+ # s2.str[1,4] = "i" #=> "i"
+ # s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
+ # s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
+ #
+ # This method may have class-specific behavior. If so, that
+ # behavior will be documented under the #+initialize_copy+ method of
+ # the class.
+ #
+ def clone(freeze: true)
+ __builtin_rb_obj_clone2(freeze)
+ end
+end
diff --git a/object.c b/object.c
index 496955e6d8..0f5650ef16 100644
--- a/object.c
+++ b/object.c
@@ -36,6 +36,7 @@
#include "ruby/encoding.h"
#include "ruby/st.h"
#include "ruby/util.h"
+#include "builtin.h"
/*!
* \defgroup object Core objects and their operations
@@ -389,35 +390,21 @@ special_object_p(VALUE obj)
}
}
-/*
- * call-seq:
- * obj.clone(freeze: true) -> an_object
- *
- * Produces a shallow copy of <i>obj</i>---the instance variables of
- * <i>obj</i> are copied, but not the objects they reference.
- * #clone copies the frozen (unless +:freeze+ keyword argument is
- * given with a false value) state of <i>obj</i>. See
- * also the discussion under Object#dup.
- *
- * class Klass
- * attr_accessor :str
- * end
- * s1 = Klass.new #=> #<Klass:0x401b3a38>
- * s1.str = "Hello" #=> "Hello"
- * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
- * s2.str[1,4] = "i" #=> "i"
- * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
- * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
- *
- * This method may have class-specific behavior. If so, that
- * behavior will be documented under the #+initialize_copy+ method of
- * the class.
- */
+static int
+obj_freeze_opt(VALUE freeze)
+{
+ if (freeze == Qfalse) return FALSE;
+
+ if (freeze != Qtrue)
+ rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE, rb_obj_class(freeze));
+
+ return TRUE;
+}
static VALUE
-rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
+rb_obj_clone2(rb_execution_context_t *ec, VALUE obj, VALUE freeze)
{
- int kwfreeze = freeze_opt(argc, argv);
+ int kwfreeze = obj_freeze_opt(freeze);
if (!special_object_p(obj))
return mutable_obj_clone(obj, kwfreeze);
return immutable_obj_clone(obj, kwfreeze);
@@ -437,6 +424,7 @@ freeze_opt(int argc, VALUE *argv)
static ID keyword_ids[1];
VALUE opt;
VALUE kwfreeze;
+ int ret = 1;
if (!keyword_ids[0]) {
CONST_ID(keyword_ids[0], "freeze");
@@ -444,13 +432,9 @@ freeze_opt(int argc, VALUE *argv)
rb_scan_args(argc, argv, "0:", &opt);
if (!NIL_P(opt)) {
rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
- if (kwfreeze == Qfalse) return FALSE;
- if (kwfreeze != Qundef && kwfreeze != Qtrue) {
- rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE,
- rb_obj_class(kwfreeze));
- }
+ ret = obj_freeze_opt(kwfreeze);
}
- return TRUE;
+ return ret;
}
static VALUE
@@ -4612,7 +4596,6 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
- rb_define_method(rb_mKernel, "clone", rb_obj_clone2, -1);
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);
@@ -4790,6 +4773,8 @@ InitVM_Object(void)
rb_deprecate_constant(rb_cObject, "FALSE");
}
+#include "kernel.rbinc"
+
void
Init_Object(void)
{