OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( | 399 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
400 env->Global() | 400 env->Global() |
401 ->Get(env.local(), v8_str("closure2")) | 401 ->Get(env.local(), v8_str("closure2")) |
402 .ToLocalChecked()))); | 402 .ToLocalChecked()))); |
403 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 403 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
404 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); | 404 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
405 CHECK_EQ(fun1->code(), fun2->code()); | 405 CHECK_EQ(fun1->code(), fun2->code()); |
406 } | 406 } |
407 } | 407 } |
408 | 408 |
| 409 // Test that optimized code for different closures is actually shared. |
| 410 TEST(OptimizedCodeSharing2) { |
| 411 if (FLAG_stress_compaction) return; |
| 412 FLAG_allow_natives_syntax = true; |
| 413 FLAG_native_context_specialization = false; |
| 414 FLAG_turbo_cache_shared_code = true; |
| 415 const char* flag = "--turbo-filter=*"; |
| 416 FlagList::SetFlagsFromString(flag, StrLength(flag)); |
| 417 CcTest::InitializeVM(); |
| 418 v8::HandleScope scope(CcTest::isolate()); |
| 419 v8::Local<v8::Script> script = v8_compile( |
| 420 "function MakeClosure() {" |
| 421 " return function() { return x; };" |
| 422 "}"); |
| 423 Handle<Code> reference_code; |
| 424 { |
| 425 LocalContext env; |
| 426 env->Global() |
| 427 ->Set(env.local(), v8_str("x"), v8::Integer::New(CcTest::isolate(), 23)) |
| 428 .FromJust(); |
| 429 script->GetUnboundScript() |
| 430 ->BindToCurrentContext() |
| 431 ->Run(env.local()) |
| 432 .ToLocalChecked(); |
| 433 CompileRun( |
| 434 "var closure0 = MakeClosure();" |
| 435 "%DebugPrint(closure0());" |
| 436 "%OptimizeFunctionOnNextCall(closure0);" |
| 437 "%DebugPrint(closure0());"); |
| 438 Handle<JSFunction> fun0 = Handle<JSFunction>::cast( |
| 439 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 440 env->Global() |
| 441 ->Get(env.local(), v8_str("closure0")) |
| 442 .ToLocalChecked()))); |
| 443 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 444 reference_code = handle(fun0->code()); |
| 445 } |
| 446 for (int i = 0; i < 3; i++) { |
| 447 LocalContext env; |
| 448 env->Global() |
| 449 ->Set(env.local(), v8_str("x"), v8::Integer::New(CcTest::isolate(), i)) |
| 450 .FromJust(); |
| 451 script->GetUnboundScript() |
| 452 ->BindToCurrentContext() |
| 453 ->Run(env.local()) |
| 454 .ToLocalChecked(); |
| 455 CompileRun( |
| 456 "var closure0 = MakeClosure();" |
| 457 "%DebugPrint(closure0());" |
| 458 "%OptimizeFunctionOnNextCall(closure0);" |
| 459 "%DebugPrint(closure0());" |
| 460 "var closure1 = MakeClosure(); closure1();" |
| 461 "var closure2 = MakeClosure(); closure2();"); |
| 462 Handle<JSFunction> fun1 = Handle<JSFunction>::cast( |
| 463 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 464 env->Global() |
| 465 ->Get(env.local(), v8_str("closure1")) |
| 466 .ToLocalChecked()))); |
| 467 Handle<JSFunction> fun2 = Handle<JSFunction>::cast( |
| 468 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 469 env->Global() |
| 470 ->Get(env.local(), v8_str("closure2")) |
| 471 .ToLocalChecked()))); |
| 472 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 473 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 474 CHECK_EQ(*reference_code, fun1->code()); |
| 475 CHECK_EQ(*reference_code, fun2->code()); |
| 476 } |
| 477 } |
| 478 |
| 479 // Test that optimized code for different closures is actually shared. |
| 480 TEST(OptimizedCodeSharing3) { |
| 481 if (FLAG_stress_compaction) return; |
| 482 FLAG_allow_natives_syntax = true; |
| 483 FLAG_native_context_specialization = false; |
| 484 FLAG_turbo_cache_shared_code = true; |
| 485 const char* flag = "--turbo-filter=*"; |
| 486 FlagList::SetFlagsFromString(flag, StrLength(flag)); |
| 487 CcTest::InitializeVM(); |
| 488 v8::HandleScope scope(CcTest::isolate()); |
| 489 v8::Local<v8::Script> script = v8_compile( |
| 490 "function MakeClosure() {" |
| 491 " return function() { return x; };" |
| 492 "}"); |
| 493 Handle<Code> reference_code; |
| 494 { |
| 495 LocalContext env; |
| 496 env->Global() |
| 497 ->Set(env.local(), v8_str("x"), v8::Integer::New(CcTest::isolate(), 23)) |
| 498 .FromJust(); |
| 499 script->GetUnboundScript() |
| 500 ->BindToCurrentContext() |
| 501 ->Run(env.local()) |
| 502 .ToLocalChecked(); |
| 503 CompileRun( |
| 504 "var closure0 = MakeClosure();" |
| 505 "%DebugPrint(closure0());" |
| 506 "%OptimizeFunctionOnNextCall(closure0);" |
| 507 "%DebugPrint(closure0());"); |
| 508 Handle<JSFunction> fun0 = Handle<JSFunction>::cast( |
| 509 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 510 env->Global() |
| 511 ->Get(env.local(), v8_str("closure0")) |
| 512 .ToLocalChecked()))); |
| 513 CHECK(fun0->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 514 reference_code = handle(fun0->code()); |
| 515 // Evict only the context-dependent entry from the optimized code map. This |
| 516 // leaves it in a state where only the context-independent entry exists. |
| 517 fun0->shared()->TrimOptimizedCodeMap(SharedFunctionInfo::kEntryLength); |
| 518 } |
| 519 for (int i = 0; i < 3; i++) { |
| 520 LocalContext env; |
| 521 env->Global() |
| 522 ->Set(env.local(), v8_str("x"), v8::Integer::New(CcTest::isolate(), i)) |
| 523 .FromJust(); |
| 524 script->GetUnboundScript() |
| 525 ->BindToCurrentContext() |
| 526 ->Run(env.local()) |
| 527 .ToLocalChecked(); |
| 528 CompileRun( |
| 529 "var closure0 = MakeClosure();" |
| 530 "%DebugPrint(closure0());" |
| 531 "%OptimizeFunctionOnNextCall(closure0);" |
| 532 "%DebugPrint(closure0());" |
| 533 "var closure1 = MakeClosure(); closure1();" |
| 534 "var closure2 = MakeClosure(); closure2();"); |
| 535 Handle<JSFunction> fun1 = Handle<JSFunction>::cast( |
| 536 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 537 env->Global() |
| 538 ->Get(env.local(), v8_str("closure1")) |
| 539 .ToLocalChecked()))); |
| 540 Handle<JSFunction> fun2 = Handle<JSFunction>::cast( |
| 541 v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( |
| 542 env->Global() |
| 543 ->Get(env.local(), v8_str("closure2")) |
| 544 .ToLocalChecked()))); |
| 545 CHECK(fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 546 CHECK(fun2->IsOptimized() || !CcTest::i_isolate()->use_crankshaft()); |
| 547 CHECK_EQ(*reference_code, fun1->code()); |
| 548 CHECK_EQ(*reference_code, fun2->code()); |
| 549 } |
| 550 } |
| 551 |
| 552 |
409 TEST(CompileFunctionInContext) { | 553 TEST(CompileFunctionInContext) { |
410 CcTest::InitializeVM(); | 554 CcTest::InitializeVM(); |
411 v8::HandleScope scope(CcTest::isolate()); | 555 v8::HandleScope scope(CcTest::isolate()); |
412 LocalContext env; | 556 LocalContext env; |
413 CompileRun("var r = 10;"); | 557 CompileRun("var r = 10;"); |
414 v8::Local<v8::Object> math = v8::Local<v8::Object>::Cast( | 558 v8::Local<v8::Object> math = v8::Local<v8::Object>::Cast( |
415 env->Global()->Get(env.local(), v8_str("Math")).ToLocalChecked()); | 559 env->Global()->Get(env.local(), v8_str("Math")).ToLocalChecked()); |
416 v8::ScriptCompiler::Source script_source(v8_str( | 560 v8::ScriptCompiler::Source script_source(v8_str( |
417 "a = PI * r * r;" | 561 "a = PI * r * r;" |
418 "x = r * cos(PI);" | 562 "x = r * cos(PI);" |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 CompileRun("foo()"); | 858 CompileRun("foo()"); |
715 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); | 859 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); |
716 CompileRun("bar()"); | 860 CompileRun("bar()"); |
717 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); | 861 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); |
718 CompileRun("foo(); foo()"); | 862 CompileRun("foo(); foo()"); |
719 CHECK_EQ(4, foo->feedback_vector()->invocation_count()); | 863 CHECK_EQ(4, foo->feedback_vector()->invocation_count()); |
720 CompileRun("%BaselineFunctionOnNextCall(foo);"); | 864 CompileRun("%BaselineFunctionOnNextCall(foo);"); |
721 CompileRun("foo();"); | 865 CompileRun("foo();"); |
722 CHECK_EQ(5, foo->feedback_vector()->invocation_count()); | 866 CHECK_EQ(5, foo->feedback_vector()->invocation_count()); |
723 } | 867 } |
OLD | NEW |