Chromium Code Reviews| 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 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1690 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 1690 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 1691 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls); | 1691 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls); |
| 1692 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls); | 1692 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls); |
| 1693 } | 1693 } |
| 1694 | 1694 |
| 1695 TEST(HeapTest, TypedHeapSanity) | 1695 TEST(HeapTest, TypedHeapSanity) |
| 1696 { | 1696 { |
| 1697 // We use TraceCounter for allocating an object on the general heap. | 1697 // We use TraceCounter for allocating an object on the general heap. |
| 1698 Persistent<TraceCounter> generalHeapObject = TraceCounter::create(); | 1698 Persistent<TraceCounter> generalHeapObject = TraceCounter::create(); |
| 1699 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create( ); | 1699 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create( ); |
| 1700 EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get( ))), | 1700 EXPECT_NE(pageHeaderFromObject(generalHeapObject.get()), |
| 1701 pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get()))); | 1701 pageHeaderFromObject(typedHeapObject.get())); |
| 1702 } | 1702 } |
| 1703 | 1703 |
| 1704 TEST(HeapTest, NoAllocation) | 1704 TEST(HeapTest, NoAllocation) |
| 1705 { | 1705 { |
| 1706 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed()); | 1706 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed()); |
| 1707 { | 1707 { |
| 1708 // Disallow allocation | 1708 // Disallow allocation |
| 1709 NoAllocationScope<AnyThread> noAllocationScope; | 1709 NoAllocationScope<AnyThread> noAllocationScope; |
| 1710 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed()); | 1710 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed()); |
| 1711 } | 1711 } |
| (...skipping 1710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3422 { | 3422 { |
| 3423 HeapStats initialHeapSize; | 3423 HeapStats initialHeapSize; |
| 3424 IntWrapper::s_destructorCalls = 0; | 3424 IntWrapper::s_destructorCalls = 0; |
| 3425 | 3425 |
| 3426 typedef HeapVector<Member<IntWrapper> > Vec; | 3426 typedef HeapVector<Member<IntWrapper> > Vec; |
| 3427 typedef PersistentHeapVector<Member<IntWrapper> > PVec; | 3427 typedef PersistentHeapVector<Member<IntWrapper> > PVec; |
| 3428 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; | 3428 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; |
| 3429 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet; | 3429 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet; |
| 3430 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet; | 3430 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet; |
| 3431 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap; | 3431 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap; |
| 3432 typedef PersistentHeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > W eakPMap; | |
| 3432 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque; | 3433 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque; |
| 3433 | 3434 |
| 3434 clearOutOldGarbage(&initialHeapSize); | 3435 clearOutOldGarbage(&initialHeapSize); |
| 3435 { | 3436 { |
| 3436 PVec pVec; | 3437 PVec pVec; |
| 3437 PDeque pDeque; | 3438 PDeque pDeque; |
| 3438 PSet pSet; | 3439 PSet pSet; |
| 3439 PListSet pListSet; | 3440 PListSet pListSet; |
| 3440 PLinkedSet pLinkedSet; | 3441 PLinkedSet pLinkedSet; |
| 3441 PMap pMap; | 3442 PMap pMap; |
| 3443 WeakPMap wpMap; | |
| 3442 | 3444 |
| 3443 IntWrapper* one(IntWrapper::create(1)); | 3445 IntWrapper* one(IntWrapper::create(1)); |
| 3444 IntWrapper* two(IntWrapper::create(2)); | 3446 IntWrapper* two(IntWrapper::create(2)); |
| 3445 IntWrapper* three(IntWrapper::create(3)); | 3447 IntWrapper* three(IntWrapper::create(3)); |
| 3446 IntWrapper* four(IntWrapper::create(4)); | 3448 IntWrapper* four(IntWrapper::create(4)); |
| 3447 IntWrapper* five(IntWrapper::create(5)); | 3449 IntWrapper* five(IntWrapper::create(5)); |
| 3448 IntWrapper* six(IntWrapper::create(6)); | 3450 IntWrapper* six(IntWrapper::create(6)); |
| 3449 IntWrapper* seven(IntWrapper::create(7)); | 3451 IntWrapper* seven(IntWrapper::create(7)); |
| 3450 IntWrapper* eight(IntWrapper::create(8)); | 3452 IntWrapper* eight(IntWrapper::create(8)); |
| 3451 IntWrapper* nine(IntWrapper::create(9)); | 3453 IntWrapper* nine(IntWrapper::create(9)); |
| 3454 Persistent<IntWrapper> ten(IntWrapper::create(10)); | |
| 3455 IntWrapper* eleven(IntWrapper::create(11)); | |
| 3452 | 3456 |
| 3453 pVec.append(one); | 3457 pVec.append(one); |
| 3454 pVec.append(two); | 3458 pVec.append(two); |
| 3455 | 3459 |
| 3456 pDeque.append(seven); | 3460 pDeque.append(seven); |
| 3457 pDeque.append(two); | 3461 pDeque.append(two); |
| 3458 | 3462 |
| 3459 Vec* vec = new Vec(); | 3463 Vec* vec = new Vec(); |
| 3460 vec->swap(pVec); | 3464 vec->swap(pVec); |
| 3461 | 3465 |
| 3462 pVec.append(two); | 3466 pVec.append(two); |
| 3463 pVec.append(three); | 3467 pVec.append(three); |
| 3464 | 3468 |
| 3465 pSet.add(four); | 3469 pSet.add(four); |
| 3466 pListSet.add(eight); | 3470 pListSet.add(eight); |
| 3467 pLinkedSet.add(nine); | 3471 pLinkedSet.add(nine); |
| 3468 pMap.add(five, six); | 3472 pMap.add(five, six); |
| 3473 wpMap.add(ten, eleven); | |
| 3469 | 3474 |
| 3470 // Collect |vec| and |one|. | 3475 // Collect |vec| and |one|. |
| 3471 vec = 0; | 3476 vec = 0; |
| 3472 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3477 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 3473 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | 3478 EXPECT_EQ(1, IntWrapper::s_destructorCalls); |
| 3474 | 3479 |
| 3475 EXPECT_EQ(2u, pVec.size()); | 3480 EXPECT_EQ(2u, pVec.size()); |
| 3476 EXPECT_EQ(two, pVec.at(0)); | 3481 EXPECT_EQ(two, pVec.at(0)); |
| 3477 EXPECT_EQ(three, pVec.at(1)); | 3482 EXPECT_EQ(three, pVec.at(1)); |
| 3478 | 3483 |
| 3479 EXPECT_EQ(2u, pDeque.size()); | 3484 EXPECT_EQ(2u, pDeque.size()); |
| 3480 EXPECT_EQ(seven, pDeque.first()); | 3485 EXPECT_EQ(seven, pDeque.first()); |
| 3481 EXPECT_EQ(seven, pDeque.takeFirst()); | 3486 EXPECT_EQ(seven, pDeque.takeFirst()); |
| 3482 EXPECT_EQ(two, pDeque.first()); | 3487 EXPECT_EQ(two, pDeque.first()); |
| 3483 | 3488 |
| 3484 EXPECT_EQ(1u, pDeque.size()); | 3489 EXPECT_EQ(1u, pDeque.size()); |
| 3485 | 3490 |
| 3486 EXPECT_EQ(1u, pSet.size()); | 3491 EXPECT_EQ(1u, pSet.size()); |
| 3487 EXPECT_TRUE(pSet.contains(four)); | 3492 EXPECT_TRUE(pSet.contains(four)); |
| 3488 | 3493 |
| 3489 EXPECT_EQ(1u, pListSet.size()); | 3494 EXPECT_EQ(1u, pListSet.size()); |
| 3490 EXPECT_TRUE(pListSet.contains(eight)); | 3495 EXPECT_TRUE(pListSet.contains(eight)); |
| 3491 | 3496 |
| 3492 EXPECT_EQ(1u, pLinkedSet.size()); | 3497 EXPECT_EQ(1u, pLinkedSet.size()); |
| 3493 EXPECT_TRUE(pLinkedSet.contains(nine)); | 3498 EXPECT_TRUE(pLinkedSet.contains(nine)); |
| 3494 | 3499 |
| 3495 EXPECT_EQ(1u, pMap.size()); | 3500 EXPECT_EQ(1u, pMap.size()); |
| 3496 EXPECT_EQ(six, pMap.get(five)); | 3501 EXPECT_EQ(six, pMap.get(five)); |
| 3502 | |
| 3503 EXPECT_EQ(1u, wpMap.size()); | |
| 3504 EXPECT_EQ(eleven, wpMap.get(ten)); | |
| 3505 ten.clear(); | |
| 3506 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 3507 EXPECT_EQ(0u, wpMap.size()); | |
| 3497 } | 3508 } |
| 3498 | 3509 |
| 3499 // Collect previous roots. | 3510 // Collect previous roots. |
| 3500 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3511 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 3501 EXPECT_EQ(9, IntWrapper::s_destructorCalls); | 3512 EXPECT_EQ(11, IntWrapper::s_destructorCalls); |
| 3502 } | 3513 } |
| 3503 | 3514 |
| 3504 TEST(HeapTest, CollectionNesting) | 3515 TEST(HeapTest, CollectionNesting) |
| 3505 { | 3516 { |
| 3506 HeapStats initialStats; | 3517 HeapStats initialStats; |
| 3507 clearOutOldGarbage(&initialStats); | 3518 clearOutOldGarbage(&initialStats); |
| 3508 int* key = &IntWrapper::s_destructorCalls; | 3519 int* key = &IntWrapper::s_destructorCalls; |
| 3509 IntWrapper::s_destructorCalls = 0; | 3520 IntWrapper::s_destructorCalls = 0; |
| 3510 typedef HeapVector<Member<IntWrapper> > IntVector; | 3521 typedef HeapVector<Member<IntWrapper> > IntVector; |
| 3511 typedef HeapDeque<Member<IntWrapper> > IntDeque; | 3522 typedef HeapDeque<Member<IntWrapper> > IntDeque; |
| (...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4576 EXPECT_EQ(lifeObject, map->get(lifeObject)->link()); | 4587 EXPECT_EQ(lifeObject, map->get(lifeObject)->link()); |
| 4577 deadObject.clear(); // Now it can live up to its name. | 4588 deadObject.clear(); // Now it can live up to its name. |
| 4578 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 4589 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 4579 EXPECT_EQ(1u, map->size()); | 4590 EXPECT_EQ(1u, map->size()); |
| 4580 EXPECT_EQ(lifeObject, map->get(lifeObject)->link()); | 4591 EXPECT_EQ(lifeObject, map->get(lifeObject)->link()); |
| 4581 lifeObject.clear(); // Despite its name. | 4592 lifeObject.clear(); // Despite its name. |
| 4582 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 4593 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 4583 EXPECT_EQ(0u, map->size()); | 4594 EXPECT_EQ(0u, map->size()); |
| 4584 } | 4595 } |
| 4585 | 4596 |
| 4597 class CrossThreadObject : public GarbageCollectedFinalized<CrossThreadObject> { | |
| 4598 public: | |
| 4599 static CrossThreadObject* create(IntWrapper* workerObjectPointer) | |
| 4600 { | |
| 4601 return new CrossThreadObject(workerObjectPointer); | |
| 4602 } | |
| 4603 | |
| 4604 virtual ~CrossThreadObject() | |
| 4605 { | |
| 4606 ++s_destructorCalls; | |
| 4607 } | |
| 4608 | |
| 4609 static int s_destructorCalls; | |
| 4610 void trace(Visitor* visitor) { visitor->trace(m_workerObject); } | |
| 4611 | |
| 4612 private: | |
| 4613 CrossThreadObject(IntWrapper* workerObjectPointer) : m_workerObject(workerOb jectPointer) { } | |
| 4614 | |
| 4615 private: | |
| 4616 Member<IntWrapper> m_workerObject; | |
| 4617 }; | |
| 4618 | |
| 4619 int CrossThreadObject::s_destructorCalls = 0; | |
| 4620 | |
| 4621 class CrossThreadPointerTester { | |
| 4622 public: | |
| 4623 static void test() | |
| 4624 { | |
| 4625 CrossThreadObject::s_destructorCalls = 0; | |
| 4626 IntWrapper::s_destructorCalls = 0; | |
| 4627 createThread(&workerThreadMain, 0, "Worker Thread"); | |
| 4628 | |
| 4629 // Wait for the worker to run. | |
| 4630 while (!s_workerRunning) { | |
| 4631 yield(); | |
| 4632 } | |
| 4633 | |
| 4634 uintptr_t stackPtrValue = 0; | |
| 4635 { | |
| 4636 // Create an object with a pointer to the other heap's IntWrapper. | |
| 4637 Persistent<CrossThreadObject> cto = CrossThreadObject::create(const_ cast<IntWrapper*>(s_workerObjectPointer)); | |
| 4638 s_workerObjectPointer = 0; | |
| 4639 | |
| 4640 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 4641 | |
| 4642 // Nothing should have been collected/destructed. | |
| 4643 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls); | |
| 4644 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | |
| 4645 | |
| 4646 // Put cto into a stack value. This is used to check that a conserva tive | |
| 4647 // GC succeeds even though we are tracing the other thread heap afte r | |
| 4648 // shutting it down. | |
| 4649 stackPtrValue = reinterpret_cast<uintptr_t>(cto.get()); | |
| 4650 } | |
| 4651 | |
| 4652 // At this point it is "programatically" okay to shut down the worker th read | |
| 4653 // since the cto object should be dead. However out stackPtrValue will c ause a | |
| 4654 // trace of the object when doing a conservative GC. | |
| 4655 // The worker thread's thread local GC's should just add the worker thre ad's | |
| 4656 // pages to the heap after finalizing IntWrapper. | |
| 4657 s_workerFinish = true; | |
| 4658 | |
| 4659 // Wait for the worker to finish. | |
| 4660 while (s_workerRunning) { | |
| 4661 // No need to enter a safepoint since the GC's done by the worker at detach | |
| 4662 // are thread local and doesn't require other threads to enter a saf epoint. | |
| 4663 yield(); | |
| 4664 } | |
| 4665 // After the worker thread has detached it should have finalized the | |
| 4666 // IntWrapper object on its heaps. Since there has been no global GC | |
| 4667 // the cto object should not have been finalized. | |
| 4668 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls); | |
| 4669 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | |
| 4670 | |
| 4671 // Now do a conservative GC. The stackPtrValue should keep cto alive | |
| 4672 // and will also cause the orphaned page of the other thread to be | |
| 4673 // traced. At this point cto should still not be finalized. | |
| 4674 Heap::collectGarbage(ThreadState::HeapPointersOnStack); | |
| 4675 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls); | |
| 4676 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | |
| 4677 | |
| 4678 // Set stackPtrValue to zero and see the cto object being collected in t he | |
| 4679 // conservative GC. | |
| 4680 stackPtrValue = 0; | |
| 4681 Heap::collectGarbage(ThreadState::HeapPointersOnStack); | |
| 4682 EXPECT_EQ(1, CrossThreadObject::s_destructorCalls); | |
| 4683 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | |
| 4684 } | |
| 4685 | |
| 4686 private: | |
| 4687 static void workerThreadMain(void* data) | |
| 4688 { | |
| 4689 ThreadState::attach(); | |
| 4690 | |
| 4691 { | |
| 4692 // Create a worker object that is only kept alive by a cross thread | |
| 4693 // pointer (from CrossThreadObject). | |
| 4694 IntWrapper* workerObject = IntWrapper::create(42); | |
| 4695 s_workerObjectPointer = workerObject; | |
| 4696 s_workerRunning = true; | |
| 4697 } | |
| 4698 | |
| 4699 // Wait for main thread to signal the worker to finish. | |
| 4700 while (!s_workerFinish) { | |
| 4701 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack ); | |
| 4702 yield(); | |
| 4703 } | |
| 4704 | |
| 4705 ThreadState::detach(); | |
| 4706 s_workerRunning = false; | |
| 4707 } | |
| 4708 | |
| 4709 static volatile IntWrapper* s_workerObjectPointer; | |
| 4710 static volatile bool s_workerRunning; | |
| 4711 static volatile bool s_workerFinish; | |
| 4712 }; | |
| 4713 | |
| 4714 volatile bool CrossThreadPointerTester::s_workerRunning = false; | |
| 4715 volatile bool CrossThreadPointerTester::s_workerFinish = false; | |
| 4716 volatile IntWrapper* CrossThreadPointerTester::s_workerObjectPointer = 0; | |
| 4717 | |
| 4718 TEST(HeapTest, CrossThreadPointerToOrphanedPage) | |
| 4719 { | |
| 4720 CrossThreadPointerTester::test(); | |
| 4721 } | |
| 4722 | |
| 4723 class DeadBitTester { | |
| 4724 public: | |
| 4725 static void test() | |
| 4726 { | |
| 4727 IntWrapper::s_destructorCalls = 0; | |
| 4728 createThread(&workerThreadMain, 0, "Worker Thread"); | |
| 4729 | |
| 4730 // Wait for the worker to run. | |
| 4731 while (!s_workerRunning) { | |
| 4732 yield(); | |
| 4733 } | |
| 4734 | |
| 4735 // Do a GC. This will not find the worker threads object since it | |
| 4736 // is not referred from any of the threads. Even a conservative | |
| 4737 // GC will not find it. | |
| 4738 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 4739 | |
| 4740 // Since the worker thread is not sweeping the worker object should | |
| 4741 // not have been finalized. | |
| 4742 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | |
| 4743 | |
| 4744 // Put the worker thread's object address on the stack and do a | |
| 4745 // conservative GC. This should find the worker object, but since | |
| 4746 // it was dead in the previous GC it should not be traced in this | |
| 4747 // GC. | |
| 4748 uintptr_t stackPtrValue = s_workerObjectPointer; | |
| 4749 s_workerObjectPointer = 0; | |
| 4750 ASSERT_UNUSED(stackPtrValue, stackPtrValue); | |
| 4751 Heap::collectGarbage(ThreadState::HeapPointersOnStack); | |
| 4752 | |
| 4753 // Since the worker thread is not sweeping the worker object should | |
| 4754 // not have been finalized. | |
| 4755 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | |
| 4756 | |
| 4757 // Tell the worker thread to finish its busy loop, but not detach. | |
| 4758 // This means there is no further GC, however the worker thread gets | |
| 4759 // to sweep so the worker object should now be finalized since the | |
| 4760 // above conservative GC should not have traced the object that was | |
| 4761 // found dead in the first GC. | |
| 4762 s_workerContinue = true; | |
| 4763 | |
| 4764 // Wait for the worker to sweep. | |
| 4765 while (!s_workerDidSweep) { | |
| 4766 // No need to enter a safepoint since the worker thread is just swee ping | |
| 4767 // its own heap. | |
| 4768 yield(); | |
| 4769 } | |
| 4770 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | |
| 4771 | |
| 4772 // Tell the worker to shut down. | |
| 4773 s_workerFinish = true; | |
| 4774 } | |
| 4775 | |
| 4776 private: | |
| 4777 static void workerThreadMain(void* data) | |
| 4778 { | |
| 4779 ThreadState::attach(); | |
| 4780 | |
| 4781 { | |
| 4782 // Create a worker object that is not kept alive except the | |
| 4783 // main thread will keep it as an integer value on its stack. | |
| 4784 IntWrapper* workerObject = IntWrapper::create(42); | |
| 4785 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); | |
| 4786 s_workerRunning = true; | |
| 4787 } | |
| 4788 | |
| 4789 // Enter a safepoint, but don't exit until the main thread tells us it | |
| 4790 // has done it works. This means this thread will not sweep its heap | |
| 4791 // since the sweep is done when the safepoint scope is destructed. | |
| 4792 { | |
| 4793 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack ); | |
| 4794 while (!s_workerContinue) { | |
| 4795 yield(); | |
| 4796 } | |
| 4797 } | |
| 4798 | |
| 4799 // At this point the worker have swept its heaps. Tell the main thread i ts | |
| 4800 // done. | |
| 4801 s_workerDidSweep = true; | |
| 4802 | |
| 4803 // Wait with detach until the main thread says so. This is not strictly | |
| 4804 // necessary, but it means the worker thread will not do its thread loca l | |
| 4805 // GCs just yet, making it easier to reason about that no new GC has occ urred | |
| 4806 // and the above sweep was the one finalizing the worker object. | |
| 4807 while (!s_workerFinish) { | |
| 4808 yield(); | |
| 4809 } | |
| 4810 | |
| 4811 ThreadState::detach(); | |
| 4812 s_workerRunning = false; | |
| 4813 } | |
| 4814 | |
| 4815 static volatile bool s_workerRunning; | |
|
Mads Ager (chromium)
2014/07/11 10:59:34
I guess we should either use atomic ops here or ha
wibling-chromium
2014/07/11 13:06:54
Done.
| |
| 4816 static volatile bool s_workerContinue; | |
| 4817 static volatile bool s_workerDidSweep; | |
| 4818 static volatile bool s_workerFinish; | |
| 4819 static volatile uintptr_t s_workerObjectPointer; | |
| 4820 }; | |
| 4821 | |
| 4822 volatile bool DeadBitTester::s_workerRunning = false; | |
| 4823 volatile bool DeadBitTester::s_workerContinue = false; | |
| 4824 volatile bool DeadBitTester::s_workerDidSweep = false; | |
| 4825 volatile bool DeadBitTester::s_workerFinish = false; | |
| 4826 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; | |
| 4827 | |
| 4828 TEST(HeapTest, ObjectDeadBit) | |
| 4829 { | |
| 4830 DeadBitTester::test(); | |
| 4831 } | |
| 4586 | 4832 |
| 4587 } // WebCore namespace | 4833 } // WebCore namespace |
| OLD | NEW |