| 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 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 757 { | 757 { |
| 758 v8::HandleScope scope(CcTest::isolate()); | 758 v8::HandleScope scope(CcTest::isolate()); |
| 759 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); | 759 uint16_t* two_byte_string = AsciiToTwoByteString("test string"); |
| 760 Local<String> string = String::NewExternal( | 760 Local<String> string = String::NewExternal( |
| 761 CcTest::isolate(), new TestResource(two_byte_string)); | 761 CcTest::isolate(), new TestResource(two_byte_string)); |
| 762 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); | 762 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); |
| 763 // Trigger GCs so that the newly allocated string moves to old gen. | 763 // Trigger GCs so that the newly allocated string moves to old gen. |
| 764 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now | 764 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 765 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now | 765 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 766 i::Handle<i::String> isymbol = | 766 i::Handle<i::String> isymbol = |
| 767 factory->InternalizeString(istring); | 767 factory->InternalizedStringFromString(istring); |
| 768 CHECK(isymbol->IsInternalizedString()); | 768 CHECK(isymbol->IsInternalizedString()); |
| 769 } | 769 } |
| 770 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 770 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 771 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 771 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 772 } | 772 } |
| 773 | 773 |
| 774 | 774 |
| 775 THREADED_TEST(UsingExternalAsciiString) { | 775 THREADED_TEST(UsingExternalAsciiString) { |
| 776 i::Factory* factory = CcTest::i_isolate()->factory(); | 776 i::Factory* factory = CcTest::i_isolate()->factory(); |
| 777 { | 777 { |
| 778 v8::HandleScope scope(CcTest::isolate()); | 778 v8::HandleScope scope(CcTest::isolate()); |
| 779 const char* one_byte_string = "test string"; | 779 const char* one_byte_string = "test string"; |
| 780 Local<String> string = String::NewExternal( | 780 Local<String> string = String::NewExternal( |
| 781 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string))); | 781 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string))); |
| 782 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); | 782 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string); |
| 783 // Trigger GCs so that the newly allocated string moves to old gen. | 783 // Trigger GCs so that the newly allocated string moves to old gen. |
| 784 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now | 784 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 785 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now | 785 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 786 i::Handle<i::String> isymbol = | 786 i::Handle<i::String> isymbol = |
| 787 factory->InternalizeString(istring); | 787 factory->InternalizedStringFromString(istring); |
| 788 CHECK(isymbol->IsInternalizedString()); | 788 CHECK(isymbol->IsInternalizedString()); |
| 789 } | 789 } |
| 790 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 790 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 791 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 791 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 792 } | 792 } |
| 793 | 793 |
| 794 | 794 |
| 795 THREADED_TEST(ScavengeExternalString) { | 795 THREADED_TEST(ScavengeExternalString) { |
| 796 i::FLAG_stress_compaction = false; | 796 i::FLAG_stress_compaction = false; |
| 797 i::FLAG_gc_global = false; | 797 i::FLAG_gc_global = false; |
| (...skipping 1981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2779 v8::Local<v8::Value> sym_val = sym2; | 2779 v8::Local<v8::Value> sym_val = sym2; |
| 2780 CHECK(sym_val->IsSymbol()); | 2780 CHECK(sym_val->IsSymbol()); |
| 2781 CHECK(sym_val->Equals(sym2)); | 2781 CHECK(sym_val->Equals(sym2)); |
| 2782 CHECK(sym_val->StrictEquals(sym2)); | 2782 CHECK(sym_val->StrictEquals(sym2)); |
| 2783 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2)); | 2783 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2)); |
| 2784 | 2784 |
| 2785 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2); | 2785 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2); |
| 2786 CHECK(sym_obj->IsSymbolObject()); | 2786 CHECK(sym_obj->IsSymbolObject()); |
| 2787 CHECK(!sym2->IsSymbolObject()); | 2787 CHECK(!sym2->IsSymbolObject()); |
| 2788 CHECK(!obj->IsSymbolObject()); | 2788 CHECK(!obj->IsSymbolObject()); |
| 2789 CHECK(!sym_obj->Equals(sym2)); | 2789 CHECK(sym_obj->Equals(sym2)); |
| 2790 CHECK(!sym_obj->StrictEquals(sym2)); | 2790 CHECK(!sym_obj->StrictEquals(sym2)); |
| 2791 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj)); | 2791 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj)); |
| 2792 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2)); | 2792 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2)); |
| 2793 | 2793 |
| 2794 // Make sure delete of a non-existent symbol property works. | 2794 // Make sure delete of a non-existent symbol property works. |
| 2795 CHECK(obj->Delete(sym1)); | 2795 CHECK(obj->Delete(sym1)); |
| 2796 CHECK(!obj->Has(sym1)); | 2796 CHECK(!obj->Has(sym1)); |
| 2797 | 2797 |
| 2798 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503))); | 2798 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503))); |
| 2799 CHECK(obj->Has(sym1)); | 2799 CHECK(obj->Has(sym1)); |
| (...skipping 4292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7092 } | 7092 } |
| 7093 | 7093 |
| 7094 object_a.flag = false; | 7094 object_a.flag = false; |
| 7095 object_b.flag = false; | 7095 object_b.flag = false; |
| 7096 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag); | 7096 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag); |
| 7097 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag); | 7097 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag); |
| 7098 CHECK(!object_b.handle.IsIndependent()); | 7098 CHECK(!object_b.handle.IsIndependent()); |
| 7099 object_a.handle.MarkIndependent(); | 7099 object_a.handle.MarkIndependent(); |
| 7100 object_b.handle.MarkIndependent(); | 7100 object_b.handle.MarkIndependent(); |
| 7101 CHECK(object_b.handle.IsIndependent()); | 7101 CHECK(object_b.handle.IsIndependent()); |
| 7102 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 7102 CcTest::heap()->PerformScavenge(); |
| 7103 CHECK(object_a.flag); | 7103 CHECK(object_a.flag); |
| 7104 CHECK(object_b.flag); | 7104 CHECK(object_b.flag); |
| 7105 } | 7105 } |
| 7106 | 7106 |
| 7107 | 7107 |
| 7108 static void InvokeScavenge() { | 7108 static void InvokeScavenge() { |
| 7109 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 7109 CcTest::heap()->PerformScavenge(); |
| 7110 } | 7110 } |
| 7111 | 7111 |
| 7112 | 7112 |
| 7113 static void InvokeMarkSweep() { | 7113 static void InvokeMarkSweep() { |
| 7114 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 7114 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 7115 } | 7115 } |
| 7116 | 7116 |
| 7117 | 7117 |
| 7118 static void ForceScavenge( | 7118 static void ForceScavenge( |
| 7119 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { | 7119 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7181 v8::HandleScope handle_scope(isolate); | 7181 v8::HandleScope handle_scope(isolate); |
| 7182 v8::Local<v8::Object> o = v8::Object::New(isolate); | 7182 v8::Local<v8::Object> o = v8::Object::New(isolate); |
| 7183 object.handle.Reset(isolate, o); | 7183 object.handle.Reset(isolate, o); |
| 7184 o->Set(v8_str("x"), v8::Integer::New(isolate, 1)); | 7184 o->Set(v8_str("x"), v8::Integer::New(isolate, 1)); |
| 7185 v8::Local<String> y_str = v8_str("y"); | 7185 v8::Local<String> y_str = v8_str("y"); |
| 7186 o->Set(y_str, y_str); | 7186 o->Set(y_str, y_str); |
| 7187 } | 7187 } |
| 7188 object.flag = false; | 7188 object.flag = false; |
| 7189 object.handle.SetWeak(&object, &RevivingCallback); | 7189 object.handle.SetWeak(&object, &RevivingCallback); |
| 7190 object.handle.MarkIndependent(); | 7190 object.handle.MarkIndependent(); |
| 7191 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 7191 CcTest::heap()->PerformScavenge(); |
| 7192 CHECK(object.flag); | 7192 CHECK(object.flag); |
| 7193 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); | 7193 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); |
| 7194 { | 7194 { |
| 7195 v8::HandleScope handle_scope(isolate); | 7195 v8::HandleScope handle_scope(isolate); |
| 7196 v8::Local<v8::Object> o = | 7196 v8::Local<v8::Object> o = |
| 7197 v8::Local<v8::Object>::New(isolate, object.handle); | 7197 v8::Local<v8::Object>::New(isolate, object.handle); |
| 7198 v8::Local<String> y_str = v8_str("y"); | 7198 v8::Local<String> y_str = v8_str("y"); |
| 7199 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x"))); | 7199 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x"))); |
| 7200 CHECK(o->Get(y_str)->Equals(y_str)); | 7200 CHECK(o->Get(y_str)->Equals(y_str)); |
| 7201 } | 7201 } |
| (...skipping 10311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17513 "outer()\n%s"; | 17513 "outer()\n%s"; |
| 17514 | 17514 |
| 17515 i::ScopedVector<char> code(1024); | 17515 i::ScopedVector<char> code(1024); |
| 17516 i::OS::SNPrintF(code, source, "//# sourceURL=source_url"); | 17516 i::OS::SNPrintF(code, source, "//# sourceURL=source_url"); |
| 17517 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined()); | 17517 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined()); |
| 17518 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url"); | 17518 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url"); |
| 17519 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined()); | 17519 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined()); |
| 17520 } | 17520 } |
| 17521 | 17521 |
| 17522 | 17522 |
| 17523 TEST(DynamicWithSourceURLInStackTraceString) { | |
| 17524 LocalContext context; | |
| 17525 v8::HandleScope scope(context->GetIsolate()); | |
| 17526 | |
| 17527 const char *source = | |
| 17528 "function outer() {\n" | |
| 17529 " function foo() {\n" | |
| 17530 " FAIL.FAIL;\n" | |
| 17531 " }\n" | |
| 17532 " foo();\n" | |
| 17533 "}\n" | |
| 17534 "outer()\n%s"; | |
| 17535 | |
| 17536 i::ScopedVector<char> code(1024); | |
| 17537 i::OS::SNPrintF(code, source, "//# sourceURL=source_url"); | |
| 17538 v8::TryCatch try_catch; | |
| 17539 CompileRunWithOrigin(code.start(), "", 0, 0); | |
| 17540 CHECK(try_catch.HasCaught()); | |
| 17541 v8::String::Utf8Value stack(try_catch.StackTrace()); | |
| 17542 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL); | |
| 17543 } | |
| 17544 | |
| 17545 | |
| 17546 static void CreateGarbageInOldSpace() { | 17523 static void CreateGarbageInOldSpace() { |
| 17547 i::Factory* factory = CcTest::i_isolate()->factory(); | 17524 i::Factory* factory = CcTest::i_isolate()->factory(); |
| 17548 v8::HandleScope scope(CcTest::isolate()); | 17525 v8::HandleScope scope(CcTest::isolate()); |
| 17549 i::AlwaysAllocateScope always_allocate; | 17526 i::AlwaysAllocateScope always_allocate; |
| 17550 for (int i = 0; i < 1000; i++) { | 17527 for (int i = 0; i < 1000; i++) { |
| 17551 factory->NewFixedArray(1000, i::TENURED); | 17528 factory->NewFixedArray(1000, i::TENURED); |
| 17552 } | 17529 } |
| 17553 } | 17530 } |
| 17554 | 17531 |
| 17555 | 17532 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17643 finished = v8::V8::IdleNotification(kShortIdlePauseInMs); | 17620 finished = v8::V8::IdleNotification(kShortIdlePauseInMs); |
| 17644 } | 17621 } |
| 17645 intptr_t final_size = CcTest::heap()->SizeOfObjects(); | 17622 intptr_t final_size = CcTest::heap()->SizeOfObjects(); |
| 17646 CHECK_LT(final_size, initial_size + 1); | 17623 CHECK_LT(final_size, initial_size + 1); |
| 17647 } | 17624 } |
| 17648 | 17625 |
| 17649 | 17626 |
| 17650 TEST(Regress2333) { | 17627 TEST(Regress2333) { |
| 17651 LocalContext env; | 17628 LocalContext env; |
| 17652 for (int i = 0; i < 3; i++) { | 17629 for (int i = 0; i < 3; i++) { |
| 17653 CcTest::heap()->CollectGarbage(i::NEW_SPACE); | 17630 CcTest::heap()->PerformScavenge(); |
| 17654 } | 17631 } |
| 17655 } | 17632 } |
| 17656 | 17633 |
| 17657 static uint32_t* stack_limit; | 17634 static uint32_t* stack_limit; |
| 17658 | 17635 |
| 17659 static void GetStackLimitCallback( | 17636 static void GetStackLimitCallback( |
| 17660 const v8::FunctionCallbackInfo<v8::Value>& args) { | 17637 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 17661 stack_limit = reinterpret_cast<uint32_t*>( | 17638 stack_limit = reinterpret_cast<uint32_t*>( |
| 17662 CcTest::i_isolate()->stack_guard()->real_climit()); | 17639 CcTest::i_isolate()->stack_guard()->real_climit()); |
| 17663 } | 17640 } |
| (...skipping 2843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20507 | 20484 |
| 20508 | 20485 |
| 20509 TEST(CallCompletedCallbackTwoExceptions) { | 20486 TEST(CallCompletedCallbackTwoExceptions) { |
| 20510 LocalContext env; | 20487 LocalContext env; |
| 20511 v8::HandleScope scope(env->GetIsolate()); | 20488 v8::HandleScope scope(env->GetIsolate()); |
| 20512 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException); | 20489 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException); |
| 20513 CompileRun("throw 'first exception';"); | 20490 CompileRun("throw 'first exception';"); |
| 20514 } | 20491 } |
| 20515 | 20492 |
| 20516 | 20493 |
| 20517 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) { | |
| 20518 v8::HandleScope scope(info.GetIsolate()); | |
| 20519 CompileRun("ext1Calls++;"); | |
| 20520 } | |
| 20521 | |
| 20522 | |
| 20523 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) { | |
| 20524 v8::HandleScope scope(info.GetIsolate()); | |
| 20525 CompileRun("ext2Calls++;"); | |
| 20526 } | |
| 20527 | |
| 20528 | |
| 20529 TEST(EnqueueMicrotask) { | |
| 20530 LocalContext env; | |
| 20531 v8::HandleScope scope(env->GetIsolate()); | |
| 20532 CompileRun( | |
| 20533 "var ext1Calls = 0;" | |
| 20534 "var ext2Calls = 0;"); | |
| 20535 CompileRun("1+1;"); | |
| 20536 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value()); | |
| 20537 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value()); | |
| 20538 | |
| 20539 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20540 Function::New(env->GetIsolate(), MicrotaskOne)); | |
| 20541 CompileRun("1+1;"); | |
| 20542 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value()); | |
| 20543 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value()); | |
| 20544 | |
| 20545 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20546 Function::New(env->GetIsolate(), MicrotaskOne)); | |
| 20547 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20548 Function::New(env->GetIsolate(), MicrotaskTwo)); | |
| 20549 CompileRun("1+1;"); | |
| 20550 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20551 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value()); | |
| 20552 | |
| 20553 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20554 Function::New(env->GetIsolate(), MicrotaskTwo)); | |
| 20555 CompileRun("1+1;"); | |
| 20556 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20557 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value()); | |
| 20558 | |
| 20559 CompileRun("1+1;"); | |
| 20560 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20561 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value()); | |
| 20562 } | |
| 20563 | |
| 20564 | |
| 20565 TEST(SetAutorunMicrotasks) { | |
| 20566 LocalContext env; | |
| 20567 v8::HandleScope scope(env->GetIsolate()); | |
| 20568 CompileRun( | |
| 20569 "var ext1Calls = 0;" | |
| 20570 "var ext2Calls = 0;"); | |
| 20571 CompileRun("1+1;"); | |
| 20572 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value()); | |
| 20573 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value()); | |
| 20574 | |
| 20575 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20576 Function::New(env->GetIsolate(), MicrotaskOne)); | |
| 20577 CompileRun("1+1;"); | |
| 20578 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value()); | |
| 20579 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value()); | |
| 20580 | |
| 20581 V8::SetAutorunMicrotasks(env->GetIsolate(), false); | |
| 20582 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20583 Function::New(env->GetIsolate(), MicrotaskOne)); | |
| 20584 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20585 Function::New(env->GetIsolate(), MicrotaskTwo)); | |
| 20586 CompileRun("1+1;"); | |
| 20587 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value()); | |
| 20588 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value()); | |
| 20589 | |
| 20590 V8::RunMicrotasks(env->GetIsolate()); | |
| 20591 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20592 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value()); | |
| 20593 | |
| 20594 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20595 Function::New(env->GetIsolate(), MicrotaskTwo)); | |
| 20596 CompileRun("1+1;"); | |
| 20597 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20598 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value()); | |
| 20599 | |
| 20600 V8::RunMicrotasks(env->GetIsolate()); | |
| 20601 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20602 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value()); | |
| 20603 | |
| 20604 V8::SetAutorunMicrotasks(env->GetIsolate(), true); | |
| 20605 v8::V8::EnqueueMicrotask(env->GetIsolate(), | |
| 20606 Function::New(env->GetIsolate(), MicrotaskTwo)); | |
| 20607 CompileRun("1+1;"); | |
| 20608 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value()); | |
| 20609 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value()); | |
| 20610 } | |
| 20611 | |
| 20612 | |
| 20613 static int probes_counter = 0; | 20494 static int probes_counter = 0; |
| 20614 static int misses_counter = 0; | 20495 static int misses_counter = 0; |
| 20615 static int updates_counter = 0; | 20496 static int updates_counter = 0; |
| 20616 | 20497 |
| 20617 | 20498 |
| 20618 static int* LookupCounter(const char* name) { | 20499 static int* LookupCounter(const char* name) { |
| 20619 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) { | 20500 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) { |
| 20620 return &probes_counter; | 20501 return &probes_counter; |
| 20621 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) { | 20502 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) { |
| 20622 return &misses_counter; | 20503 return &misses_counter; |
| (...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21926 static void OptimizationCallback( | 21807 static void OptimizationCallback( |
| 21927 const v8::FunctionCallbackInfo<v8::Value>& info) { | 21808 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 21928 CHECK(callee == info.Callee()); | 21809 CHECK(callee == info.Callee()); |
| 21929 CHECK(data == info.Data()); | 21810 CHECK(data == info.Data()); |
| 21930 CHECK(receiver == info.This()); | 21811 CHECK(receiver == info.This()); |
| 21931 if (info.Length() == 1) { | 21812 if (info.Length() == 1) { |
| 21932 CHECK_EQ(v8_num(1), info[0]); | 21813 CHECK_EQ(v8_num(1), info[0]); |
| 21933 } | 21814 } |
| 21934 CHECK(holder == info.Holder()); | 21815 CHECK(holder == info.Holder()); |
| 21935 count++; | 21816 count++; |
| 21936 info.GetReturnValue().Set(v8_str("returned")); | |
| 21937 } | 21817 } |
| 21938 | 21818 |
| 21939 // TODO(dcarney): move this to v8.h | 21819 // TODO(dcarney): move this to v8.h |
| 21940 static void SetAccessorProperty(Local<Object> object, | 21820 static void SetAccessorProperty(Local<Object> object, |
| 21941 Local<String> name, | 21821 Local<String> name, |
| 21942 Local<Function> getter, | 21822 Local<Function> getter, |
| 21943 Local<Function> setter = Local<Function>()) { | 21823 Local<Function> setter = Local<Function>()) { |
| 21944 i::Isolate* isolate = CcTest::i_isolate(); | 21824 i::Isolate* isolate = CcTest::i_isolate(); |
| 21945 v8::AccessControl settings = v8::DEFAULT; | 21825 v8::AccessControl settings = v8::DEFAULT; |
| 21946 v8::PropertyAttribute attribute = v8::None; | 21826 v8::PropertyAttribute attribute = v8::None; |
| 21947 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter); | 21827 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter); |
| 21948 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true); | 21828 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true); |
| 21949 if (setter_i.is_null()) setter_i = isolate->factory()->null_value(); | 21829 if (setter_i.is_null()) setter_i = isolate->factory()->null_value(); |
| 21950 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(*object), | 21830 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(*object), |
| 21951 v8::Utils::OpenHandle(*name), | 21831 v8::Utils::OpenHandle(*name), |
| 21952 getter_i, | 21832 getter_i, |
| 21953 setter_i, | 21833 setter_i, |
| 21954 static_cast<PropertyAttributes>(attribute), | 21834 static_cast<PropertyAttributes>(attribute), |
| 21955 settings); | 21835 settings); |
| 21956 } | 21836 } |
| 21957 | 21837 |
| 21958 public: | 21838 public: |
| 21959 enum SignatureType { | 21839 void Run(bool use_signature, bool global) { |
| 21960 kNoSignature, | |
| 21961 kSignatureOnReceiver, | |
| 21962 kSignatureOnPrototype | |
| 21963 }; | |
| 21964 | |
| 21965 void RunAll() { | |
| 21966 SignatureType signature_types[] = | |
| 21967 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype}; | |
| 21968 for (unsigned i = 0; i < ARRAY_SIZE(signature_types); i++) { | |
| 21969 SignatureType signature_type = signature_types[i]; | |
| 21970 for (int j = 0; j < 2; j++) { | |
| 21971 bool global = j == 0; | |
| 21972 int key = signature_type + | |
| 21973 ARRAY_SIZE(signature_types) * (global ? 1 : 0); | |
| 21974 Run(signature_type, global, key); | |
| 21975 } | |
| 21976 } | |
| 21977 } | |
| 21978 | |
| 21979 void Run(SignatureType signature_type, bool global, int key) { | |
| 21980 v8::Isolate* isolate = CcTest::isolate(); | 21840 v8::Isolate* isolate = CcTest::isolate(); |
| 21981 v8::HandleScope scope(isolate); | 21841 v8::HandleScope scope(isolate); |
| 21982 // Build a template for signature checks. | 21842 // Build a template for signature checks. |
| 21983 Local<v8::ObjectTemplate> signature_template; | 21843 Local<v8::ObjectTemplate> signature_template; |
| 21984 Local<v8::Signature> signature; | 21844 Local<v8::Signature> signature; |
| 21985 { | 21845 { |
| 21986 Local<v8::FunctionTemplate> parent_template = | 21846 Local<v8::FunctionTemplate> parent_template = |
| 21987 FunctionTemplate::New(isolate); | 21847 FunctionTemplate::New(isolate); |
| 21988 parent_template->SetHiddenPrototype(true); | 21848 parent_template->SetHiddenPrototype(true); |
| 21989 Local<v8::FunctionTemplate> function_template | 21849 Local<v8::FunctionTemplate> function_template |
| 21990 = FunctionTemplate::New(isolate); | 21850 = FunctionTemplate::New(isolate); |
| 21991 function_template->Inherit(parent_template); | 21851 function_template->Inherit(parent_template); |
| 21992 switch (signature_type) { | 21852 if (use_signature) { |
| 21993 case kNoSignature: | 21853 signature = v8::Signature::New(isolate, parent_template); |
| 21994 break; | |
| 21995 case kSignatureOnReceiver: | |
| 21996 signature = v8::Signature::New(isolate, function_template); | |
| 21997 break; | |
| 21998 case kSignatureOnPrototype: | |
| 21999 signature = v8::Signature::New(isolate, parent_template); | |
| 22000 break; | |
| 22001 } | 21854 } |
| 22002 signature_template = function_template->InstanceTemplate(); | 21855 signature_template = function_template->InstanceTemplate(); |
| 22003 } | 21856 } |
| 22004 // Global object must pass checks. | 21857 // Global object must pass checks. |
| 22005 Local<v8::Context> context = | 21858 Local<v8::Context> context = |
| 22006 v8::Context::New(isolate, NULL, signature_template); | 21859 v8::Context::New(isolate, NULL, signature_template); |
| 22007 v8::Context::Scope context_scope(context); | 21860 v8::Context::Scope context_scope(context); |
| 22008 // Install regular object that can pass signature checks. | 21861 // Install regular object that can pass signature checks. |
| 22009 Local<Object> function_receiver = signature_template->NewInstance(); | 21862 Local<Object> function_receiver = signature_template->NewInstance(); |
| 22010 context->Global()->Set(v8_str("function_receiver"), function_receiver); | 21863 context->Global()->Set(v8_str("function_receiver"), function_receiver); |
| 22011 // Get the holder objects. | 21864 // Get the holder objects. |
| 22012 Local<Object> inner_global = | 21865 Local<Object> inner_global = |
| 22013 Local<Object>::Cast(context->Global()->GetPrototype()); | 21866 Local<Object>::Cast(context->Global()->GetPrototype()); |
| 22014 // Install functions on hidden prototype object if there is one. | 21867 Local<Object> function_holder = |
| 21868 Local<Object>::Cast(function_receiver->GetPrototype()); |
| 21869 // Install function on hidden prototype object. |
| 22015 data = Object::New(isolate); | 21870 data = Object::New(isolate); |
| 22016 Local<FunctionTemplate> function_template = FunctionTemplate::New( | 21871 Local<FunctionTemplate> function_template = FunctionTemplate::New( |
| 22017 isolate, OptimizationCallback, data, signature); | 21872 isolate, OptimizationCallback, data, signature); |
| 22018 Local<Function> function = function_template->GetFunction(); | 21873 Local<Function> function = function_template->GetFunction(); |
| 22019 Local<Object> global_holder = inner_global; | 21874 Local<Object> global_holder = Local<Object>::Cast( |
| 22020 Local<Object> function_holder = function_receiver; | 21875 inner_global->GetPrototype()); |
| 22021 if (signature_type == kSignatureOnPrototype) { | |
| 22022 function_holder = Local<Object>::Cast(function_holder->GetPrototype()); | |
| 22023 global_holder = Local<Object>::Cast(global_holder->GetPrototype()); | |
| 22024 } | |
| 22025 global_holder->Set(v8_str("g_f"), function); | 21876 global_holder->Set(v8_str("g_f"), function); |
| 22026 SetAccessorProperty(global_holder, v8_str("g_acc"), function, function); | 21877 SetAccessorProperty(global_holder, v8_str("g_acc"), function, function); |
| 22027 function_holder->Set(v8_str("f"), function); | 21878 function_holder->Set(v8_str("f"), function); |
| 22028 SetAccessorProperty(function_holder, v8_str("acc"), function, function); | 21879 SetAccessorProperty(function_holder, v8_str("acc"), function, function); |
| 22029 // Initialize expected values. | 21880 // Initialize expected values. |
| 22030 callee = function; | 21881 callee = function; |
| 22031 count = 0; | 21882 count = 0; |
| 22032 if (global) { | 21883 if (global) { |
| 22033 receiver = context->Global(); | 21884 receiver = context->Global(); |
| 22034 holder = inner_global; | 21885 holder = inner_global; |
| 22035 } else { | 21886 } else { |
| 22036 holder = function_receiver; | 21887 holder = function_receiver; |
| 22037 // If not using a signature, add something else to the prototype chain | 21888 // If not using a signature, add something else to the prototype chain |
| 22038 // to test the case that holder != receiver | 21889 // to test the case that holder != receiver |
| 22039 if (signature_type == kNoSignature) { | 21890 if (!use_signature) { |
| 22040 receiver = Local<Object>::Cast(CompileRun( | 21891 receiver = Local<Object>::Cast(CompileRun( |
| 22041 "var receiver_subclass = {};\n" | 21892 "var receiver_subclass = {};\n" |
| 22042 "receiver_subclass.__proto__ = function_receiver;\n" | 21893 "receiver_subclass.__proto__ = function_receiver;\n" |
| 22043 "receiver_subclass")); | 21894 "receiver_subclass")); |
| 22044 } else { | 21895 } else { |
| 22045 receiver = Local<Object>::Cast(CompileRun( | 21896 receiver = Local<Object>::Cast(CompileRun( |
| 22046 "var receiver_subclass = function_receiver;\n" | 21897 "var receiver_subclass = function_receiver;\n" |
| 22047 "receiver_subclass")); | 21898 "receiver_subclass")); |
| 22048 } | 21899 } |
| 22049 } | 21900 } |
| 22050 // With no signature, the holder is not set. | 21901 // With no signature, the holder is not set. |
| 22051 if (signature_type == kNoSignature) holder = receiver; | 21902 if (!use_signature) holder = receiver; |
| 22052 // build wrap_function | 21903 // build wrap_function |
| 21904 int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0); |
| 22053 i::ScopedVector<char> wrap_function(200); | 21905 i::ScopedVector<char> wrap_function(200); |
| 22054 if (global) { | 21906 if (global) { |
| 22055 i::OS::SNPrintF( | 21907 i::OS::SNPrintF( |
| 22056 wrap_function, | 21908 wrap_function, |
| 22057 "function wrap_f_%d() { var f = g_f; return f(); }\n" | 21909 "function wrap_f_%d() { var f = g_f; return f(); }\n" |
| 22058 "function wrap_get_%d() { return this.g_acc; }\n" | 21910 "function wrap_get_%d() { return this.g_acc; }\n" |
| 22059 "function wrap_set_%d() { return this.g_acc = 1; }\n", | 21911 "function wrap_set_%d() { this.g_acc = 1; }\n", |
| 22060 key, key, key); | 21912 key, key, key); |
| 22061 } else { | 21913 } else { |
| 22062 i::OS::SNPrintF( | 21914 i::OS::SNPrintF( |
| 22063 wrap_function, | 21915 wrap_function, |
| 22064 "function wrap_f_%d() { return receiver_subclass.f(); }\n" | 21916 "function wrap_f_%d() { return receiver_subclass.f(); }\n" |
| 22065 "function wrap_get_%d() { return receiver_subclass.acc; }\n" | 21917 "function wrap_get_%d() { return receiver_subclass.acc; }\n" |
| 22066 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n", | 21918 "function wrap_set_%d() { receiver_subclass.acc = 1; }\n", |
| 22067 key, key, key); | 21919 key, key, key); |
| 22068 } | 21920 } |
| 22069 // build source string | 21921 // build source string |
| 22070 i::ScopedVector<char> source(1000); | 21922 i::ScopedVector<char> source(500); |
| 22071 i::OS::SNPrintF( | 21923 i::OS::SNPrintF( |
| 22072 source, | 21924 source, |
| 22073 "%s\n" // wrap functions | 21925 "%s\n" // wrap functions |
| 22074 "function wrap_f() { return wrap_f_%d(); }\n" | 21926 "function wrap_f() { wrap_f_%d(); }\n" |
| 22075 "function wrap_get() { return wrap_get_%d(); }\n" | 21927 "function wrap_get() { wrap_get_%d(); }\n" |
| 22076 "function wrap_set() { return wrap_set_%d(); }\n" | 21928 "function wrap_set() { wrap_set_%d(); }\n" |
| 22077 "check = function(returned) {\n" | |
| 22078 " if (returned !== 'returned') { throw returned; }\n" | |
| 22079 "}\n" | |
| 22080 "\n" | 21929 "\n" |
| 22081 "check(wrap_f());\n" | 21930 "wrap_f();\n" |
| 22082 "check(wrap_f());\n" | 21931 "wrap_f();\n" |
| 22083 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n" | 21932 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n" |
| 22084 "check(wrap_f());\n" | 21933 "wrap_f();\n" |
| 22085 "\n" | 21934 "\n" |
| 22086 "check(wrap_get());\n" | 21935 "wrap_get();\n" |
| 22087 "check(wrap_get());\n" | 21936 "wrap_get();\n" |
| 22088 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n" | 21937 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n" |
| 22089 "check(wrap_get());\n" | 21938 "wrap_get();\n" |
| 22090 "\n" | 21939 "\n" |
| 22091 "check = function(returned) {\n" | 21940 "wrap_set();\n" |
| 22092 " if (returned !== 1) { throw returned; }\n" | 21941 "wrap_set();\n" |
| 22093 "}\n" | |
| 22094 "check(wrap_set());\n" | |
| 22095 "check(wrap_set());\n" | |
| 22096 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n" | 21942 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n" |
| 22097 "check(wrap_set());\n", | 21943 "wrap_set();\n", |
| 22098 wrap_function.start(), key, key, key, key, key, key); | 21944 wrap_function.start(), key, key, key, key, key, key); |
| 22099 v8::TryCatch try_catch; | 21945 v8::TryCatch try_catch; |
| 22100 CompileRun(source.start()); | 21946 CompileRun(source.start()); |
| 22101 ASSERT(!try_catch.HasCaught()); | 21947 ASSERT(!try_catch.HasCaught()); |
| 22102 CHECK_EQ(9, count); | 21948 CHECK_EQ(9, count); |
| 22103 } | 21949 } |
| 22104 }; | 21950 }; |
| 22105 | 21951 |
| 22106 | 21952 |
| 22107 Local<Object> ApiCallOptimizationChecker::data; | 21953 Local<Object> ApiCallOptimizationChecker::data; |
| 22108 Local<Object> ApiCallOptimizationChecker::receiver; | 21954 Local<Object> ApiCallOptimizationChecker::receiver; |
| 22109 Local<Object> ApiCallOptimizationChecker::holder; | 21955 Local<Object> ApiCallOptimizationChecker::holder; |
| 22110 Local<Object> ApiCallOptimizationChecker::callee; | 21956 Local<Object> ApiCallOptimizationChecker::callee; |
| 22111 int ApiCallOptimizationChecker::count = 0; | 21957 int ApiCallOptimizationChecker::count = 0; |
| 22112 | 21958 |
| 22113 | 21959 |
| 22114 TEST(TestFunctionCallOptimization) { | 21960 TEST(TestFunctionCallOptimization) { |
| 22115 i::FLAG_allow_natives_syntax = true; | 21961 i::FLAG_allow_natives_syntax = true; |
| 22116 ApiCallOptimizationChecker checker; | 21962 ApiCallOptimizationChecker checker; |
| 22117 checker.RunAll(); | 21963 checker.Run(true, true); |
| 21964 checker.Run(false, true); |
| 21965 checker.Run(true, false); |
| 21966 checker.Run(false, false); |
| 22118 } | 21967 } |
| OLD | NEW |