41 using ::v8::internal::Deoptimizer;
42 using ::v8::internal::EmbeddedVector;
43 using ::v8::internal::Handle;
44 using ::v8::internal::Isolate;
45 using ::v8::internal::JSFunction;
46 using ::v8::internal::OS;
50 #define SMALL_STRING_BUFFER_SIZE 80
57 : always_opt_(i::FLAG_always_opt),
58 allow_natives_syntax_(i::FLAG_allow_natives_syntax),
59 use_inlining_(i::FLAG_use_inlining) {
60 i::FLAG_always_opt =
true;
61 i::FLAG_allow_natives_syntax =
true;
62 i::FLAG_use_inlining =
false;
66 i::FLAG_allow_natives_syntax = allow_natives_syntax_;
67 i::FLAG_always_opt = always_opt_;
68 i::FLAG_use_inlining = use_inlining_;
73 bool allow_natives_syntax_;
83 : allow_natives_syntax_(i::FLAG_allow_natives_syntax),
84 use_inlining_(i::FLAG_use_inlining) {
85 i::FLAG_allow_natives_syntax =
true;
86 i::FLAG_use_inlining =
false;
90 i::FLAG_allow_natives_syntax = allow_natives_syntax_;
91 i::FLAG_use_inlining = use_inlining_;
95 bool allow_natives_syntax_;
102 static void NonIncrementalGC() {
108 const char* property_name) {
124 "function h() { %DeoptimizeFunction(f); }"
125 "function g() { count++; h(); }"
126 "function f() { g(); };"
132 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
133 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
141 "function g() { count++; %DeoptimizeFunction(f); f(false); }"
142 "function f(x) { if (x) { g(); } else { return } };"
148 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
149 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
153 TEST(DeoptimizeSimpleWithArguments) {
162 "function h(x) { %DeoptimizeFunction(f); }"
163 "function g(x, y) { count++; h(x); }"
164 "function f(x, y, z) { g(1,x); y+z; };"
165 "f(1, \"2\", false);");
170 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
171 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
180 "function g(x, y) { count++; %DeoptimizeFunction(f); f(false, 1, y); }"
181 "function f(x, y, z) { if (x) { g(x, y); } else { return y + z; } };"
182 "f(true, 1, \"2\");");
187 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
188 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
203 "function h(x, y, z) { return x + y + z; }"
204 "function g(z) { count++; %DeoptimizeFunction(f); return z;}"
205 "function f(x,y,z) { return h(x, y, g(z)); };"
206 "result = f(1, 2, 3);");
211 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
212 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
228 "function g() { count++; %DeoptimizeFunction(f); }"
229 "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };"
236 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
253 "function g() { count++;"
254 " %DeoptimizeFunction(f1);"
255 " %DeoptimizeFunction(f2);"
256 " %DeoptimizeFunction(f3);"
257 " %DeoptimizeFunction(f4);}"
258 "function f4(x) { g(); };"
259 "function f3(x, y, z) { f4(); return x + y + z; };"
260 "function f2(x, y) { return x + f3(y + 1, y + 1, y + 1) + y; };"
261 "function f1(x) { return f2(x + 1, x + 1) + x; };"
268 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
280 "function g() { count++;"
281 " %DeoptimizeFunction(f); }"
282 "function f() { g(); };"
283 "result = new f() instanceof f;");
288 CHECK(env->
Global()->Get(v8_str(
"result"))->IsTrue());
289 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
296 "function g() { count++;"
297 " %DeoptimizeFunction(f); }"
298 "function f(x, y) { this.x = x; g(); this.y = y; };"
299 "result = new f(1, 2);"
300 "result = result.x + result.y;");
306 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
310 TEST(DeoptimizeConstructorMultiple) {
319 "function g() { count++;"
320 " %DeoptimizeFunction(f1);"
321 " %DeoptimizeFunction(f2);"
322 " %DeoptimizeFunction(f3);"
323 " %DeoptimizeFunction(f4);}"
324 "function f4(x) { this.result = x; g(); };"
325 "function f3(x, y, z) { this.result = new f4(x + y + z).result; };"
326 "function f2(x, y) {"
327 " this.result = x + new f3(y + 1, y + 1, y + 1).result + y; };"
328 "function f1(x) { this.result = new f2(x + 1, x + 1).result + x; };"
329 "result = new f1(1).result;");
335 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
339 TEST(DeoptimizeBinaryOperationADDString) {
343 const char* f_source =
"function f(x, y) { return x + y; };";
349 i::FLAG_prepare_always_opt =
true;
350 CompileRun(
"var count = 0;"
354 "X.prototype.toString = function () {"
355 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'"
357 CompileRun(f_source);
358 CompileRun(
"for (var i = 0; i < 5; i++) {"
363 i::FLAG_always_opt =
true;
364 CompileRun(f_source);
365 CompileRun(
"f('a+', new X());");
367 GetJSFunction(env->
Global(),
"f")->IsOptimized());
370 CompileRun(
"deopt = true;"
371 "var result = f('a+', new X());");
375 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
378 CHECK(result->IsString());
381 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
385 static void CompileConstructorWithDeoptimizingValueOf() {
386 CompileRun(
"var count = 0;"
390 "X.prototype.valueOf = function () {"
391 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8"
396 static void TestDeoptimizeBinaryOpHelper(
LocalContext* env,
397 const char* binary_op) {
398 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer;
399 OS::SNPrintF(f_source_buffer,
400 "function f(x, y) { return x %s y; };",
402 char* f_source = f_source_buffer.start();
407 i::FLAG_prepare_always_opt =
true;
408 CompileConstructorWithDeoptimizingValueOf();
409 CompileRun(f_source);
410 CompileRun(
"for (var i = 0; i < 5; i++) {"
415 i::FLAG_always_opt =
true;
416 CompileRun(f_source);
417 CompileRun(
"f(7, new X());");
419 GetJSFunction((*env)->Global(),
"f")->IsOptimized());
422 CompileRun(
"deopt = true;"
423 "var result = f(7, new X());");
425 CHECK(!GetJSFunction((*env)->Global(),
"f")->IsOptimized());
429 TEST(DeoptimizeBinaryOperationADD) {
433 TestDeoptimizeBinaryOpHelper(&env,
"+");
437 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
441 TEST(DeoptimizeBinaryOperationSUB) {
445 TestDeoptimizeBinaryOpHelper(&env,
"-");
449 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
453 TEST(DeoptimizeBinaryOperationMUL) {
457 TestDeoptimizeBinaryOpHelper(&env,
"*");
461 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
465 TEST(DeoptimizeBinaryOperationDIV) {
469 TestDeoptimizeBinaryOpHelper(&env,
"/");
473 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
477 TEST(DeoptimizeBinaryOperationMOD) {
481 TestDeoptimizeBinaryOpHelper(&env,
"%");
485 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
493 const char* f_source =
"function f(x, y) { return x < y; };";
499 i::FLAG_prepare_always_opt =
true;
500 CompileRun(
"var count = 0;"
504 "X.prototype.toString = function () {"
505 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'"
507 CompileRun(f_source);
508 CompileRun(
"for (var i = 0; i < 5; i++) {"
513 i::FLAG_always_opt =
true;
514 CompileRun(f_source);
515 CompileRun(
"f('a', new X());");
517 GetJSFunction(env->
Global(),
"f")->IsOptimized());
520 CompileRun(
"deopt = true;"
521 "var result = f('a', new X());");
525 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
527 CHECK_EQ(
true, env->
Global()->Get(v8_str(
"result"))->BooleanValue());
528 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
532 TEST(DeoptimizeLoadICStoreIC) {
537 const char* f1_source =
"function f1(x) { return x.y; };";
538 const char* g1_source =
"function g1(x) { x.y = 1; };";
539 const char* f2_source =
"function f2(x, y) { return x[y]; };";
540 const char* g2_source =
"function g2(x, y) { x[y] = 1; };";
546 i::FLAG_prepare_always_opt =
true;
547 CompileRun(
"var count = 0;"
551 "X.prototype.__defineGetter__('y', function () {"
552 " if (deopt) { count++; %DeoptimizeFunction(f1); };"
555 "X.prototype.__defineSetter__('y', function () {"
556 " if (deopt) { count++; %DeoptimizeFunction(g1); };"
558 "X.prototype.__defineGetter__('z', function () {"
559 " if (deopt) { count++; %DeoptimizeFunction(f2); };"
562 "X.prototype.__defineSetter__('z', function () {"
563 " if (deopt) { count++; %DeoptimizeFunction(g2); };"
565 CompileRun(f1_source);
566 CompileRun(g1_source);
567 CompileRun(f2_source);
568 CompileRun(g2_source);
569 CompileRun(
"for (var i = 0; i < 5; i++) {"
577 i::FLAG_always_opt =
true;
578 CompileRun(f1_source);
579 CompileRun(g1_source);
580 CompileRun(f2_source);
581 CompileRun(g2_source);
582 CompileRun(
"f1(new X());");
583 CompileRun(
"g1(new X());");
584 CompileRun(
"f2(new X(), 'z');");
585 CompileRun(
"g2(new X(), 'z');");
587 CHECK(GetJSFunction(env->
Global(),
"f1")->IsOptimized());
588 CHECK(GetJSFunction(env->
Global(),
"g1")->IsOptimized());
589 CHECK(GetJSFunction(env->
Global(),
"f2")->IsOptimized());
590 CHECK(GetJSFunction(env->
Global(),
"g2")->IsOptimized());
594 CompileRun(
"deopt = true;"
595 "var result = f1(new X());"
598 "g2(new X(), 'z');");
602 CHECK(!GetJSFunction(env->
Global(),
"f1")->IsOptimized());
603 CHECK(!GetJSFunction(env->
Global(),
"g1")->IsOptimized());
604 CHECK(!GetJSFunction(env->
Global(),
"f2")->IsOptimized());
605 CHECK(!GetJSFunction(env->
Global(),
"g2")->IsOptimized());
608 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
612 TEST(DeoptimizeLoadICStoreICNested) {
617 const char* f1_source =
"function f1(x) { return x.y; };";
618 const char* g1_source =
"function g1(x) { x.y = 1; };";
619 const char* f2_source =
"function f2(x, y) { return x[y]; };";
620 const char* g2_source =
"function g2(x, y) { x[y] = 1; };";
626 i::FLAG_prepare_always_opt =
true;
627 CompileRun(
"var count = 0;"
631 "X.prototype.__defineGetter__('y', function () {"
635 "X.prototype.__defineSetter__('y', function () {"
638 "X.prototype.__defineGetter__('z', function () {"
641 "X.prototype.__defineSetter__('z', function () {"
644 " %DeoptimizeFunction(f1);"
645 " %DeoptimizeFunction(g1);"
646 " %DeoptimizeFunction(f2);"
647 " %DeoptimizeFunction(g2); };"
649 CompileRun(f1_source);
650 CompileRun(g1_source);
651 CompileRun(f2_source);
652 CompileRun(g2_source);
653 CompileRun(
"for (var i = 0; i < 5; i++) {"
661 i::FLAG_always_opt =
true;
662 CompileRun(f1_source);
663 CompileRun(g1_source);
664 CompileRun(f2_source);
665 CompileRun(g2_source);
666 CompileRun(
"f1(new X());");
667 CompileRun(
"g1(new X());");
668 CompileRun(
"f2(new X(), 'z');");
669 CompileRun(
"g2(new X(), 'z');");
671 CHECK(GetJSFunction(env->
Global(),
"f1")->IsOptimized());
672 CHECK(GetJSFunction(env->
Global(),
"g1")->IsOptimized());
673 CHECK(GetJSFunction(env->
Global(),
"f2")->IsOptimized());
674 CHECK(GetJSFunction(env->
Global(),
"g2")->IsOptimized());
678 CompileRun(
"deopt = true;"
679 "var result = f1(new X());");
683 CHECK(!GetJSFunction(env->
Global(),
"f1")->IsOptimized());
684 CHECK(!GetJSFunction(env->
Global(),
"g1")->IsOptimized());
685 CHECK(!GetJSFunction(env->
Global(),
"f2")->IsOptimized());
686 CHECK(!GetJSFunction(env->
Global(),
"g2")->IsOptimized());
689 CHECK_EQ(0, Deoptimizer::GetDeoptimizedCodeCount(Isolate::Current()));
#define CHECK_EQ(expected, value)
static bool UseCrankshaft()
V8EXPORT Local< Value > Get(Handle< Value > key)
static V8EXPORT Local< String > New(const char *data, int length=-1)
AlwaysOptimizeAllowNativesSyntaxNoInlining()
static const int kAbortIncrementalMarkingMask
static Local< T > Cast(Local< S > that)
~AllowNativesSyntaxNoInlining()
~AlwaysOptimizeAllowNativesSyntaxNoInlining()
AllowNativesSyntaxNoInlining()
static v8::internal::Handle< v8::internal::TemplateInfo > OpenHandle(const Template *that)