| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "public/platform/WebTraceLocation.h" | 43 #include "public/platform/WebTraceLocation.h" |
| 44 #include "wtf/HashTraits.h" | 44 #include "wtf/HashTraits.h" |
| 45 #include "wtf/LinkedHashSet.h" | 45 #include "wtf/LinkedHashSet.h" |
| 46 | 46 |
| 47 #include <gtest/gtest.h> | 47 #include <gtest/gtest.h> |
| 48 | 48 |
| 49 namespace blink { | 49 namespace blink { |
| 50 | 50 |
| 51 static void preciselyCollectGarbage() | 51 static void preciselyCollectGarbage() |
| 52 { | 52 { |
| 53 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); | 53 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, H
eap::ForcedGC); |
| 54 } | 54 } |
| 55 | 55 |
| 56 static void conservativelyCollectGarbage() | 56 static void conservativelyCollectGarbage() |
| 57 { | 57 { |
| 58 Heap::collectGarbage(ThreadState::HeapPointersOnStack, ThreadState::GCWithSw
eep, Heap::ForcedGC); | 58 Heap::collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithSweep, Hea
p::ForcedGC); |
| 59 } | 59 } |
| 60 | 60 |
| 61 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> { | 61 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> { |
| 62 public: | 62 public: |
| 63 static IntWrapper* create(int x) | 63 static IntWrapper* create(int x) |
| 64 { | 64 { |
| 65 return new IntWrapper(x); | 65 return new IntWrapper(x); |
| 66 } | 66 } |
| 67 | 67 |
| 68 virtual ~IntWrapper() | 68 virtual ~IntWrapper() |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 static void constructDeletedValue(blink::PairWithWeakHandling& slot, bool) {
new (NotNull, &slot) blink::PairWithWeakHandling(HashTableDeletedValue); } | 235 static void constructDeletedValue(blink::PairWithWeakHandling& slot, bool) {
new (NotNull, &slot) blink::PairWithWeakHandling(HashTableDeletedValue); } |
| 236 static bool isDeletedValue(const blink::PairWithWeakHandling& value) { retur
n value.isHashTableDeletedValue(); } | 236 static bool isDeletedValue(const blink::PairWithWeakHandling& value) { retur
n value.isHashTableDeletedValue(); } |
| 237 }; | 237 }; |
| 238 | 238 |
| 239 } | 239 } |
| 240 | 240 |
| 241 namespace blink { | 241 namespace blink { |
| 242 | 242 |
| 243 class TestGCScope { | 243 class TestGCScope { |
| 244 public: | 244 public: |
| 245 explicit TestGCScope(ThreadState::StackState state) | 245 explicit TestGCScope(BlinkGC::StackState state) |
| 246 : m_state(ThreadState::current()) | 246 : m_state(ThreadState::current()) |
| 247 , m_safePointScope(state) | 247 , m_safePointScope(state) |
| 248 , m_parkedAllThreads(false) | 248 , m_parkedAllThreads(false) |
| 249 { | 249 { |
| 250 ASSERT(m_state->checkThread()); | 250 ASSERT(m_state->checkThread()); |
| 251 if (LIKELY(ThreadState::stopThreads())) { | 251 if (LIKELY(ThreadState::stopThreads())) { |
| 252 Heap::preGC(); | 252 Heap::preGC(); |
| 253 m_parkedAllThreads = true; | 253 m_parkedAllThreads = true; |
| 254 } | 254 } |
| 255 } | 255 } |
| 256 | 256 |
| 257 bool allThreadsParked() { return m_parkedAllThreads; } | 257 bool allThreadsParked() { return m_parkedAllThreads; } |
| 258 | 258 |
| 259 ~TestGCScope() | 259 ~TestGCScope() |
| 260 { | 260 { |
| 261 // Only cleanup if we parked all threads in which case the GC happened | 261 // Only cleanup if we parked all threads in which case the GC happened |
| 262 // and we need to resume the other threads. | 262 // and we need to resume the other threads. |
| 263 if (LIKELY(m_parkedAllThreads)) { | 263 if (LIKELY(m_parkedAllThreads)) { |
| 264 Heap::postGC(ThreadState::GCWithSweep); | 264 Heap::postGC(BlinkGC::GCWithSweep); |
| 265 ThreadState::resumeThreads(); | 265 ThreadState::resumeThreads(); |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 private: | 269 private: |
| 270 ThreadState* m_state; | 270 ThreadState* m_state; |
| 271 SafePointScope m_safePointScope; | 271 SafePointScope m_safePointScope; |
| 272 bool m_parkedAllThreads; // False if we fail to park all threads | 272 bool m_parkedAllThreads; // False if we fail to park all threads |
| 273 }; | 273 }; |
| 274 | 274 |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 class ThreadedTesterBase { | 461 class ThreadedTesterBase { |
| 462 protected: | 462 protected: |
| 463 static void test(ThreadedTesterBase* tester) | 463 static void test(ThreadedTesterBase* tester) |
| 464 { | 464 { |
| 465 Vector<OwnPtr<WebThread>, numberOfThreads> m_threads; | 465 Vector<OwnPtr<WebThread>, numberOfThreads> m_threads; |
| 466 for (int i = 0; i < numberOfThreads; i++) { | 466 for (int i = 0; i < numberOfThreads; i++) { |
| 467 m_threads.append(adoptPtr(Platform::current()->createThread("blink g
c testing thread"))); | 467 m_threads.append(adoptPtr(Platform::current()->createThread("blink g
c testing thread"))); |
| 468 m_threads.last()->taskRunner()->postTask(FROM_HERE, new Task(threadS
afeBind(threadFunc, AllowCrossThreadAccess(tester)))); | 468 m_threads.last()->taskRunner()->postTask(FROM_HERE, new Task(threadS
afeBind(threadFunc, AllowCrossThreadAccess(tester)))); |
| 469 } | 469 } |
| 470 while (tester->m_threadsToFinish) { | 470 while (tester->m_threadsToFinish) { |
| 471 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 471 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 472 Platform::current()->yieldCurrentThread(); | 472 Platform::current()->yieldCurrentThread(); |
| 473 } | 473 } |
| 474 delete tester; | 474 delete tester; |
| 475 } | 475 } |
| 476 | 476 |
| 477 virtual void runThread() = 0; | 477 virtual void runThread() = 0; |
| 478 | 478 |
| 479 protected: | 479 protected: |
| 480 static const int numberOfThreads = 10; | 480 static const int numberOfThreads = 10; |
| 481 static const int gcPerThread = 5; | 481 static const int gcPerThread = 5; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 } | 517 } |
| 518 | 518 |
| 519 void runThread() override | 519 void runThread() override |
| 520 { | 520 { |
| 521 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; | 521 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; |
| 522 ThreadState::attach(); | 522 ThreadState::attach(); |
| 523 | 523 |
| 524 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); | 524 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); |
| 525 int gcCount = 0; | 525 int gcCount = 0; |
| 526 while (!done()) { | 526 while (!done()) { |
| 527 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); | 527 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 528 { | 528 { |
| 529 Persistent<IntWrapper> wrapper; | 529 Persistent<IntWrapper> wrapper; |
| 530 | 530 |
| 531 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob
alPersistent(0x0ed0cabb); | 531 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob
alPersistent(0x0ed0cabb); |
| 532 | 532 |
| 533 for (int i = 0; i < numberOfAllocations; i++) { | 533 for (int i = 0; i < numberOfAllocations; i++) { |
| 534 wrapper = IntWrapper::create(0x0bbac0de); | 534 wrapper = IntWrapper::create(0x0bbac0de); |
| 535 if (!(i % 10)) { | 535 if (!(i % 10)) { |
| 536 globalPersistent = createGlobalPersistent(0x0ed0cabb); | 536 globalPersistent = createGlobalPersistent(0x0ed0cabb); |
| 537 } | 537 } |
| 538 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 538 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 539 Platform::current()->yieldCurrentThread(); | 539 Platform::current()->yieldCurrentThread(); |
| 540 } | 540 } |
| 541 | 541 |
| 542 if (gcCount < gcPerThread) { | 542 if (gcCount < gcPerThread) { |
| 543 preciselyCollectGarbage(); | 543 preciselyCollectGarbage(); |
| 544 gcCount++; | 544 gcCount++; |
| 545 atomicIncrement(&m_gcCount); | 545 atomicIncrement(&m_gcCount); |
| 546 } | 546 } |
| 547 | 547 |
| 548 // Taking snapshot shouldn't have any bad side effect. | 548 // Taking snapshot shouldn't have any bad side effect. |
| 549 // TODO(haraken): This snapshot GC causes crashes, so disable | 549 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 550 // it at the moment. Fix the crash and enable it. | 550 // it at the moment. Fix the crash and enable it. |
| 551 // Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, Thre
adState::TakeSnapshot, Heap::ForcedGC); | 551 // Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC:
:TakeSnapshot, Heap::ForcedGC); |
| 552 preciselyCollectGarbage(); | 552 preciselyCollectGarbage(); |
| 553 EXPECT_EQ(wrapper->value(), 0x0bbac0de); | 553 EXPECT_EQ(wrapper->value(), 0x0bbac0de); |
| 554 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb); | 554 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb); |
| 555 } | 555 } |
| 556 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 556 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 557 Platform::current()->yieldCurrentThread(); | 557 Platform::current()->yieldCurrentThread(); |
| 558 } | 558 } |
| 559 | 559 |
| 560 // Intentionally leak the cross-thread persistent so as to verify | 560 // Intentionally leak the cross-thread persistent so as to verify |
| 561 // that later GCs correctly handle cross-thread persistents that | 561 // that later GCs correctly handle cross-thread persistents that |
| 562 // refer to finalized objects after their heaps have been detached | 562 // refer to finalized objects after their heaps have been detached |
| 563 // and freed. | 563 // and freed. |
| 564 EXPECT_TRUE(longLivingPersistent.leakPtr()); | 564 EXPECT_TRUE(longLivingPersistent.leakPtr()); |
| 565 | 565 |
| 566 ThreadState::detach(); | 566 ThreadState::detach(); |
| 567 atomicDecrement(&m_threadsToFinish); | 567 atomicDecrement(&m_threadsToFinish); |
| 568 } | 568 } |
| 569 }; | 569 }; |
| 570 | 570 |
| 571 class ThreadedWeaknessTester : public ThreadedTesterBase { | 571 class ThreadedWeaknessTester : public ThreadedTesterBase { |
| 572 public: | 572 public: |
| 573 static void test() | 573 static void test() |
| 574 { | 574 { |
| 575 ThreadedTesterBase::test(new ThreadedWeaknessTester); | 575 ThreadedTesterBase::test(new ThreadedWeaknessTester); |
| 576 } | 576 } |
| 577 | 577 |
| 578 private: | 578 private: |
| 579 void runThread() override | 579 void runThread() override |
| 580 { | 580 { |
| 581 ThreadState::attach(); | 581 ThreadState::attach(); |
| 582 | 582 |
| 583 int gcCount = 0; | 583 int gcCount = 0; |
| 584 while (!done()) { | 584 while (!done()) { |
| 585 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); | 585 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 586 { | 586 { |
| 587 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we
akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; | 587 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we
akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; |
| 588 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak
Map2; | 588 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak
Map2; |
| 589 | 589 |
| 590 for (int i = 0; i < numberOfAllocations; i++) { | 590 for (int i = 0; i < numberOfAllocations; i++) { |
| 591 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0)
); | 591 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0)
); |
| 592 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0)
); | 592 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0)
); |
| 593 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 593 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 594 Platform::current()->yieldCurrentThread(); | 594 Platform::current()->yieldCurrentThread(); |
| 595 } | 595 } |
| 596 | 596 |
| 597 if (gcCount < gcPerThread) { | 597 if (gcCount < gcPerThread) { |
| 598 preciselyCollectGarbage(); | 598 preciselyCollectGarbage(); |
| 599 gcCount++; | 599 gcCount++; |
| 600 atomicIncrement(&m_gcCount); | 600 atomicIncrement(&m_gcCount); |
| 601 } | 601 } |
| 602 | 602 |
| 603 // Taking snapshot shouldn't have any bad side effect. | 603 // Taking snapshot shouldn't have any bad side effect. |
| 604 // TODO(haraken): This snapshot GC causes crashes, so disable | 604 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 605 // it at the moment. Fix the crash and enable it. | 605 // it at the moment. Fix the crash and enable it. |
| 606 // Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, Thre
adState::TakeSnapshot, Heap::ForcedGC); | 606 // Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC:
:TakeSnapshot, Heap::ForcedGC); |
| 607 preciselyCollectGarbage(); | 607 preciselyCollectGarbage(); |
| 608 EXPECT_TRUE(weakMap->isEmpty()); | 608 EXPECT_TRUE(weakMap->isEmpty()); |
| 609 EXPECT_TRUE(weakMap2.isEmpty()); | 609 EXPECT_TRUE(weakMap2.isEmpty()); |
| 610 } | 610 } |
| 611 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 611 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 612 Platform::current()->yieldCurrentThread(); | 612 Platform::current()->yieldCurrentThread(); |
| 613 } | 613 } |
| 614 ThreadState::detach(); | 614 ThreadState::detach(); |
| 615 atomicDecrement(&m_threadsToFinish); | 615 atomicDecrement(&m_threadsToFinish); |
| 616 } | 616 } |
| 617 }; | 617 }; |
| 618 | 618 |
| 619 class ThreadPersistentHeapTester : public ThreadedTesterBase { | 619 class ThreadPersistentHeapTester : public ThreadedTesterBase { |
| 620 public: | 620 public: |
| 621 static void test() | 621 static void test() |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 // so as to avoid possible warnings about linker duplicates. | 772 // so as to avoid possible warnings about linker duplicates. |
| 773 // Override operator new to allocate IntNode subtype objects onto | 773 // Override operator new to allocate IntNode subtype objects onto |
| 774 // the dedicated heap for blink::Node. | 774 // the dedicated heap for blink::Node. |
| 775 // | 775 // |
| 776 // TODO(haraken): untangling the heap unit tests from Blink would | 776 // TODO(haraken): untangling the heap unit tests from Blink would |
| 777 // simplify and avoid running into this problem - http://crbug.com/425381 | 777 // simplify and avoid running into this problem - http://crbug.com/425381 |
| 778 GC_PLUGIN_IGNORE("crbug.com/443854") | 778 GC_PLUGIN_IGNORE("crbug.com/443854") |
| 779 void* operator new(size_t size) | 779 void* operator new(size_t size) |
| 780 { | 780 { |
| 781 ThreadState* state = ThreadState::current(); | 781 ThreadState* state = ThreadState::current(); |
| 782 return Heap::allocateOnHeapIndex(state, size, ThreadState::NodeHeapIndex
, GCInfoTrait<IntNode>::index()); | 782 return Heap::allocateOnHeapIndex(state, size, BlinkGC::NodeHeapIndex, GC
InfoTrait<IntNode>::index()); |
| 783 } | 783 } |
| 784 | 784 |
| 785 static IntNode* create(int i) | 785 static IntNode* create(int i) |
| 786 { | 786 { |
| 787 return new IntNode(i); | 787 return new IntNode(i); |
| 788 } | 788 } |
| 789 | 789 |
| 790 DEFINE_INLINE_TRACE() { } | 790 DEFINE_INLINE_TRACE() { } |
| 791 | 791 |
| 792 int value() { return m_value; } | 792 int value() { return m_value; } |
| (...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1964 #endif | 1964 #endif |
| 1965 | 1965 |
| 1966 TEST(HeapTest, LazySweepingPages) | 1966 TEST(HeapTest, LazySweepingPages) |
| 1967 { | 1967 { |
| 1968 clearOutOldGarbage(); | 1968 clearOutOldGarbage(); |
| 1969 | 1969 |
| 1970 SimpleFinalizedObject::s_destructorCalls = 0; | 1970 SimpleFinalizedObject::s_destructorCalls = 0; |
| 1971 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); | 1971 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); |
| 1972 for (int i = 0; i < 1000; i++) | 1972 for (int i = 0; i < 1000; i++) |
| 1973 SimpleFinalizedObject::create(); | 1973 SimpleFinalizedObject::create(); |
| 1974 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
outSweep, Heap::ForcedGC); | 1974 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep
, Heap::ForcedGC); |
| 1975 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); | 1975 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); |
| 1976 for (int i = 0; i < 10000; i++) | 1976 for (int i = 0; i < 10000; i++) |
| 1977 SimpleFinalizedObject::create(); | 1977 SimpleFinalizedObject::create(); |
| 1978 EXPECT_EQ(1000, SimpleFinalizedObject::s_destructorCalls); | 1978 EXPECT_EQ(1000, SimpleFinalizedObject::s_destructorCalls); |
| 1979 preciselyCollectGarbage(); | 1979 preciselyCollectGarbage(); |
| 1980 EXPECT_EQ(11000, SimpleFinalizedObject::s_destructorCalls); | 1980 EXPECT_EQ(11000, SimpleFinalizedObject::s_destructorCalls); |
| 1981 } | 1981 } |
| 1982 | 1982 |
| 1983 TEST(HeapTest, LazySweepingLargeObjectPages) | 1983 TEST(HeapTest, LazySweepingLargeObjectPages) |
| 1984 { | 1984 { |
| 1985 clearOutOldGarbage(); | 1985 clearOutOldGarbage(); |
| 1986 | 1986 |
| 1987 // Create free lists that can be reused for IntWrappers created in | 1987 // Create free lists that can be reused for IntWrappers created in |
| 1988 // LargeHeapObject::create(). | 1988 // LargeHeapObject::create(). |
| 1989 Persistent<IntWrapper> p1 = new IntWrapper(1); | 1989 Persistent<IntWrapper> p1 = new IntWrapper(1); |
| 1990 for (int i = 0; i < 100; i++) { | 1990 for (int i = 0; i < 100; i++) { |
| 1991 new IntWrapper(i); | 1991 new IntWrapper(i); |
| 1992 } | 1992 } |
| 1993 Persistent<IntWrapper> p2 = new IntWrapper(2); | 1993 Persistent<IntWrapper> p2 = new IntWrapper(2); |
| 1994 preciselyCollectGarbage(); | 1994 preciselyCollectGarbage(); |
| 1995 preciselyCollectGarbage(); | 1995 preciselyCollectGarbage(); |
| 1996 | 1996 |
| 1997 LargeHeapObject::s_destructorCalls = 0; | 1997 LargeHeapObject::s_destructorCalls = 0; |
| 1998 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); | 1998 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); |
| 1999 for (int i = 0; i < 10; i++) | 1999 for (int i = 0; i < 10; i++) |
| 2000 LargeHeapObject::create(); | 2000 LargeHeapObject::create(); |
| 2001 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
outSweep, Heap::ForcedGC); | 2001 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep
, Heap::ForcedGC); |
| 2002 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); | 2002 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); |
| 2003 for (int i = 0; i < 10; i++) { | 2003 for (int i = 0; i < 10; i++) { |
| 2004 LargeHeapObject::create(); | 2004 LargeHeapObject::create(); |
| 2005 EXPECT_EQ(i + 1, LargeHeapObject::s_destructorCalls); | 2005 EXPECT_EQ(i + 1, LargeHeapObject::s_destructorCalls); |
| 2006 } | 2006 } |
| 2007 LargeHeapObject::create(); | 2007 LargeHeapObject::create(); |
| 2008 LargeHeapObject::create(); | 2008 LargeHeapObject::create(); |
| 2009 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); | 2009 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); |
| 2010 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
outSweep, Heap::ForcedGC); | 2010 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep
, Heap::ForcedGC); |
| 2011 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); | 2011 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); |
| 2012 preciselyCollectGarbage(); | 2012 preciselyCollectGarbage(); |
| 2013 EXPECT_EQ(22, LargeHeapObject::s_destructorCalls); | 2013 EXPECT_EQ(22, LargeHeapObject::s_destructorCalls); |
| 2014 } | 2014 } |
| 2015 | 2015 |
| 2016 class SimpleFinalizedEagerObjectBase : public GarbageCollectedFinalized<SimpleFi
nalizedEagerObjectBase> { | 2016 class SimpleFinalizedEagerObjectBase : public GarbageCollectedFinalized<SimpleFi
nalizedEagerObjectBase> { |
| 2017 public: | 2017 public: |
| 2018 virtual ~SimpleFinalizedEagerObjectBase() { } | 2018 virtual ~SimpleFinalizedEagerObjectBase() { } |
| 2019 DEFINE_INLINE_TRACE() { } | 2019 DEFINE_INLINE_TRACE() { } |
| 2020 | 2020 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 SimpleFinalizedEagerObject::s_destructorCalls = 0; | 2075 SimpleFinalizedEagerObject::s_destructorCalls = 0; |
| 2076 SimpleFinalizedObjectInstanceOfTemplate::s_destructorCalls = 0; | 2076 SimpleFinalizedObjectInstanceOfTemplate::s_destructorCalls = 0; |
| 2077 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); | 2077 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); |
| 2078 EXPECT_EQ(0, SimpleFinalizedEagerObject::s_destructorCalls); | 2078 EXPECT_EQ(0, SimpleFinalizedEagerObject::s_destructorCalls); |
| 2079 for (int i = 0; i < 1000; i++) | 2079 for (int i = 0; i < 1000; i++) |
| 2080 SimpleFinalizedObject::create(); | 2080 SimpleFinalizedObject::create(); |
| 2081 for (int i = 0; i < 100; i++) | 2081 for (int i = 0; i < 100; i++) |
| 2082 SimpleFinalizedEagerObject::create(); | 2082 SimpleFinalizedEagerObject::create(); |
| 2083 for (int i = 0; i < 100; i++) | 2083 for (int i = 0; i < 100; i++) |
| 2084 SimpleFinalizedObjectInstanceOfTemplate::create(); | 2084 SimpleFinalizedObjectInstanceOfTemplate::create(); |
| 2085 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
outSweep, Heap::ForcedGC); | 2085 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep
, Heap::ForcedGC); |
| 2086 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); | 2086 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls); |
| 2087 EXPECT_EQ(100, SimpleFinalizedEagerObject::s_destructorCalls); | 2087 EXPECT_EQ(100, SimpleFinalizedEagerObject::s_destructorCalls); |
| 2088 EXPECT_EQ(100, SimpleFinalizedObjectInstanceOfTemplate::s_destructorCalls); | 2088 EXPECT_EQ(100, SimpleFinalizedObjectInstanceOfTemplate::s_destructorCalls); |
| 2089 } | 2089 } |
| 2090 | 2090 |
| 2091 TEST(HeapTest, Finalization) | 2091 TEST(HeapTest, Finalization) |
| 2092 { | 2092 { |
| 2093 { | 2093 { |
| 2094 HeapTestSubClass* t1 = HeapTestSubClass::create(); | 2094 HeapTestSubClass* t1 = HeapTestSubClass::create(); |
| 2095 HeapTestSubClass* t2 = HeapTestSubClass::create(); | 2095 HeapTestSubClass* t2 = HeapTestSubClass::create(); |
| (...skipping 1696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3792 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; | 3792 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; |
| 3793 | 3793 |
| 3794 // This is a low-level test where we call checkAndMarkPointer. This method | 3794 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3795 // causes the object start bitmap to be computed which requires the heap | 3795 // causes the object start bitmap to be computed which requires the heap |
| 3796 // to be in a consistent state (e.g. the free allocation area must be put | 3796 // to be in a consistent state (e.g. the free allocation area must be put |
| 3797 // into a free list header). However when we call makeConsistentForGC it | 3797 // into a free list header). However when we call makeConsistentForGC it |
| 3798 // also clears out the freelists so we have to rebuild those before trying | 3798 // also clears out the freelists so we have to rebuild those before trying |
| 3799 // to allocate anything again. We do this by forcing a GC after doing the | 3799 // to allocate anything again. We do this by forcing a GC after doing the |
| 3800 // checkAndMarkPointer tests. | 3800 // checkAndMarkPointer tests. |
| 3801 { | 3801 { |
| 3802 TestGCScope scope(ThreadState::HeapPointersOnStack); | 3802 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3803 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. | 3803 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. |
| 3804 Heap::flushHeapDoesNotContainCache(); | 3804 Heap::flushHeapDoesNotContainCache(); |
| 3805 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3805 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3806 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]))
; | 3806 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]))
; |
| 3807 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); | 3807 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); |
| 3808 } | 3808 } |
| 3809 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3809 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
| 3810 visitor.reset(); | 3810 visitor.reset(); |
| 3811 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); | 3811 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); |
| 3812 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)); | 3812 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)); |
| 3813 EXPECT_EQ(2ul, visitor.count()); | 3813 EXPECT_EQ(2ul, visitor.count()); |
| 3814 visitor.reset(); | 3814 visitor.reset(); |
| 3815 } | 3815 } |
| 3816 // This forces a GC without stack scanning which results in the objects | 3816 // This forces a GC without stack scanning which results in the objects |
| 3817 // being collected. This will also rebuild the above mentioned freelists, | 3817 // being collected. This will also rebuild the above mentioned freelists, |
| 3818 // however we don't rely on that below since we don't have any allocations. | 3818 // however we don't rely on that below since we don't have any allocations. |
| 3819 clearOutOldGarbage(); | 3819 clearOutOldGarbage(); |
| 3820 { | 3820 { |
| 3821 TestGCScope scope(ThreadState::HeapPointersOnStack); | 3821 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3822 EXPECT_TRUE(scope.allThreadsParked()); | 3822 EXPECT_TRUE(scope.allThreadsParked()); |
| 3823 Heap::flushHeapDoesNotContainCache(); | 3823 Heap::flushHeapDoesNotContainCache(); |
| 3824 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3824 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3825 // We would like to assert that checkAndMarkPointer returned false | 3825 // We would like to assert that checkAndMarkPointer returned false |
| 3826 // here because the pointers no longer point into a valid object | 3826 // here because the pointers no longer point into a valid object |
| 3827 // (it's been freed by the GCs. But checkAndMarkPointer will return | 3827 // (it's been freed by the GCs. But checkAndMarkPointer will return |
| 3828 // true for any pointer that points into a heap page, regardless of | 3828 // true for any pointer that points into a heap page, regardless of |
| 3829 // whether it points at a valid object (this ensures the | 3829 // whether it points at a valid object (this ensures the |
| 3830 // correctness of the page-based on-heap address caches), so we | 3830 // correctness of the page-based on-heap address caches), so we |
| 3831 // can't make that assert. | 3831 // can't make that assert. |
| (...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4638 OwnPtr<WebThread> sleepingThread = adoptPtr(Platform::current()->createT
hread("SleepingThread")); | 4638 OwnPtr<WebThread> sleepingThread = adoptPtr(Platform::current()->createT
hread("SleepingThread")); |
| 4639 sleepingThread->taskRunner()->postTask(FROM_HERE, new Task(threadSafeBin
d(sleeperMainFunc))); | 4639 sleepingThread->taskRunner()->postTask(FROM_HERE, new Task(threadSafeBin
d(sleeperMainFunc))); |
| 4640 | 4640 |
| 4641 // Wait for the sleeper to run. | 4641 // Wait for the sleeper to run. |
| 4642 while (!s_sleeperRunning) { | 4642 while (!s_sleeperRunning) { |
| 4643 Platform::current()->yieldCurrentThread(); | 4643 Platform::current()->yieldCurrentThread(); |
| 4644 } | 4644 } |
| 4645 | 4645 |
| 4646 { | 4646 { |
| 4647 // Expect the first attempt to park the sleeping thread to fail | 4647 // Expect the first attempt to park the sleeping thread to fail |
| 4648 TestGCScope scope(ThreadState::NoHeapPointersOnStack); | 4648 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); |
| 4649 EXPECT_FALSE(scope.allThreadsParked()); | 4649 EXPECT_FALSE(scope.allThreadsParked()); |
| 4650 } | 4650 } |
| 4651 | 4651 |
| 4652 s_sleeperDone = true; | 4652 s_sleeperDone = true; |
| 4653 | 4653 |
| 4654 // Wait for the sleeper to finish. | 4654 // Wait for the sleeper to finish. |
| 4655 while (s_sleeperRunning) { | 4655 while (s_sleeperRunning) { |
| 4656 // We enter the safepoint here since the sleeper thread will detach | 4656 // We enter the safepoint here since the sleeper thread will detach |
| 4657 // causing it to GC. | 4657 // causing it to GC. |
| 4658 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); | 4658 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 4659 Platform::current()->yieldCurrentThread(); | 4659 Platform::current()->yieldCurrentThread(); |
| 4660 } | 4660 } |
| 4661 | 4661 |
| 4662 { | 4662 { |
| 4663 // Since the sleeper thread has detached this is the only thread. | 4663 // Since the sleeper thread has detached this is the only thread. |
| 4664 TestGCScope scope(ThreadState::NoHeapPointersOnStack); | 4664 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); |
| 4665 EXPECT_TRUE(scope.allThreadsParked()); | 4665 EXPECT_TRUE(scope.allThreadsParked()); |
| 4666 } | 4666 } |
| 4667 } | 4667 } |
| 4668 | 4668 |
| 4669 private: | 4669 private: |
| 4670 static void sleeperMainFunc() | 4670 static void sleeperMainFunc() |
| 4671 { | 4671 { |
| 4672 ThreadState::attach(); | 4672 ThreadState::attach(); |
| 4673 s_sleeperRunning = true; | 4673 s_sleeperRunning = true; |
| 4674 | 4674 |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5368 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); | 5368 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); |
| 5369 } | 5369 } |
| 5370 | 5370 |
| 5371 // Signal the main thread that the worker is done with its allocation. | 5371 // Signal the main thread that the worker is done with its allocation. |
| 5372 wakeMainThread(); | 5372 wakeMainThread(); |
| 5373 | 5373 |
| 5374 { | 5374 { |
| 5375 // Wait for the main thread to do two GCs without sweeping this thre
ad | 5375 // Wait for the main thread to do two GCs without sweeping this thre
ad |
| 5376 // heap. The worker waits within a safepoint, but there is no sweepi
ng | 5376 // heap. The worker waits within a safepoint, but there is no sweepi
ng |
| 5377 // until leaving the safepoint scope. | 5377 // until leaving the safepoint scope. |
| 5378 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 5378 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 5379 parkWorkerThread(); | 5379 parkWorkerThread(); |
| 5380 } | 5380 } |
| 5381 | 5381 |
| 5382 // Wake up the main thread when done sweeping. | 5382 // Wake up the main thread when done sweeping. |
| 5383 wakeMainThread(); | 5383 wakeMainThread(); |
| 5384 | 5384 |
| 5385 // Wait with detach until the main thread says so. This is not strictly | 5385 // Wait with detach until the main thread says so. This is not strictly |
| 5386 // necessary, but it means the worker thread will not do its thread loca
l | 5386 // necessary, but it means the worker thread will not do its thread loca
l |
| 5387 // GCs just yet, making it easier to reason about that no new GC has occ
urred | 5387 // GCs just yet, making it easier to reason about that no new GC has occ
urred |
| 5388 // and the above sweep was the one finalizing the worker object. | 5388 // and the above sweep was the one finalizing the worker object. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5424 preciselyCollectGarbage(); | 5424 preciselyCollectGarbage(); |
| 5425 preciselyCollectGarbage(); | 5425 preciselyCollectGarbage(); |
| 5426 | 5426 |
| 5427 // Wake up the worker thread so it can continue. It will sweep | 5427 // Wake up the worker thread so it can continue. It will sweep |
| 5428 // and perform another GC where the backing store of its | 5428 // and perform another GC where the backing store of its |
| 5429 // collection should be strongified. | 5429 // collection should be strongified. |
| 5430 wakeWorkerThread(); | 5430 wakeWorkerThread(); |
| 5431 | 5431 |
| 5432 // Wait for the worker thread to sweep its heaps before checking. | 5432 // Wait for the worker thread to sweep its heaps before checking. |
| 5433 { | 5433 { |
| 5434 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 5434 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 5435 parkMainThread(); | 5435 parkMainThread(); |
| 5436 } | 5436 } |
| 5437 } | 5437 } |
| 5438 | 5438 |
| 5439 private: | 5439 private: |
| 5440 | 5440 |
| 5441 using WeakCollectionType = HeapHashMap<WeakMember<IntWrapper>, Member<IntWra
pper>>; | 5441 using WeakCollectionType = HeapHashMap<WeakMember<IntWrapper>, Member<IntWra
pper>>; |
| 5442 | 5442 |
| 5443 static WeakCollectionType* allocateCollection() | 5443 static WeakCollectionType* allocateCollection() |
| 5444 { | 5444 { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5462 // Signal the main thread that the worker is done with its allocation. | 5462 // Signal the main thread that the worker is done with its allocation. |
| 5463 wakeMainThread(); | 5463 wakeMainThread(); |
| 5464 | 5464 |
| 5465 { | 5465 { |
| 5466 // Wait for the main thread to do two GCs without sweeping | 5466 // Wait for the main thread to do two GCs without sweeping |
| 5467 // this thread heap. The worker waits within a safepoint, | 5467 // this thread heap. The worker waits within a safepoint, |
| 5468 // but there is no sweeping until leaving the safepoint | 5468 // but there is no sweeping until leaving the safepoint |
| 5469 // scope. If the weak collection backing is marked dead | 5469 // scope. If the weak collection backing is marked dead |
| 5470 // because of this we will not get strongification in the | 5470 // because of this we will not get strongification in the |
| 5471 // GC we force when we continue. | 5471 // GC we force when we continue. |
| 5472 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 5472 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 5473 parkWorkerThread(); | 5473 parkWorkerThread(); |
| 5474 } | 5474 } |
| 5475 | 5475 |
| 5476 return weakCollection; | 5476 return weakCollection; |
| 5477 } | 5477 } |
| 5478 | 5478 |
| 5479 static void workerThreadMain() | 5479 static void workerThreadMain() |
| 5480 { | 5480 { |
| 5481 MutexLocker locker(workerThreadMutex()); | 5481 MutexLocker locker(workerThreadMutex()); |
| 5482 | 5482 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5653 // Wait for the main thread to get the global lock to ensure it has | 5653 // Wait for the main thread to get the global lock to ensure it has |
| 5654 // it before the worker tries to acquire it. We want the worker to | 5654 // it before the worker tries to acquire it. We want the worker to |
| 5655 // block in the SafePointAwareMutexLocker until the main thread | 5655 // block in the SafePointAwareMutexLocker until the main thread |
| 5656 // has done a GC. The GC will not mark the "dlo" object since the worker | 5656 // has done a GC. The GC will not mark the "dlo" object since the worker |
| 5657 // is entering the safepoint with NoHeapPointersOnStack. When the worker | 5657 // is entering the safepoint with NoHeapPointersOnStack. When the worker |
| 5658 // subsequently gets the global lock and leaves the safepoint it will | 5658 // subsequently gets the global lock and leaves the safepoint it will |
| 5659 // sweep its heap and finalize "dlo". The destructor of "dlo" will try | 5659 // sweep its heap and finalize "dlo". The destructor of "dlo" will try |
| 5660 // to acquire the same global lock that the thread just got and deadlock | 5660 // to acquire the same global lock that the thread just got and deadlock |
| 5661 // unless the global lock is recursive. | 5661 // unless the global lock is recursive. |
| 5662 parkWorkerThread(); | 5662 parkWorkerThread(); |
| 5663 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState:
:NoHeapPointersOnStack); | 5663 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), BlinkGC::NoH
eapPointersOnStack); |
| 5664 | 5664 |
| 5665 // We won't get here unless the lock is recursive since the sweep done | 5665 // We won't get here unless the lock is recursive since the sweep done |
| 5666 // in the constructor of SafePointAwareMutexLocker after | 5666 // in the constructor of SafePointAwareMutexLocker after |
| 5667 // getting the lock will not complete given the "dlo" destructor is | 5667 // getting the lock will not complete given the "dlo" destructor is |
| 5668 // waiting to get the same lock. | 5668 // waiting to get the same lock. |
| 5669 // Tell the main thread the worker has done its sweep. | 5669 // Tell the main thread the worker has done its sweep. |
| 5670 wakeMainThread(); | 5670 wakeMainThread(); |
| 5671 | 5671 |
| 5672 ThreadState::detach(); | 5672 ThreadState::detach(); |
| 5673 } | 5673 } |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6374 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject**
object) | 6374 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject**
object) |
| 6375 { | 6375 { |
| 6376 // Step 2: Create an object and store the pointer. | 6376 // Step 2: Create an object and store the pointer. |
| 6377 MutexLocker locker(workerThreadMutex()); | 6377 MutexLocker locker(workerThreadMutex()); |
| 6378 ThreadState::attach(); | 6378 ThreadState::attach(); |
| 6379 *object = DestructorLockingObject::create(); | 6379 *object = DestructorLockingObject::create(); |
| 6380 wakeMainThread(); | 6380 wakeMainThread(); |
| 6381 parkWorkerThread(); | 6381 parkWorkerThread(); |
| 6382 | 6382 |
| 6383 // Step 4: Run a GC. | 6383 // Step 4: Run a GC. |
| 6384 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); | 6384 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, H
eap::ForcedGC); |
| 6385 wakeMainThread(); | 6385 wakeMainThread(); |
| 6386 parkWorkerThread(); | 6386 parkWorkerThread(); |
| 6387 | 6387 |
| 6388 // Step 6: Finish. | 6388 // Step 6: Finish. |
| 6389 ThreadState::detach(); | 6389 ThreadState::detach(); |
| 6390 wakeMainThread(); | 6390 wakeMainThread(); |
| 6391 } | 6391 } |
| 6392 | 6392 |
| 6393 } // anonymous namespace | 6393 } // anonymous namespace |
| 6394 | 6394 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 6411 ASSERT_TRUE(object); | 6411 ASSERT_TRUE(object); |
| 6412 CrossThreadWeakPersistent<DestructorLockingObject> crossThreadWeakPersistent
(object); | 6412 CrossThreadWeakPersistent<DestructorLockingObject> crossThreadWeakPersistent
(object); |
| 6413 object = nullptr; | 6413 object = nullptr; |
| 6414 { | 6414 { |
| 6415 SafePointAwareMutexLocker recursiveMutexLocker(recursiveMutex()); | 6415 SafePointAwareMutexLocker recursiveMutexLocker(recursiveMutex()); |
| 6416 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls); | 6416 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls); |
| 6417 } | 6417 } |
| 6418 | 6418 |
| 6419 { | 6419 { |
| 6420 // Pretend we have no pointers on stack during the step 4. | 6420 // Pretend we have no pointers on stack during the step 4. |
| 6421 SafePointScope scope(ThreadState::NoHeapPointersOnStack); | 6421 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 6422 wakeWorkerThread(); | 6422 wakeWorkerThread(); |
| 6423 parkMainThread(); | 6423 parkMainThread(); |
| 6424 } | 6424 } |
| 6425 | 6425 |
| 6426 // Step 5: Make sure the weak persistent is cleared. | 6426 // Step 5: Make sure the weak persistent is cleared. |
| 6427 EXPECT_FALSE(crossThreadWeakPersistent.get()); | 6427 EXPECT_FALSE(crossThreadWeakPersistent.get()); |
| 6428 { | 6428 { |
| 6429 SafePointAwareMutexLocker recursiveMutexLocker(recursiveMutex()); | 6429 SafePointAwareMutexLocker recursiveMutexLocker(recursiveMutex()); |
| 6430 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); | 6430 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); |
| 6431 } | 6431 } |
| 6432 | 6432 |
| 6433 wakeWorkerThread(); | 6433 wakeWorkerThread(); |
| 6434 parkMainThread(); | 6434 parkMainThread(); |
| 6435 } | 6435 } |
| 6436 | 6436 |
| 6437 } // namespace blink | 6437 } // namespace blink |
| OLD | NEW |