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());
141 "function g() { count++; %DeoptimizeFunction(f); f(false); }"
142 "function f(x) { if (x) { g(); } else { return } };"
148 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
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());
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());
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());
228 "function g() { count++; %DeoptimizeFunction(f); }"
229 "function f(x) { calls++; if (x > 0) { f(x - 1); } else { g(); } };"
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; };"
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());
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;");
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;");
339 TEST(DeoptimizeBinaryOperationADDString) {
340 i::FLAG_concurrent_recompilation =
false;
345 const char* f_source =
"function f(x, y) { return x + y; };";
350 i::FLAG_prepare_always_opt =
true;
351 CompileRun(
"var count = 0;"
355 "X.prototype.toString = function () {"
356 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'an X'"
358 CompileRun(f_source);
359 CompileRun(
"for (var i = 0; i < 5; i++) {"
364 i::FLAG_always_opt =
true;
365 CompileRun(f_source);
366 CompileRun(
"f('a+', new X());");
368 GetJSFunction(env->
Global(),
"f")->IsOptimized());
371 CompileRun(
"deopt = true;"
372 "var result = f('a+', new X());");
376 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
379 CHECK(result->IsString());
386 static void CompileConstructorWithDeoptimizingValueOf() {
387 CompileRun(
"var count = 0;"
391 "X.prototype.valueOf = function () {"
392 " if (deopt) { count++; %DeoptimizeFunction(f); } return 8"
397 static void TestDeoptimizeBinaryOpHelper(
LocalContext* env,
398 const char* binary_op) {
399 EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> f_source_buffer;
400 OS::SNPrintF(f_source_buffer,
401 "function f(x, y) { return x %s y; };",
403 char* f_source = f_source_buffer.start();
408 i::FLAG_prepare_always_opt =
true;
409 CompileConstructorWithDeoptimizingValueOf();
410 CompileRun(f_source);
411 CompileRun(
"for (var i = 0; i < 5; i++) {"
416 i::FLAG_always_opt =
true;
417 CompileRun(f_source);
418 CompileRun(
"f(7, new X());");
420 GetJSFunction((*env)->Global(),
"f")->IsOptimized());
423 CompileRun(
"deopt = true;"
424 "var result = f(7, new X());");
426 CHECK(!GetJSFunction((*env)->Global(),
"f")->IsOptimized());
430 TEST(DeoptimizeBinaryOperationADD) {
431 i::FLAG_concurrent_recompilation =
false;
435 TestDeoptimizeBinaryOpHelper(&env,
"+");
443 TEST(DeoptimizeBinaryOperationSUB) {
444 i::FLAG_concurrent_recompilation =
false;
448 TestDeoptimizeBinaryOpHelper(&env,
"-");
456 TEST(DeoptimizeBinaryOperationMUL) {
457 i::FLAG_concurrent_recompilation =
false;
461 TestDeoptimizeBinaryOpHelper(&env,
"*");
469 TEST(DeoptimizeBinaryOperationDIV) {
470 i::FLAG_concurrent_recompilation =
false;
474 TestDeoptimizeBinaryOpHelper(&env,
"/");
482 TEST(DeoptimizeBinaryOperationMOD) {
483 i::FLAG_concurrent_recompilation =
false;
487 TestDeoptimizeBinaryOpHelper(&env,
"%");
496 i::FLAG_concurrent_recompilation =
false;
500 const char* f_source =
"function f(x, y) { return x < y; };";
506 i::FLAG_prepare_always_opt =
true;
507 CompileRun(
"var count = 0;"
511 "X.prototype.toString = function () {"
512 " if (deopt) { count++; %DeoptimizeFunction(f); } return 'b'"
514 CompileRun(f_source);
515 CompileRun(
"for (var i = 0; i < 5; i++) {"
520 i::FLAG_always_opt =
true;
521 CompileRun(f_source);
522 CompileRun(
"f('a', new X());");
524 GetJSFunction(env->
Global(),
"f")->IsOptimized());
527 CompileRun(
"deopt = true;"
528 "var result = f('a', new X());");
532 CHECK(!GetJSFunction(env->
Global(),
"f")->IsOptimized());
534 CHECK_EQ(
true, env->
Global()->Get(v8_str(
"result"))->BooleanValue());
539 TEST(DeoptimizeLoadICStoreIC) {
540 i::FLAG_concurrent_recompilation =
false;
545 const char* f1_source =
"function f1(x) { return x.y; };";
546 const char* g1_source =
"function g1(x) { x.y = 1; };";
547 const char* f2_source =
"function f2(x, y) { return x[y]; };";
548 const char* g2_source =
"function g2(x, y) { x[y] = 1; };";
554 i::FLAG_prepare_always_opt =
true;
555 CompileRun(
"var count = 0;"
559 "X.prototype.__defineGetter__('y', function () {"
560 " if (deopt) { count++; %DeoptimizeFunction(f1); };"
563 "X.prototype.__defineSetter__('y', function () {"
564 " if (deopt) { count++; %DeoptimizeFunction(g1); };"
566 "X.prototype.__defineGetter__('z', function () {"
567 " if (deopt) { count++; %DeoptimizeFunction(f2); };"
570 "X.prototype.__defineSetter__('z', function () {"
571 " if (deopt) { count++; %DeoptimizeFunction(g2); };"
573 CompileRun(f1_source);
574 CompileRun(g1_source);
575 CompileRun(f2_source);
576 CompileRun(g2_source);
577 CompileRun(
"for (var i = 0; i < 5; i++) {"
585 i::FLAG_always_opt =
true;
586 CompileRun(f1_source);
587 CompileRun(g1_source);
588 CompileRun(f2_source);
589 CompileRun(g2_source);
590 CompileRun(
"f1(new X());");
591 CompileRun(
"g1(new X());");
592 CompileRun(
"f2(new X(), 'z');");
593 CompileRun(
"g2(new X(), 'z');");
595 CHECK(GetJSFunction(env->
Global(),
"f1")->IsOptimized());
596 CHECK(GetJSFunction(env->
Global(),
"g1")->IsOptimized());
597 CHECK(GetJSFunction(env->
Global(),
"f2")->IsOptimized());
598 CHECK(GetJSFunction(env->
Global(),
"g2")->IsOptimized());
602 CompileRun(
"deopt = true;"
603 "var result = f1(new X());"
606 "g2(new X(), 'z');");
610 CHECK(!GetJSFunction(env->
Global(),
"f1")->IsOptimized());
611 CHECK(!GetJSFunction(env->
Global(),
"g1")->IsOptimized());
612 CHECK(!GetJSFunction(env->
Global(),
"f2")->IsOptimized());
613 CHECK(!GetJSFunction(env->
Global(),
"g2")->IsOptimized());
619 TEST(DeoptimizeLoadICStoreICNested) {
620 i::FLAG_concurrent_recompilation =
false;
625 const char* f1_source =
"function f1(x) { return x.y; };";
626 const char* g1_source =
"function g1(x) { x.y = 1; };";
627 const char* f2_source =
"function f2(x, y) { return x[y]; };";
628 const char* g2_source =
"function g2(x, y) { x[y] = 1; };";
634 i::FLAG_prepare_always_opt =
true;
635 CompileRun(
"var count = 0;"
639 "X.prototype.__defineGetter__('y', function () {"
643 "X.prototype.__defineSetter__('y', function () {"
646 "X.prototype.__defineGetter__('z', function () {"
649 "X.prototype.__defineSetter__('z', function () {"
652 " %DeoptimizeFunction(f1);"
653 " %DeoptimizeFunction(g1);"
654 " %DeoptimizeFunction(f2);"
655 " %DeoptimizeFunction(g2); };"
657 CompileRun(f1_source);
658 CompileRun(g1_source);
659 CompileRun(f2_source);
660 CompileRun(g2_source);
661 CompileRun(
"for (var i = 0; i < 5; i++) {"
669 i::FLAG_always_opt =
true;
670 CompileRun(f1_source);
671 CompileRun(g1_source);
672 CompileRun(f2_source);
673 CompileRun(g2_source);
674 CompileRun(
"f1(new X());");
675 CompileRun(
"g1(new X());");
676 CompileRun(
"f2(new X(), 'z');");
677 CompileRun(
"g2(new X(), 'z');");
679 CHECK(GetJSFunction(env->
Global(),
"f1")->IsOptimized());
680 CHECK(GetJSFunction(env->
Global(),
"g1")->IsOptimized());
681 CHECK(GetJSFunction(env->
Global(),
"f2")->IsOptimized());
682 CHECK(GetJSFunction(env->
Global(),
"g2")->IsOptimized());
686 CompileRun(
"deopt = true;"
687 "var result = f1(new X());");
691 CHECK(!GetJSFunction(env->
Global(),
"f1")->IsOptimized());
692 CHECK(!GetJSFunction(env->
Global(),
"g1")->IsOptimized());
693 CHECK(!GetJSFunction(env->
Global(),
"f2")->IsOptimized());
694 CHECK(!GetJSFunction(env->
Global(),
"g2")->IsOptimized());
#define CHECK_EQ(expected, value)
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Local< Value > Get(Handle< Value > key)
kSerializedDataOffset Object
v8::Isolate * GetIsolate()
AlwaysOptimizeAllowNativesSyntaxNoInlining()
static i::Isolate * i_isolate()
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
static V8_INLINE Local< T > Cast(Local< S > that)
static const int kAbortIncrementalMarkingMask
~AllowNativesSyntaxNoInlining()
V8_INLINE bool IsEmpty() const
~AlwaysOptimizeAllowNativesSyntaxNoInlining()
AllowNativesSyntaxNoInlining()
static v8::Isolate * isolate()
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)