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

ruby-changes:47384

From: nagachika <ko1@a...>
Date: Fri, 4 Aug 2017 23:31:57 +0900 (JST)
Subject: [ruby-changes:47384] nagachika:r59500 (ruby_2_4): merge revision(s) 59357, 59358: [Backport #13391] [Backport #13404]

nagachika	2017-08-04 23:31:52 +0900 (Fri, 04 Aug 2017)

  New Revision: 59500

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59500

  Log:
    merge revision(s) 59357,59358: [Backport #13391] [Backport #13404]
    
    proc.c: rb_block_min_max_arity
    
    * proc.c (rb_block_min_max_arity): new function to get arity range
      from the current block.
    vm_eval.c: rb_lambda_call
    
    * enum.c (enum_collect): make the block arity same as the given
      block.  [Bug #13391]
    
    * internal.h (vm_ifunc): store arity instead of unused id.
    
    * proc.c (rb_vm_block_min_max_arity): return ifunc arity.
    
    * vm_eval.c (rb_lambda_call): call method with lambda block.

  Modified directories:
    branches/ruby_2_4/
  Modified files:
    branches/ruby_2_4/enum.c
    branches/ruby_2_4/internal.h
    branches/ruby_2_4/proc.c
    branches/ruby_2_4/test/ruby/test_enum.rb
    branches/ruby_2_4/version.h
    branches/ruby_2_4/vm_eval.c
Index: ruby_2_4/vm_eval.c
===================================================================
--- ruby_2_4/vm_eval.c	(revision 59499)
+++ ruby_2_4/vm_eval.c	(revision 59500)
@@ -1203,7 +1203,7 @@ rb_iterate(VALUE (* it_proc)(VALUE), VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_4/vm_eval.c#L1203
 	   VALUE (* bl_proc)(ANYARGS), VALUE data2)
 {
     return rb_iterate0(it_proc, data1,
-		       bl_proc ? IFUNC_NEW(bl_proc, data2, rb_frame_this_func()) : 0,
+		       bl_proc ? rb_vm_ifunc_proc_new(bl_proc, (void *)data2) : 0,
 		       GET_THREAD());
 }
 
@@ -1236,6 +1236,23 @@ rb_block_call(VALUE obj, ID mid, int arg https://github.com/ruby/ruby/blob/trunk/ruby_2_4/vm_eval.c#L1236
     return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
 }
 
+VALUE
+rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
+	       rb_block_call_func_t bl_proc, int min_argc, int max_argc,
+	       VALUE data2)
+{
+    struct iter_method_arg arg;
+    struct vm_ifunc *block;
+
+    if (!bl_proc) rb_raise(rb_eArgError, "NULL lambda function");
+    arg.obj = obj;
+    arg.mid = mid;
+    arg.argc = argc;
+    arg.argv = argv;
+    block = rb_vm_ifunc_new(bl_proc, (void *)data2, min_argc, max_argc);
+    return rb_iterate0(iterate_method, (VALUE)&arg, block, GET_THREAD());
+}
+
 static VALUE
 iterate_check_method(VALUE obj)
 {
Index: ruby_2_4/test/ruby/test_enum.rb
===================================================================
--- ruby_2_4/test/ruby/test_enum.rb	(revision 59499)
+++ ruby_2_4/test/ruby/test_enum.rb	(revision 59500)
@@ -798,6 +798,10 @@ class TestEnumerable < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_enum.rb#L798
     lambda2 = ->(x, i) { [x.upcase, i] }
     assert_equal([['A',0], ['B',1], ['C',2], ['D',3], ['E',4]],
       @obj.each_with_index.map(&lambda2))
+
+    hash = { a: 'hoge', b: 'fuga' }
+    lambda = -> (k, v) { "#{k}:#{v}" }
+    assert_equal ["a:hoge", "b:fuga"], hash.map(&lambda)
   end
 
   def test_flat_map
Index: ruby_2_4/version.h
===================================================================
--- ruby_2_4/version.h	(revision 59499)
+++ ruby_2_4/version.h	(revision 59500)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/version.h#L1
 #define RUBY_VERSION "2.4.2"
 #define RUBY_RELEASE_DATE "2017-08-04"
-#define RUBY_PATCHLEVEL 167
+#define RUBY_PATCHLEVEL 168
 
 #define RUBY_RELEASE_YEAR 2017
 #define RUBY_RELEASE_MONTH 8
Index: ruby_2_4/enum.c
===================================================================
--- ruby_2_4/enum.c	(revision 59499)
+++ ruby_2_4/enum.c	(revision 59500)
@@ -496,11 +496,13 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ruby_2_4/enum.c#L496
 enum_collect(VALUE obj)
 {
     VALUE ary;
+    int min_argc, max_argc;
 
     RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
 
     ary = rb_ary_new();
-    rb_block_call(obj, id_each, 0, 0, collect_i, ary);
+    min_argc = rb_block_min_max_arity(&max_argc);
+    rb_lambda_call(obj, id_each, 0, 0, collect_i, min_argc, max_argc, ary);
 
     return ary;
 }
Index: ruby_2_4/proc.c
===================================================================
--- ruby_2_4/proc.c	(revision 59499)
+++ ruby_2_4/proc.c	(revision 59500)
@@ -635,16 +635,47 @@ sym_proc_new(VALUE klass, VALUE sym) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L635
     return procval;
 }
 
+struct vm_ifunc *
+rb_vm_ifunc_new(VALUE (*func)(ANYARGS), const void *data, int min_argc, int max_argc)
+{
+    union {
+	struct vm_ifunc_argc argc;
+	VALUE packed;
+    } arity;
+
+    if (min_argc < UNLIMITED_ARGUMENTS ||
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+	min_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+#endif
+	0) {
+	rb_raise(rb_eRangeError, "minimum argument number out of range: %d",
+		 min_argc);
+    }
+    if (max_argc < UNLIMITED_ARGUMENTS ||
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+	max_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
+#endif
+	0) {
+	rb_raise(rb_eRangeError, "maximum argument number out of range: %d",
+		 max_argc);
+    }
+    arity.argc.min = min_argc;
+    arity.argc.max = max_argc;
+    return IFUNC_NEW(func, data, arity.packed);
+}
+
 VALUE
 rb_func_proc_new(rb_block_call_func_t func, VALUE val)
 {
-    return cfunc_proc_new(rb_cProc, (VALUE)IFUNC_NEW(func, val, 0), 0);
+    struct vm_ifunc *ifunc = rb_vm_ifunc_proc_new(func, (void *)val);
+    return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 0);
 }
 
 VALUE
-rb_func_lambda_new(rb_block_call_func_t func, VALUE val)
+rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc)
 {
-    return cfunc_proc_new(rb_cProc, (VALUE)IFUNC_NEW(func, val, 0), 1);
+    struct vm_ifunc *ifunc = rb_vm_ifunc_new(func, (void *)val, min_argc, max_argc);
+    return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 1);
 }
 
 static const char proc_without_block[] = "tried to create Proc object without a block";
@@ -928,13 +959,13 @@ rb_iseq_min_max_arity(const rb_iseq_t *i https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L959
 }
 
 static int
-rb_block_min_max_arity(const struct rb_block *block, int *max)
+rb_vm_block_min_max_arity(const struct rb_block *block, int *max)
 {
     switch (vm_block_type(block)) {
       case block_type_iseq:
 	return rb_iseq_min_max_arity(block->as.captured.code.iseq, max);
       case block_type_proc:
-	return rb_block_min_max_arity(vm_proc_block(block->as.proc), max);
+	return rb_vm_block_min_max_arity(vm_proc_block(block->as.proc), max);
       case block_type_ifunc:
 	{
 	    const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
@@ -942,8 +973,9 @@ rb_block_min_max_arity(const struct rb_b https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L973
 		/* e.g. method(:foo).to_proc.arity */
 		return method_min_max_arity((VALUE)ifunc->data, max);
 	    }
+	    *max = ifunc->argc.max;
+	    return ifunc->argc.min;
 	}
-	/* fall through */
       case block_type_symbol:
 	break;
     }
@@ -962,7 +994,7 @@ rb_proc_min_max_arity(VALUE self, int *m https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L994
 {
     rb_proc_t *proc;
     GetProcPtr(self, proc);
-    return rb_block_min_max_arity(&proc->block, max);
+    return rb_vm_block_min_max_arity(&proc->block, max);
 }
 
 int
@@ -971,7 +1003,7 @@ rb_proc_arity(VALUE self) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L1003
     rb_proc_t *proc;
     int max, min;
     GetProcPtr(self, proc);
-    min = rb_block_min_max_arity(&proc->block, &max);
+    min = rb_vm_block_min_max_arity(&proc->block, &max);
     return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
 }
 
@@ -1011,7 +1043,7 @@ rb_block_arity(void) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L1043
     }
 
     block_setup(&block, block_handler);
-    min = rb_block_min_max_arity(&block, &max);
+    min = rb_vm_block_min_max_arity(&block, &max);
 
     switch (vm_block_type(&block)) {
       case block_handler_type_symbol:
@@ -1031,6 +1063,22 @@ rb_block_arity(void) https://github.com/ruby/ruby/blob/trunk/ruby_2_4/proc.c#L1063
     }
 }
 
+int
+rb_block_min_max_arity(int *max)
+{
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = th->cfp;
+    VALUE block_handler = rb_vm_frame_block_handler(cfp);
+    struct rb_block block;
+
+    if (block_handler == VM_BLOCK_HANDLER_NONE) {
+	rb_raise(rb_eArgError, "no block given");
+    }
+
+    block_setup(&block, block_handler);
+    return rb_vm_block_min_max_arity(&block, max);
+}
+
 const rb_iseq_t *
 rb_proc_get_iseq(VALUE self, int *is_proc)
 {
Index: ruby_2_4/internal.h
===================================================================
--- ruby_2_4/internal.h	(revision 59499)
+++ ruby_2_4/internal.h	(revision 59500)
@@ -790,15 +790,30 @@ struct vm_throw_data { https://github.com/ruby/ruby/blob/trunk/ruby_2_4/internal.h#L790
 
 /* IFUNC */
 
+struct vm_ifunc_argc {
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+    int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
+    int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
+#else
+    int min, max;
+#endif
+};
+
 struct vm_ifunc {
     VALUE flags;
     VALUE reserved;
     VALUE (*func)(ANYARGS);
     const void *data;
-    ID id;
+    struct vm_ifunc_argc argc;
 };
 
 #define IFUNC_NEW(a, b, c) ((struct vm_ifunc *)rb_imemo_new(imemo_ifunc, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
+struct vm_ifunc *rb_vm_ifunc_new(VALUE (*func)(ANYARGS), const void *data, int min_argc, int max_argc);
+static inline struct vm_ifunc *
+rb_vm_ifunc_proc_new(VALUE (*func)(ANYARGS), const void *data)
+{
+    return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
+}
 
 /* MEMO */
 
@@ -1335,8 +1350,9 @@ ID rb_id_attrget(ID id); https://github.com/ruby/ruby/blob/trunk/ruby_2_4/internal.h#L1350
 VALUE rb_proc_location(VALUE self);
 st_index_t rb_hash_proc(st_index_t hash, VALUE proc);
 int rb_block_arity(void);
+int rb_block_min_max_arity(int *max);
 VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val);
-VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val);
+VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc);
 
 /* process.c */
 #define RB_MAX_GROUPS (65536)
@@ -1596,6 +1612,9 @@ VALUE rb_check_funcall_default(VALUE, ID https://github.com/ruby/ruby/blob/trunk/ruby_2_4/internal.h#L1612
 VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, int *stateptr);
 VALUE rb_yield_1(VALUE val);
 VALUE rb_yield_lambda(VALUE values);
+VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
+		     rb_block_call_func_t bl_proc, int min_argc, int max_argc,
+		     VALUE data2);
 
 /* vm_insnhelper.c */
 VALUE rb_equal_opt(VALUE obj1, VALUE obj2);
Index: ruby_2_4
===================================================================
--- ruby_2_4	(revision 59499)
+++ ruby_2_4	(revision 59500)

Property changes on: ruby_2_4
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
   Merged /trunk:r59357-59358

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

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