| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 | 2 |
| 3 #include <stdlib.h> | 3 #include <stdlib.h> |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "compilation-cache.h" | 7 #include "compilation-cache.h" |
| 8 #include "execution.h" | 8 #include "execution.h" |
| 9 #include "factory.h" | 9 #include "factory.h" |
| 10 #include "macro-assembler.h" | 10 #include "macro-assembler.h" |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 global_handles->Destroy(h3.location()); | 351 global_handles->Destroy(h3.location()); |
| 352 | 352 |
| 353 CHECK_EQ(*h4, *h2); | 353 CHECK_EQ(*h4, *h2); |
| 354 global_handles->Destroy(h2.location()); | 354 global_handles->Destroy(h2.location()); |
| 355 global_handles->Destroy(h4.location()); | 355 global_handles->Destroy(h4.location()); |
| 356 } | 356 } |
| 357 | 357 |
| 358 | 358 |
| 359 static bool WeakPointerCleared = false; | 359 static bool WeakPointerCleared = false; |
| 360 | 360 |
| 361 static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Value> handle, | 361 static void TestWeakGlobalHandleCallback(v8::Isolate* isolate, |
| 362 v8::Persistent<v8::Value> handle, |
| 362 void* id) { | 363 void* id) { |
| 363 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true; | 364 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true; |
| 364 handle.Dispose(); | 365 handle.Dispose(isolate); |
| 365 } | 366 } |
| 366 | 367 |
| 367 | 368 |
| 368 TEST(WeakGlobalHandlesScavenge) { | 369 TEST(WeakGlobalHandlesScavenge) { |
| 369 InitializeVM(); | 370 InitializeVM(); |
| 370 GlobalHandles* global_handles = Isolate::Current()->global_handles(); | 371 GlobalHandles* global_handles = Isolate::Current()->global_handles(); |
| 371 | 372 |
| 372 WeakPointerCleared = false; | 373 WeakPointerCleared = false; |
| 373 | 374 |
| 374 Handle<Object> h1; | 375 Handle<Object> h1; |
| 375 Handle<Object> h2; | 376 Handle<Object> h2; |
| 376 | 377 |
| 377 { | 378 { |
| 378 HandleScope scope; | 379 HandleScope scope; |
| 379 | 380 |
| 380 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); | 381 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); |
| 381 Handle<Object> u = FACTORY->NewNumber(1.12344); | 382 Handle<Object> u = FACTORY->NewNumber(1.12344); |
| 382 | 383 |
| 383 h1 = global_handles->Create(*i); | 384 h1 = global_handles->Create(*i); |
| 384 h2 = global_handles->Create(*u); | 385 h2 = global_handles->Create(*u); |
| 385 } | 386 } |
| 386 | 387 |
| 387 global_handles->MakeWeak(h2.location(), | 388 global_handles->MakeWeak(h2.location(), |
| 388 reinterpret_cast<void*>(1234), | 389 reinterpret_cast<void*>(1234), |
| 390 NULL, |
| 389 &TestWeakGlobalHandleCallback); | 391 &TestWeakGlobalHandleCallback); |
| 390 | 392 |
| 391 // Scavenge treats weak pointers as normal roots. | 393 // Scavenge treats weak pointers as normal roots. |
| 392 HEAP->PerformScavenge(); | 394 HEAP->PerformScavenge(); |
| 393 | 395 |
| 394 CHECK((*h1)->IsString()); | 396 CHECK((*h1)->IsString()); |
| 395 CHECK((*h2)->IsHeapNumber()); | 397 CHECK((*h2)->IsHeapNumber()); |
| 396 | 398 |
| 397 CHECK(!WeakPointerCleared); | 399 CHECK(!WeakPointerCleared); |
| 398 CHECK(!global_handles->IsNearDeath(h2.location())); | 400 CHECK(!global_handles->IsNearDeath(h2.location())); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 422 h2 = global_handles->Create(*u); | 424 h2 = global_handles->Create(*u); |
| 423 } | 425 } |
| 424 | 426 |
| 425 // Make sure the objects are promoted. | 427 // Make sure the objects are promoted. |
| 426 HEAP->CollectGarbage(OLD_POINTER_SPACE); | 428 HEAP->CollectGarbage(OLD_POINTER_SPACE); |
| 427 HEAP->CollectGarbage(NEW_SPACE); | 429 HEAP->CollectGarbage(NEW_SPACE); |
| 428 CHECK(!HEAP->InNewSpace(*h1) && !HEAP->InNewSpace(*h2)); | 430 CHECK(!HEAP->InNewSpace(*h1) && !HEAP->InNewSpace(*h2)); |
| 429 | 431 |
| 430 global_handles->MakeWeak(h2.location(), | 432 global_handles->MakeWeak(h2.location(), |
| 431 reinterpret_cast<void*>(1234), | 433 reinterpret_cast<void*>(1234), |
| 434 NULL, |
| 432 &TestWeakGlobalHandleCallback); | 435 &TestWeakGlobalHandleCallback); |
| 433 CHECK(!GlobalHandles::IsNearDeath(h1.location())); | 436 CHECK(!GlobalHandles::IsNearDeath(h1.location())); |
| 434 CHECK(!GlobalHandles::IsNearDeath(h2.location())); | 437 CHECK(!GlobalHandles::IsNearDeath(h2.location())); |
| 435 | 438 |
| 436 // Incremental marking potentially marked handles before they turned weak. | 439 // Incremental marking potentially marked handles before they turned weak. |
| 437 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 440 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
| 438 | 441 |
| 439 CHECK((*h1)->IsString()); | 442 CHECK((*h1)->IsString()); |
| 440 | 443 |
| 441 CHECK(WeakPointerCleared); | 444 CHECK(WeakPointerCleared); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 455 | 458 |
| 456 { | 459 { |
| 457 HandleScope scope; | 460 HandleScope scope; |
| 458 | 461 |
| 459 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); | 462 Handle<Object> i = FACTORY->NewStringFromAscii(CStrVector("fisk")); |
| 460 h = global_handles->Create(*i); | 463 h = global_handles->Create(*i); |
| 461 } | 464 } |
| 462 | 465 |
| 463 global_handles->MakeWeak(h.location(), | 466 global_handles->MakeWeak(h.location(), |
| 464 reinterpret_cast<void*>(1234), | 467 reinterpret_cast<void*>(1234), |
| 468 NULL, |
| 465 &TestWeakGlobalHandleCallback); | 469 &TestWeakGlobalHandleCallback); |
| 466 | 470 |
| 467 // Scanvenge does not recognize weak reference. | 471 // Scanvenge does not recognize weak reference. |
| 468 HEAP->PerformScavenge(); | 472 HEAP->PerformScavenge(); |
| 469 | 473 |
| 470 CHECK(!WeakPointerCleared); | 474 CHECK(!WeakPointerCleared); |
| 471 | 475 |
| 472 // Mark-compact treats weak reference properly. | 476 // Mark-compact treats weak reference properly. |
| 473 HEAP->CollectGarbage(OLD_POINTER_SPACE); | 477 HEAP->CollectGarbage(OLD_POINTER_SPACE); |
| 474 | 478 |
| (...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1307 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1311 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); |
| 1308 | 1312 |
| 1309 ctx[i]->Exit(); | 1313 ctx[i]->Exit(); |
| 1310 } | 1314 } |
| 1311 | 1315 |
| 1312 // Force compilation cache cleanup. | 1316 // Force compilation cache cleanup. |
| 1313 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1317 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 1314 | 1318 |
| 1315 // Dispose the native contexts one by one. | 1319 // Dispose the native contexts one by one. |
| 1316 for (int i = 0; i < kNumTestContexts; i++) { | 1320 for (int i = 0; i < kNumTestContexts; i++) { |
| 1317 ctx[i].Dispose(); | 1321 ctx[i].Dispose(ctx[i]->GetIsolate()); |
| 1318 ctx[i].Clear(); | 1322 ctx[i].Clear(); |
| 1319 | 1323 |
| 1320 // Scavenge treats these references as strong. | 1324 // Scavenge treats these references as strong. |
| 1321 for (int j = 0; j < 10; j++) { | 1325 for (int j = 0; j < 10; j++) { |
| 1322 HEAP->PerformScavenge(); | 1326 HEAP->PerformScavenge(); |
| 1323 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); | 1327 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); |
| 1324 } | 1328 } |
| 1325 | 1329 |
| 1326 // Mark compact handles the weak references. | 1330 // Mark compact handles the weak references. |
| 1327 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1331 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 ctx2->Global()->Set(v8_str("o"), v); | 1614 ctx2->Global()->Set(v8_str("o"), v); |
| 1611 v8::Local<v8::Value> res = CompileRun( | 1615 v8::Local<v8::Value> res = CompileRun( |
| 1612 "function f() { return o.x; }" | 1616 "function f() { return o.x; }" |
| 1613 "for (var i = 0; i < 10; ++i) f();" | 1617 "for (var i = 0; i < 10; ++i) f();" |
| 1614 "%OptimizeFunctionOnNextCall(f);" | 1618 "%OptimizeFunctionOnNextCall(f);" |
| 1615 "f();"); | 1619 "f();"); |
| 1616 CHECK_EQ(42, res->Int32Value()); | 1620 CHECK_EQ(42, res->Int32Value()); |
| 1617 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1621 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1618 ctx2->Exit(); | 1622 ctx2->Exit(); |
| 1619 ctx1->Exit(); | 1623 ctx1->Exit(); |
| 1620 ctx1.Dispose(); | 1624 ctx1.Dispose(ctx1->GetIsolate()); |
| 1621 v8::V8::ContextDisposedNotification(); | 1625 v8::V8::ContextDisposedNotification(); |
| 1622 } | 1626 } |
| 1623 HEAP->CollectAllAvailableGarbage(); | 1627 HEAP->CollectAllAvailableGarbage(); |
| 1624 CHECK_EQ(2, NumberOfGlobalObjects()); | 1628 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1625 ctx2.Dispose(); | 1629 ctx2.Dispose(ctx2->GetIsolate()); |
| 1626 HEAP->CollectAllAvailableGarbage(); | 1630 HEAP->CollectAllAvailableGarbage(); |
| 1627 CHECK_EQ(0, NumberOfGlobalObjects()); | 1631 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1628 } | 1632 } |
| 1629 | 1633 |
| 1630 | 1634 |
| 1631 // Test that we don't embed functions from foreign contexts into | 1635 // Test that we don't embed functions from foreign contexts into |
| 1632 // optimized code. | 1636 // optimized code. |
| 1633 TEST(LeakNativeContextViaFunction) { | 1637 TEST(LeakNativeContextViaFunction) { |
| 1634 i::FLAG_allow_natives_syntax = true; | 1638 i::FLAG_allow_natives_syntax = true; |
| 1635 v8::HandleScope outer_scope; | 1639 v8::HandleScope outer_scope; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1648 ctx2->Global()->Set(v8_str("o"), v); | 1652 ctx2->Global()->Set(v8_str("o"), v); |
| 1649 v8::Local<v8::Value> res = CompileRun( | 1653 v8::Local<v8::Value> res = CompileRun( |
| 1650 "function f(x) { return x(); }" | 1654 "function f(x) { return x(); }" |
| 1651 "for (var i = 0; i < 10; ++i) f(o);" | 1655 "for (var i = 0; i < 10; ++i) f(o);" |
| 1652 "%OptimizeFunctionOnNextCall(f);" | 1656 "%OptimizeFunctionOnNextCall(f);" |
| 1653 "f(o);"); | 1657 "f(o);"); |
| 1654 CHECK_EQ(42, res->Int32Value()); | 1658 CHECK_EQ(42, res->Int32Value()); |
| 1655 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1659 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1656 ctx2->Exit(); | 1660 ctx2->Exit(); |
| 1657 ctx1->Exit(); | 1661 ctx1->Exit(); |
| 1658 ctx1.Dispose(); | 1662 ctx1.Dispose(ctx1->GetIsolate()); |
| 1659 v8::V8::ContextDisposedNotification(); | 1663 v8::V8::ContextDisposedNotification(); |
| 1660 } | 1664 } |
| 1661 HEAP->CollectAllAvailableGarbage(); | 1665 HEAP->CollectAllAvailableGarbage(); |
| 1662 CHECK_EQ(2, NumberOfGlobalObjects()); | 1666 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1663 ctx2.Dispose(); | 1667 ctx2.Dispose(ctx2->GetIsolate()); |
| 1664 HEAP->CollectAllAvailableGarbage(); | 1668 HEAP->CollectAllAvailableGarbage(); |
| 1665 CHECK_EQ(0, NumberOfGlobalObjects()); | 1669 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1666 } | 1670 } |
| 1667 | 1671 |
| 1668 | 1672 |
| 1669 TEST(LeakNativeContextViaMapKeyed) { | 1673 TEST(LeakNativeContextViaMapKeyed) { |
| 1670 i::FLAG_allow_natives_syntax = true; | 1674 i::FLAG_allow_natives_syntax = true; |
| 1671 v8::HandleScope outer_scope; | 1675 v8::HandleScope outer_scope; |
| 1672 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1676 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1673 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1677 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1684 ctx2->Global()->Set(v8_str("o"), v); | 1688 ctx2->Global()->Set(v8_str("o"), v); |
| 1685 v8::Local<v8::Value> res = CompileRun( | 1689 v8::Local<v8::Value> res = CompileRun( |
| 1686 "function f() { return o[0]; }" | 1690 "function f() { return o[0]; }" |
| 1687 "for (var i = 0; i < 10; ++i) f();" | 1691 "for (var i = 0; i < 10; ++i) f();" |
| 1688 "%OptimizeFunctionOnNextCall(f);" | 1692 "%OptimizeFunctionOnNextCall(f);" |
| 1689 "f();"); | 1693 "f();"); |
| 1690 CHECK_EQ(42, res->Int32Value()); | 1694 CHECK_EQ(42, res->Int32Value()); |
| 1691 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1695 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1692 ctx2->Exit(); | 1696 ctx2->Exit(); |
| 1693 ctx1->Exit(); | 1697 ctx1->Exit(); |
| 1694 ctx1.Dispose(); | 1698 ctx1.Dispose(ctx1->GetIsolate()); |
| 1695 v8::V8::ContextDisposedNotification(); | 1699 v8::V8::ContextDisposedNotification(); |
| 1696 } | 1700 } |
| 1697 HEAP->CollectAllAvailableGarbage(); | 1701 HEAP->CollectAllAvailableGarbage(); |
| 1698 CHECK_EQ(2, NumberOfGlobalObjects()); | 1702 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1699 ctx2.Dispose(); | 1703 ctx2.Dispose(ctx2->GetIsolate()); |
| 1700 HEAP->CollectAllAvailableGarbage(); | 1704 HEAP->CollectAllAvailableGarbage(); |
| 1701 CHECK_EQ(0, NumberOfGlobalObjects()); | 1705 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1702 } | 1706 } |
| 1703 | 1707 |
| 1704 | 1708 |
| 1705 TEST(LeakNativeContextViaMapProto) { | 1709 TEST(LeakNativeContextViaMapProto) { |
| 1706 i::FLAG_allow_natives_syntax = true; | 1710 i::FLAG_allow_natives_syntax = true; |
| 1707 v8::HandleScope outer_scope; | 1711 v8::HandleScope outer_scope; |
| 1708 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1712 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
| 1709 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1713 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1724 " p.__proto__ = o;" | 1728 " p.__proto__ = o;" |
| 1725 " return p.x;" | 1729 " return p.x;" |
| 1726 "}" | 1730 "}" |
| 1727 "for (var i = 0; i < 10; ++i) f();" | 1731 "for (var i = 0; i < 10; ++i) f();" |
| 1728 "%OptimizeFunctionOnNextCall(f);" | 1732 "%OptimizeFunctionOnNextCall(f);" |
| 1729 "f();"); | 1733 "f();"); |
| 1730 CHECK_EQ(42, res->Int32Value()); | 1734 CHECK_EQ(42, res->Int32Value()); |
| 1731 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1735 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1732 ctx2->Exit(); | 1736 ctx2->Exit(); |
| 1733 ctx1->Exit(); | 1737 ctx1->Exit(); |
| 1734 ctx1.Dispose(); | 1738 ctx1.Dispose(ctx1->GetIsolate()); |
| 1735 v8::V8::ContextDisposedNotification(); | 1739 v8::V8::ContextDisposedNotification(); |
| 1736 } | 1740 } |
| 1737 HEAP->CollectAllAvailableGarbage(); | 1741 HEAP->CollectAllAvailableGarbage(); |
| 1738 CHECK_EQ(2, NumberOfGlobalObjects()); | 1742 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1739 ctx2.Dispose(); | 1743 ctx2.Dispose(ctx2->GetIsolate()); |
| 1740 HEAP->CollectAllAvailableGarbage(); | 1744 HEAP->CollectAllAvailableGarbage(); |
| 1741 CHECK_EQ(0, NumberOfGlobalObjects()); | 1745 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1742 } | 1746 } |
| 1743 | 1747 |
| 1744 | 1748 |
| 1745 TEST(InstanceOfStubWriteBarrier) { | 1749 TEST(InstanceOfStubWriteBarrier) { |
| 1746 i::FLAG_allow_natives_syntax = true; | 1750 i::FLAG_allow_natives_syntax = true; |
| 1747 #ifdef VERIFY_HEAP | 1751 #ifdef VERIFY_HEAP |
| 1748 i::FLAG_verify_heap = true; | 1752 i::FLAG_verify_heap = true; |
| 1749 #endif | 1753 #endif |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2825 // Now optimize the function so that it is taken off the candidate list. | 2829 // Now optimize the function so that it is taken off the candidate list. |
| 2826 { | 2830 { |
| 2827 HandleScope inner_scope; | 2831 HandleScope inner_scope; |
| 2828 CompileRun("%OptimizeFunctionOnNextCall(f); f(3);"); | 2832 CompileRun("%OptimizeFunctionOnNextCall(f); f(3);"); |
| 2829 } | 2833 } |
| 2830 | 2834 |
| 2831 // This cycle will bust the heap and subsequent cycles will go ballistic. | 2835 // This cycle will bust the heap and subsequent cycles will go ballistic. |
| 2832 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2836 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 2833 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2837 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
| 2834 } | 2838 } |
| OLD | NEW |