Project

General

Profile

Feature #10333 » 0001-optimize-yoda-literal-string.patch

normalperson (Eric Wong), 10/07/2014 01:11 AM

View differences:

benchmark/bm_vm2_streq2.rb
1
i = 0
2
foo = "literal"
3
while i<6_000_000 # benchmark loop 2
4
  i += 1
5
  "literal" == foo
6
end
compile.c
4306 4306
		}
4307 4307
		break;
4308 4308
	    }
4309
	    /* TODO: optimization shortcut
4309
	    /* optimization shortcut
4310 4310
	     *   "yoda" == other -> opt_streq2("yoda", other)
4311 4311
	     */
4312
	    if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR) {
4313
		DECL_ANCHOR(args);
4314
		unsigned int flag = 0;
4315
		VALUE argc;
4316
		VALUE yoda = rb_fstring(node->nd_recv->nd_lit);
4317
		node->nd_recv->nd_lit = yoda;
4318

  
4319
		INIT_ANCHOR(args);
4320
		argc = setup_args(iseq, args, node->nd_args, &flag);
4321
		assert(flag == 0 && argc == INT2FIX(1));
4322
		ADD_SEQ(ret, args);
4323
		ADD_INSN2(ret, line, opt_streq2,
4324
			new_callinfo(iseq, node->nd_mid, 1, 0, 0), yoda);
4325
		if (poped) {
4326
		    ADD_INSN(ret, line, pop);
4327
		}
4328
		break;
4329
	    }
4312 4330
	}
4313 4331
      case NODE_FCALL:
4314 4332
      case NODE_VCALL:{		/* VCALL: variable or call */
insns.def
1988 1988

  
1989 1989
/**
1990 1990
  @c optimize
1991
  @e "yoda" == other
1992
 */
1993
DEFINE_INSN
1994
opt_streq2
1995
(CALL_INFO ci, VALUE yoda)
1996
(VALUE other)
1997
(VALUE val)
1998
{
1999
    if (BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) {
2000
	val = rb_str_equal(yoda, other);
2001
    }
2002
    else {
2003
	yoda = rb_str_resurrect(yoda);
2004
	PUSH(yoda);
2005
	PUSH(other);
2006
	CALL_SIMPLE_METHOD(yoda);
2007
    }
2008
}
2009
/**
2010
  @c optimize
1991 2011
  @e optimized length
1992 2012
  @j 最適化された recv.length()。
1993 2013
 */
test/ruby/test_string.rb
2304 2304
    end
2305 2305
  end
2306 2306

  
2307
  def test_opt_streq1
2307
  def test_opt_streq
2308 2308
    assert_separately([], <<-RUBY)
2309 2309
      class String
2310 2310
        undef ==
......
2312 2312
          :TROO
2313 2313
        end
2314 2314
      end
2315
      assert_equal(:TROO, ("foo" == "foo"))
2315
      foo = "foo"
2316
      assert_equal(:TROO, (foo == "foo"), 'opt_streq1')
2317
      assert_equal(:TROO, ("foo" == foo), 'opt_streq2')
2316 2318
    RUBY
2317 2319

  
2318 2320
    if @cls == String
......
2321 2323
      recv = "something"
2322 2324
      res = []
2323 2325
      before = GC.stat(:total_allocated_objects)
2324
      nr.times { res << (recv == "constant") }
2326
      nr.times { res << (recv == "constant") } # opt_streq1
2327
      nr.times { res << ("constant" == recv) } # opt_streq2
2325 2328
      assert_equal before, GC.stat(:total_allocated_objects)
2326 2329
      assert_equal [ false ], res.uniq!
2327 2330

  
2328 2331
      res.clear
2329 2332
      before = GC.stat(:total_allocated_objects)
2330
      nr.times { res << (recv == "something") }
2333
      nr.times { res << (recv == "something") } # opt_streq1
2334
      nr.times { res << ("something" == recv) } # opt_streq2
2331 2335
      assert_equal before, GC.stat(:total_allocated_objects)
2332 2336
      assert_equal [ true ], res.uniq!
2333 2337
    end
2334
-