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

ruby-changes:47377

From: nagachika <ko1@a...>
Date: Fri, 4 Aug 2017 01:00:46 +0900 (JST)
Subject: [ruby-changes:47377] nagachika:r59493 (ruby_2_4): merge revision(s) 59183, 59184: [Backport #13682]

nagachika	2017-08-04 01:00:34 +0900 (Fri, 04 Aug 2017)

  New Revision: 59493

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

  Log:
    merge revision(s) 59183,59184: [Backport #13682]
    
    fix return in toplevel rescue/ensure
    
    * compile.c (iseq_compile_each0): throw TAG_RETURN at return in
      toplevel rescue/ensure to adjust VM stack properly.
      [ruby-core:81777] [Bug #13682]
    
    * vm_insnhelper.c (vm_throw_start): allow return in toplevel
      rescue/ensure.
    fix return in toplevel ensure
    
    * compile.c (iseq_compile_each0): adjust stack after return in
      toplevel ensure, when the value is used.
      [ruby-core:81777] [Bug #13682]

  Modified directories:
    branches/ruby_2_4/
  Modified files:
    branches/ruby_2_4/compile.c
    branches/ruby_2_4/test/ruby/test_eval.rb
    branches/ruby_2_4/test/ruby/test_syntax.rb
    branches/ruby_2_4/version.h
    branches/ruby_2_4/vm_insnhelper.c
Index: ruby_2_4/version.h
===================================================================
--- ruby_2_4/version.h	(revision 59492)
+++ ruby_2_4/version.h	(revision 59493)
@@ -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 166
+#define RUBY_PATCHLEVEL 167
 
 #define RUBY_RELEASE_YEAR 2017
 #define RUBY_RELEASE_MONTH 8
Index: ruby_2_4/test/ruby/test_eval.rb
===================================================================
--- ruby_2_4/test/ruby/test_eval.rb	(revision 59492)
+++ ruby_2_4/test/ruby/test_eval.rb	(revision 59493)
@@ -525,4 +525,14 @@ class TestEval < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_eval.rb#L525
       b.eval('yield')
     }, '[Bug #10368]'
   end
+
+  def test_return_in_eval_proc
+    x = proc {eval("return :ng")}
+    assert_raise(LocalJumpError) {x.call}
+  end
+
+  def test_return_in_eval_lambda
+    x = lambda {eval("return :ok")}
+    assert_equal(:ok, x.call)
+  end
 end
Index: ruby_2_4/test/ruby/test_syntax.rb
===================================================================
--- ruby_2_4/test/ruby/test_syntax.rb	(revision 59492)
+++ ruby_2_4/test/ruby/test_syntax.rb	(revision 59493)
@@ -984,6 +984,8 @@ eom https://github.com/ruby/ruby/blob/trunk/ruby_2_4/test/ruby/test_syntax.rb#L984
       return 1; raise
       "#{return}"
       raise((return; "should not raise"))
+      begin raise; ensure return; end; self
+      begin raise; ensure return; end and self
     end;
     all_assertions(feature4840) do |a|
       code.each_line do |s|
Index: ruby_2_4/vm_insnhelper.c
===================================================================
--- ruby_2_4/vm_insnhelper.c	(revision 59492)
+++ ruby_2_4/vm_insnhelper.c	(revision 59493)
@@ -1080,6 +1080,7 @@ vm_throw_start(rb_thread_t *const th, rb https://github.com/ruby/ruby/blob/trunk/ruby_2_4/vm_insnhelper.c#L1080
 	const VALUE *current_ep = GET_EP();
 	const VALUE *target_lep = VM_EP_LEP(current_ep);
 	int in_class_frame = 0;
+	int toplevel = 1;
 	escape_cfp = reg_cfp;
 
 	while (escape_cfp < eocfp) {
@@ -1098,6 +1099,7 @@ vm_throw_start(rb_thread_t *const th, rb https://github.com/ruby/ruby/blob/trunk/ruby_2_4/vm_insnhelper.c#L1099
 
 	    if (lep == target_lep) {
 		if (VM_FRAME_TYPE(escape_cfp) == VM_FRAME_MAGIC_LAMBDA) {
+		    toplevel = 0;
 		    if (in_class_frame) {
 			/* lambda {class A; ... return ...; end} */
 			goto valid_return;
@@ -1114,6 +1116,20 @@ vm_throw_start(rb_thread_t *const th, rb https://github.com/ruby/ruby/blob/trunk/ruby_2_4/vm_insnhelper.c#L1116
 			}
 		    }
 		}
+		else if (VM_FRAME_RUBYFRAME_P(escape_cfp)) {
+		    switch (escape_cfp->iseq->body->type) {
+		      case ISEQ_TYPE_TOP:
+		      case ISEQ_TYPE_MAIN:
+			if (toplevel) goto valid_return;
+			break;
+		      case ISEQ_TYPE_EVAL:
+		      case ISEQ_TYPE_CLASS:
+			toplevel = 0;
+			break;
+		      default:
+			break;
+		    }
+		}
 	    }
 
 	    if (escape_cfp->ep == target_lep && escape_cfp->iseq->body->type == ISEQ_TYPE_METHOD) {
Index: ruby_2_4/compile.c
===================================================================
--- ruby_2_4/compile.c	(revision 59492)
+++ ruby_2_4/compile.c	(revision 59493)
@@ -4647,8 +4647,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/compile.c#L4647
 	CHECK(COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr));
 	last = ensr->last;
 	last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
-	if (!popped && last_leave)
-	    popped = 1;
 
 	er.begin = lstart;
 	er.end = lend;
@@ -4656,13 +4654,16 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/compile.c#L4654
 	push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
 
 	ADD_LABEL(ret, lstart);
-	CHECK(COMPILE_(ret, "ensure head", node->nd_head, popped));
+	CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave)));
 	ADD_LABEL(ret, lend);
 	if (ensr->anchor.next == 0) {
 	    ADD_INSN(ret, line, nop);
 	}
 	else {
 	    ADD_SEQ(ret, ensr);
+	    if (!popped && last_leave) {
+		ADD_INSN(ret, line, putnil);
+	    }
 	}
 	ADD_LABEL(ret, lcont);
 	if (last_leave) ADD_INSN(ret, line, pop);
@@ -5476,15 +5477,23 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/ruby_2_4/compile.c#L5477
 	if (is) {
 	    enum iseq_type type = is->body->type;
 	    const rb_iseq_t *parent_iseq = is->body->parent_iseq;
-	    enum iseq_type parent_type = parent_iseq ? parent_iseq->body->type : type;
+	    enum iseq_type parent_type;
 
-	    if (type == ISEQ_TYPE_TOP || type == ISEQ_TYPE_MAIN ||
-		((type == ISEQ_TYPE_RESCUE || type == ISEQ_TYPE_ENSURE) &&
-		 (parent_type == ISEQ_TYPE_TOP || parent_type == ISEQ_TYPE_MAIN))) {
+	    if (type == ISEQ_TYPE_TOP || type == ISEQ_TYPE_MAIN) {
 		ADD_ADJUST(ret, line, 0);
 		ADD_INSN(ret, line, putnil);
 		ADD_INSN(ret, line, leave);
 	    }
+	    else if ((type == ISEQ_TYPE_RESCUE || type == ISEQ_TYPE_ENSURE) &&
+		     parent_iseq &&
+		     ((parent_type = parent_iseq->body->type) == ISEQ_TYPE_TOP ||
+		      parent_type == ISEQ_TYPE_MAIN)) {
+		ADD_INSN(ret, line, putnil);
+		ADD_INSN1(ret, line, throw, INT2FIX(TAG_RETURN));
+		if (popped) {
+		    ADD_INSN(ret, line, pop);
+		}
+	    }
 	    else {
 		LABEL *splabel = 0;
 
Index: ruby_2_4
===================================================================
--- ruby_2_4	(revision 59492)
+++ ruby_2_4	(revision 59493)

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

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

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