Feature #10333 » 0001-optimize-yoda-literal-string.patch
| benchmark/bm_vm2_streq2.rb | ||
|---|---|---|
| 
     i = 0 
   | 
||
| 
     foo = "literal" 
   | 
||
| 
     while i<6_000_000 # benchmark loop 2 
   | 
||
| 
       i += 1 
   | 
||
| 
       "literal" == foo 
   | 
||
| 
     end 
   | 
||
| compile.c | ||
|---|---|---|
| 
     		} 
   | 
||
| 
     		break; 
   | 
||
| 
     	    } 
   | 
||
| 
     	    /* TODO: optimization shortcut 
   | 
||
| 
     	    /* optimization shortcut 
   | 
||
| 
     	     *   "yoda" == other -> opt_streq2("yoda", other) 
   | 
||
| 
     	     */ 
   | 
||
| 
     	    if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR) { 
   | 
||
| 
     		DECL_ANCHOR(args); 
   | 
||
| 
     		unsigned int flag = 0; 
   | 
||
| 
     		VALUE argc; 
   | 
||
| 
     		VALUE yoda = rb_fstring(node->nd_recv->nd_lit); 
   | 
||
| 
     		node->nd_recv->nd_lit = yoda; 
   | 
||
| 
     		INIT_ANCHOR(args); 
   | 
||
| 
     		argc = setup_args(iseq, args, node->nd_args, &flag); 
   | 
||
| 
     		assert(flag == 0 && argc == INT2FIX(1)); 
   | 
||
| 
     		ADD_SEQ(ret, args); 
   | 
||
| 
     		ADD_INSN2(ret, line, opt_streq2, 
   | 
||
| 
     			new_callinfo(iseq, node->nd_mid, 1, 0, 0), yoda); 
   | 
||
| 
     		if (poped) { 
   | 
||
| 
     		    ADD_INSN(ret, line, pop); 
   | 
||
| 
     		} 
   | 
||
| 
     		break; 
   | 
||
| 
     	    } 
   | 
||
| 
     	} 
   | 
||
| 
           case NODE_FCALL: 
   | 
||
| 
           case NODE_VCALL:{		/* VCALL: variable or call */ 
   | 
||
| insns.def | ||
|---|---|---|
| 
     /** 
   | 
||
| 
       @c optimize 
   | 
||
| 
       @e "yoda" == other 
   | 
||
| 
      */ 
   | 
||
| 
     DEFINE_INSN 
   | 
||
| 
     opt_streq2 
   | 
||
| 
     (CALL_INFO ci, VALUE yoda) 
   | 
||
| 
     (VALUE other) 
   | 
||
| 
     (VALUE val) 
   | 
||
| 
     { 
   | 
||
| 
         if (BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) { 
   | 
||
| 
     	val = rb_str_equal(yoda, other); 
   | 
||
| 
         } 
   | 
||
| 
         else { 
   | 
||
| 
     	yoda = rb_str_resurrect(yoda); 
   | 
||
| 
     	PUSH(yoda); 
   | 
||
| 
     	PUSH(other); 
   | 
||
| 
     	CALL_SIMPLE_METHOD(yoda); 
   | 
||
| 
         } 
   | 
||
| 
     } 
   | 
||
| 
     /** 
   | 
||
| 
       @c optimize 
   | 
||
| 
       @e optimized length 
   | 
||
| 
       @j 最適化された recv.length()。 
   | 
||
| 
      */ 
   | 
||
| test/ruby/test_string.rb | ||
|---|---|---|
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def test_opt_streq1 
   | 
||
| 
       def test_opt_streq 
   | 
||
| 
         assert_separately([], <<-RUBY) 
   | 
||
| 
           class String 
   | 
||
| 
             undef == 
   | 
||
| ... | ... | |
| 
               :TROO 
   | 
||
| 
             end 
   | 
||
| 
           end 
   | 
||
| 
           assert_equal(:TROO, ("foo" == "foo")) 
   | 
||
| 
           foo = "foo" 
   | 
||
| 
           assert_equal(:TROO, (foo == "foo"), 'opt_streq1') 
   | 
||
| 
           assert_equal(:TROO, ("foo" == foo), 'opt_streq2') 
   | 
||
| 
         RUBY 
   | 
||
| 
         if @cls == String 
   | 
||
| ... | ... | |
| 
           recv = "something" 
   | 
||
| 
           res = [] 
   | 
||
| 
           before = GC.stat(:total_allocated_objects) 
   | 
||
| 
           nr.times { res << (recv == "constant") } 
   | 
||
| 
           nr.times { res << (recv == "constant") } # opt_streq1 
   | 
||
| 
           nr.times { res << ("constant" == recv) } # opt_streq2 
   | 
||
| 
           assert_equal before, GC.stat(:total_allocated_objects) 
   | 
||
| 
           assert_equal [ false ], res.uniq! 
   | 
||
| 
           res.clear 
   | 
||
| 
           before = GC.stat(:total_allocated_objects) 
   | 
||
| 
           nr.times { res << (recv == "something") } 
   | 
||
| 
           nr.times { res << (recv == "something") } # opt_streq1 
   | 
||
| 
           nr.times { res << ("something" == recv) } # opt_streq2 
   | 
||
| 
           assert_equal before, GC.stat(:total_allocated_objects) 
   | 
||
| 
           assert_equal [ true ], res.uniq! 
   | 
||
| 
         end 
   | 
||
| 
     -  
   | 
||