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 | |
553 TEST(CompileFunctionInContext) { | 409 TEST(CompileFunctionInContext) { |
554 CcTest::InitializeVM(); | 410 CcTest::InitializeVM(); |
555 v8::HandleScope scope(CcTest::isolate()); | 411 v8::HandleScope scope(CcTest::isolate()); |
556 LocalContext env; | 412 LocalContext env; |
557 CompileRun("var r = 10;"); | 413 CompileRun("var r = 10;"); |
558 v8::Local<v8::Object> math = v8::Local<v8::Object>::Cast( | 414 v8::Local<v8::Object> math = v8::Local<v8::Object>::Cast( |
559 env->Global()->Get(env.local(), v8_str("Math")).ToLocalChecked()); | 415 env->Global()->Get(env.local(), v8_str("Math")).ToLocalChecked()); |
560 v8::ScriptCompiler::Source script_source(v8_str( | 416 v8::ScriptCompiler::Source script_source(v8_str( |
561 "a = PI * r * r;" | 417 "a = PI * r * r;" |
562 "x = r * cos(PI);" | 418 "x = r * cos(PI);" |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 CompileRun("foo()"); | 714 CompileRun("foo()"); |
859 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); | 715 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); |
860 CompileRun("bar()"); | 716 CompileRun("bar()"); |
861 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); | 717 CHECK_EQ(2, foo->feedback_vector()->invocation_count()); |
862 CompileRun("foo(); foo()"); | 718 CompileRun("foo(); foo()"); |
863 CHECK_EQ(4, foo->feedback_vector()->invocation_count()); | 719 CHECK_EQ(4, foo->feedback_vector()->invocation_count()); |
864 CompileRun("%BaselineFunctionOnNextCall(foo);"); | 720 CompileRun("%BaselineFunctionOnNextCall(foo);"); |
865 CompileRun("foo();"); | 721 CompileRun("foo();"); |
866 CHECK_EQ(5, foo->feedback_vector()->invocation_count()); | 722 CHECK_EQ(5, foo->feedback_vector()->invocation_count()); |
867 } | 723 } |
OLD | NEW |