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

ruby-changes:53954

From: tenderlove <ko1@a...>
Date: Tue, 4 Dec 2018 08:53:17 +0900 (JST)
Subject: [ruby-changes:53954] tenderlove:r66174 (trunk): Collapse putobject, putobject, newarray

tenderlove	2018-12-04 08:53:11 +0900 (Tue, 04 Dec 2018)

  New Revision: 66174

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

  Log:
    Collapse putobject, putobject, newarray
    
    This collapses:
    
    ```
    == disasm: #<ISeq:bar@b...:3 (3,0)-(5,3)> (catch: FALSE)
    0000 putobject                    "a"                                 (   4)[LiCa]
    0002 putobject                    "b"
    0004 putobject                    "c"
    0006 putobject                    "d"
    0008 putobject                    "e"
    0010 putobject                    "f"
    0012 putobject                    "g"
    0014 putobject                    "h"
    0016 putobject                    "i"
    0018 putobject                    "j"
    0020 putobject                    "k"
    0022 newarray                     11
    0024 leave                                                            (   5)[Re]
    ```
    
    In to this:
    
    ```
    == disasm: #<ISeq:bar@b...:3 (3,0)-(5,3)> (catch: FALSE)
    0000 duparray                     ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"](   4)[LiCa]
    0002 leave                                                            (   5)[Re]
    ```

  Modified files:
    trunk/compile.c
    trunk/test/ruby/test_literal.rb
Index: compile.c
===================================================================
--- compile.c	(revision 66173)
+++ compile.c	(revision 66174)
@@ -3847,7 +3847,7 @@ enum compile_array_type_t { https://github.com/ruby/ruby/blob/trunk/compile.c#L3847
 };
 
 static inline int
-static_literal_node_p(const NODE *node)
+static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
 {
     node = node->nd_head;
     switch (nd_type(node)) {
@@ -3856,13 +3856,19 @@ static_literal_node_p(const NODE *node) https://github.com/ruby/ruby/blob/trunk/compile.c#L3856
       case NODE_TRUE:
       case NODE_FALSE:
 	return TRUE;
+      case NODE_STR:
+	if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
+	    return TRUE;
+	} else {
+	    return FALSE;
+	}
       default:
 	return FALSE;
     }
 }
 
 static inline VALUE
-static_literal_value(const NODE *node)
+static_literal_value(const NODE *node, rb_iseq_t *iseq)
 {
     node = node->nd_head;
     switch (nd_type(node)) {
@@ -3872,6 +3878,17 @@ static_literal_value(const NODE *node) https://github.com/ruby/ruby/blob/trunk/compile.c#L3878
 	return Qtrue;
       case NODE_FALSE:
 	return Qfalse;
+      case NODE_STR:
+	if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
+	    VALUE lit;
+	    VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
+	    lit = rb_str_dup(node->nd_lit);
+	    rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
+	    return rb_str_freeze(lit);
+	}
+	else {
+	    return rb_fstring(node->nd_lit);
+	}
       default:
 	return node->nd_lit;
     }
@@ -3921,7 +3938,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCH https://github.com/ruby/ruby/blob/trunk/compile.c#L3938
 		    }
 		    break;
 		}
-		if (opt_p && !static_literal_node_p(node)) {
+		if (opt_p && !static_literal_node_p(node, iseq)) {
 		    opt_p = 0;
 		}
 
@@ -3943,15 +3960,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCH https://github.com/ruby/ruby/blob/trunk/compile.c#L3960
 		    node = start_node;
 
 		    while (node != end_node) {
-			rb_ary_push(ary, static_literal_value(node));
+			rb_ary_push(ary, static_literal_value(node, iseq));
 			node = node->nd_next;
 		    }
 		    while (node && node->nd_next &&
-			   static_literal_node_p(node) &&
-			   static_literal_node_p(node->nd_next)) {
+			   static_literal_node_p(node, iseq) &&
+			   static_literal_node_p(node->nd_next, iseq)) {
 			VALUE elem[2];
-			elem[0] = static_literal_value(node);
-			elem[1] = static_literal_value(node->nd_next);
+			elem[0] = static_literal_value(node, iseq);
+			elem[1] = static_literal_value(node->nd_next, iseq);
 			rb_ary_cat(ary, elem, 2);
 			node = node->nd_next->nd_next;
 			len++;
Index: test/ruby/test_literal.rb
===================================================================
--- test/ruby/test_literal.rb	(revision 66173)
+++ test/ruby/test_literal.rb	(revision 66174)
@@ -177,6 +177,12 @@ class TestRubyLiteral < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/ruby/test_literal.rb#L177
     end
   end
 
+  def test_frozen_string_in_array_literal
+    list = eval("# frozen-string-literal: true\n""['foo', 'bar']")
+    assert_equal 2, list.length
+    list.each { |str| assert_predicate str, :frozen? }
+  end
+
   if defined?(RubyVM::InstructionSequence.compile_option) and
     RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal)
     def test_debug_frozen_string
@@ -189,6 +195,17 @@ class TestRubyLiteral < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/ruby/test_literal.rb#L195
         str << "x"
       }
     end
+
+    def test_debug_frozen_string_in_array_literal
+      src = '["foo"]'; f = "test.rb"; n = 1
+      opt = {frozen_string_literal: true, debug_frozen_string_literal: true}
+      ary = RubyVM::InstructionSequence.compile(src, f, f, n, opt).eval
+      assert_equal("foo", ary.first)
+      assert_predicate(ary.first, :frozen?)
+      assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) {
+        ary.first << "x"
+      }
+    end
   end
 
   def test_regexp

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

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