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

ruby-changes:39578

From: ko1 <ko1@a...>
Date: Sat, 22 Aug 2015 05:48:14 +0900 (JST)
Subject: [ruby-changes:39578] ko1:r51659 (trunk): * vm_opts.h, iseq.c, iseq.h: add compile option to force frozen

ko1	2015-08-22 05:47:53 +0900 (Sat, 22 Aug 2015)

  New Revision: 51659

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

  Log:
    * vm_opts.h, iseq.c, iseq.h: add compile option to force frozen
      string literals.
      [Feature #11473]
      This addition is not specification change, but to try frozen
      string literal world discussed on [Feature #11473].
      You can try frozen string literal world using this magical line:
        RubyVM::InstructionSequence.compile_option =
          {frozen_string_literal: true}
      Note that this is a global compilation option, so that you need to
      compile another script like that:
        p 'foo'.frozen? #=> false
        RubyVM::InstructionSequence.compile_option =
          {frozen_string_literal: true}
        p 'foo'.frozen? #=> false, because this line is already compiled.
        p eval("'foo'.frozen?") #=> true
      Details:
        * String literals are deduped by rb_fstring().
        * Dynamic string literals ("...#{xyz}...") is now only frozen,
          not deduped. Maybe you have other ideas.
      Now, please do not use this option on your productions :)
      Of course, current specification can be changed.
    * compile.c: ditto.
    * test/ruby/test_iseq.rb: add a test.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/iseq.c
    trunk/iseq.h
    trunk/test/ruby/test_iseq.rb
    trunk/vm_opts.h
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51658)
+++ ChangeLog	(revision 51659)
@@ -1,3 +1,38 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Aug 22 05:31:37 2015  Koichi Sasada  <ko1@a...>
+
+	* vm_opts.h, iseq.c, iseq.h: add compile option to force frozen
+	  string literals.
+	  [Feature #11473]
+
+	  This addition is not specification change, but to try frozen
+	  string literal world discussed on [Feature #11473].
+
+	  You can try frozen string literal world using this magical line:
+
+	    RubyVM::InstructionSequence.compile_option =
+	      {frozen_string_literal: true}
+
+	  Note that this is a global compilation option, so that you need to
+	  compile another script like that:
+
+	    p 'foo'.frozen? #=> false
+	    RubyVM::InstructionSequence.compile_option =
+	      {frozen_string_literal: true}
+	    p 'foo'.frozen? #=> false, because this line is already compiled.
+	    p eval("'foo'.frozen?") #=> true
+
+	  Details:
+	    * String literals are deduped by rb_fstring().
+	    * Dynamic string literals ("...#{xyz}...") is now only frozen,
+	      not deduped. Maybe you have other ideas.
+
+	  Now, please do not use this option on your productions :)
+	  Of course, current specification can be changed.
+
+	* compile.c: ditto.
+
+	* test/ruby/test_iseq.rb: add a test.
+
 Sat Aug 22 02:53:12 2015  Aaron Patterson <tenderlove@r...>
 
 	* ext/psych/*: update to Psych 2.0.14
Index: iseq.c
===================================================================
--- iseq.c	(revision 51658)
+++ iseq.c	(revision 51659)
@@ -338,7 +338,9 @@ static rb_compile_option_t COMPILE_OPTIO https://github.com/ruby/ruby/blob/trunk/iseq.c#L338
     OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_unification; */
     OPT_STACK_CACHING, /* int stack_caching; */
     OPT_TRACE_INSTRUCTION, /* int trace_instruction */
+    OPT_FROZEN_STRING_LITERAL
 };
+
 static const rb_compile_option_t COMPILE_OPTION_FALSE = {0};
 
 static void
@@ -375,6 +377,7 @@ make_compile_option(rb_compile_option_t https://github.com/ruby/ruby/blob/trunk/iseq.c#L377
 	SET_COMPILE_OPTION(option, opt, instructions_unification);
 	SET_COMPILE_OPTION(option, opt, stack_caching);
 	SET_COMPILE_OPTION(option, opt, trace_instruction);
+	SET_COMPILE_OPTION(option, opt, frozen_string_literal);
 	SET_COMPILE_OPTION_NUM(option, opt, debug_level);
 #undef SET_COMPILE_OPTION
 #undef SET_COMPILE_OPTION_NUM
Index: iseq.h
===================================================================
--- iseq.h	(revision 51658)
+++ iseq.h	(revision 51659)
@@ -61,6 +61,7 @@ struct rb_compile_option_struct { https://github.com/ruby/ruby/blob/trunk/iseq.h#L61
     int instructions_unification;
     int stack_caching;
     int trace_instruction;
+    int frozen_string_literal;
     int debug_level;
 };
 
Index: compile.c
===================================================================
--- compile.c	(revision 51658)
+++ compile.c	(revision 51659)
@@ -5002,10 +5002,15 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L5002
 	break;
       }
       case NODE_STR:{
-	node->nd_lit = rb_fstring(node->nd_lit);
 	debugp_param("nd_lit", node->nd_lit);
 	if (!poped) {
-	    ADD_INSN1(ret, line, putstring, node->nd_lit);
+	    node->nd_lit = rb_fstring(node->nd_lit);
+	    if (iseq->compile_data->option->frozen_string_literal) {
+		ADD_INSN1(ret, line, putobject, node->nd_lit); /* already frozen */
+	    }
+	    else {
+		ADD_INSN1(ret, line, putstring, node->nd_lit);
+	    }
 	}
 	break;
       }
@@ -5015,6 +5020,11 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L5020
 	if (poped) {
 	    ADD_INSN(ret, line, pop);
 	}
+	else {
+	    if (iseq->compile_data->option->frozen_string_literal) {
+		ADD_SEND (ret, line, idFreeze, INT2FIX(0));
+	    }
+	}
 	break;
       }
       case NODE_XSTR:{
Index: vm_opts.h
===================================================================
--- vm_opts.h	(revision 51658)
+++ vm_opts.h	(revision 51659)
@@ -23,7 +23,7 @@ https://github.com/ruby/ruby/blob/trunk/vm_opts.h#L23
 #define OPT_PEEPHOLE_OPTIMIZATION    1
 #define OPT_SPECIALISED_INSTRUCTION  1
 #define OPT_INLINE_CONST_CACHE       1
-
+#define OPT_FROZEN_STRING_LITERAL    0
 
 /* Build Options.
  * You can't change these options at runtime.
Index: test/ruby/test_iseq.rb
===================================================================
--- test/ruby/test_iseq.rb	(revision 51658)
+++ test/ruby/test_iseq.rb	(revision 51659)
@@ -141,4 +141,17 @@ class TestISeq < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_iseq.rb#L141
     assert_raise(TypeError, bug11159) {ISeq.compile(:foo)}
     assert_raise(TypeError, bug11159) {ISeq.compile(1)}
   end
+
+  def test_frozen_string_literal_compile_option
+    $f = 'f'
+    line = __LINE__ + 2
+    code = <<-'EOS'
+    ['foo', 'foo', "#{$f}foo"]
+    EOS
+    s1, s2, s3 = RubyVM::InstructionSequence.compile(code, __FILE__, __FILE__, line, {frozen_string_literal: true}).eval
+    assert(s1.frozen?)
+    assert(s2.frozen?)
+    assert(s3.frozen?)
+    assert(s1.object_id == s2.object_id)
+  end
 end

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

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