| 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 | 131 |
| 132 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeakPair; | 132 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeakPair; |
| 133 | 133 |
| 134 struct PairWithWeakHandling : public StrongWeakPair { | 134 struct PairWithWeakHandling : public StrongWeakPair { |
| 135 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 135 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| 136 | 136 |
| 137 public: | 137 public: |
| 138 // Regular constructor. | 138 // Regular constructor. |
| 139 PairWithWeakHandling(IntWrapper* one, IntWrapper* two) | 139 PairWithWeakHandling(IntWrapper* one, IntWrapper* two) |
| 140 : StrongWeakPair(one, two) { | 140 : StrongWeakPair(one, two) { |
| 141 ASSERT( | 141 ASSERT(one); // We use null first field to indicate empty slots in the hash |
| 142 one); // We use null first field to indicate empty slots in the hash ta
ble. | 142 // table. |
| 143 } | 143 } |
| 144 | 144 |
| 145 // The HashTable (via the HashTrait) calls this constructor with a | 145 // The HashTable (via the HashTrait) calls this constructor with a |
| 146 // placement new to mark slots in the hash table as being deleted. We will | 146 // placement new to mark slots in the hash table as being deleted. We will |
| 147 // never call trace or the destructor on these slots. We mark ourselves delete
d | 147 // never call trace or the destructor on these slots. We mark ourselves |
| 148 // deleted |
| 148 // with a pointer to -1 in the first field. | 149 // with a pointer to -1 in the first field. |
| 149 PairWithWeakHandling(WTF::HashTableDeletedValueType) | 150 PairWithWeakHandling(WTF::HashTableDeletedValueType) |
| 150 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr) {} | 151 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr) {} |
| 151 | 152 |
| 152 // Used by the HashTable (via the HashTrait) to skip deleted slots in the | 153 // Used by the HashTable (via the HashTrait) to skip deleted slots in the |
| 153 // table. Recognizes objects that were 'constructed' using the above | 154 // table. Recognizes objects that were 'constructed' using the above |
| 154 // constructor. | 155 // constructor. |
| 155 bool isHashTableDeletedValue() const { | 156 bool isHashTableDeletedValue() const { |
| 156 return first == reinterpret_cast<IntWrapper*>(-1); | 157 return first == reinterpret_cast<IntWrapper*>(-1); |
| 157 } | 158 } |
| 158 | 159 |
| 159 // Since we don't allocate independent objects of this type, we don't need | 160 // Since we don't allocate independent objects of this type, we don't need |
| 160 // a regular trace method. Instead, we use a traceInCollection method. If | 161 // a regular trace method. Instead, we use a traceInCollection method. If |
| 161 // the entry should be deleted from the collection we return true and don't | 162 // the entry should be deleted from the collection we return true and don't |
| 162 // trace the strong pointer. | 163 // trace the strong pointer. |
| 163 template <typename VisitorDispatcher> | 164 template <typename VisitorDispatcher> |
| 164 bool traceInCollection(VisitorDispatcher visitor, | 165 bool traceInCollection(VisitorDispatcher visitor, |
| 165 WTF::ShouldWeakPointersBeMarkedStrongly strongify) { | 166 WTF::ShouldWeakPointersBeMarkedStrongly strongify) { |
| 166 visitor->traceInCollection(second, strongify); | 167 visitor->traceInCollection(second, strongify); |
| 167 if (!ThreadHeap::isHeapObjectAlive(second)) | 168 if (!ThreadHeap::isHeapObjectAlive(second)) |
| 168 return true; | 169 return true; |
| 169 // FIXME: traceInCollection is also called from WeakProcessing to check if t
he entry is dead. | 170 // FIXME: traceInCollection is also called from WeakProcessing to check if |
| 170 // The below if avoids calling trace in that case by only calling trace when
|first| is not yet marked. | 171 // the entry is dead. |
| 172 // The below if avoids calling trace in that case by only calling trace when |
| 173 // |first| is not yet marked. |
| 171 if (!ThreadHeap::isHeapObjectAlive(first)) | 174 if (!ThreadHeap::isHeapObjectAlive(first)) |
| 172 visitor->trace(first); | 175 visitor->trace(first); |
| 173 return false; | 176 return false; |
| 174 } | 177 } |
| 175 }; | 178 }; |
| 176 | 179 |
| 177 template <typename T> | 180 template <typename T> |
| 178 struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<T> { | 181 struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<T> { |
| 179 // We want to treat the object as a weak object in the sense that it can | 182 // We want to treat the object as a weak object in the sense that it can |
| 180 // disappear from hash sets and hash maps. | 183 // disappear from hash sets and hash maps. |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 | 582 |
| 580 if (gcCount < gcPerThread) { | 583 if (gcCount < gcPerThread) { |
| 581 preciselyCollectGarbage(); | 584 preciselyCollectGarbage(); |
| 582 gcCount++; | 585 gcCount++; |
| 583 atomicIncrement(&m_gcCount); | 586 atomicIncrement(&m_gcCount); |
| 584 } | 587 } |
| 585 | 588 |
| 586 // Taking snapshot shouldn't have any bad side effect. | 589 // Taking snapshot shouldn't have any bad side effect. |
| 587 // TODO(haraken): This snapshot GC causes crashes, so disable | 590 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 588 // it at the moment. Fix the crash and enable it. | 591 // it at the moment. Fix the crash and enable it. |
| 589 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::T
akeSnapshot, BlinkGC::ForcedGC); | 592 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, |
| 593 // BlinkGC::TakeSnapshot, BlinkGC::ForcedGC); |
| 590 preciselyCollectGarbage(); | 594 preciselyCollectGarbage(); |
| 591 EXPECT_EQ(wrapper->value(), 0x0bbac0de); | 595 EXPECT_EQ(wrapper->value(), 0x0bbac0de); |
| 592 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb); | 596 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb); |
| 593 } | 597 } |
| 594 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 598 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 595 testing::yieldCurrentThread(); | 599 testing::yieldCurrentThread(); |
| 596 } | 600 } |
| 597 | 601 |
| 598 ThreadState::detachCurrentThread(); | 602 ThreadState::detachCurrentThread(); |
| 599 atomicDecrement(&m_threadsToFinish); | 603 atomicDecrement(&m_threadsToFinish); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 625 | 629 |
| 626 if (gcCount < gcPerThread) { | 630 if (gcCount < gcPerThread) { |
| 627 preciselyCollectGarbage(); | 631 preciselyCollectGarbage(); |
| 628 gcCount++; | 632 gcCount++; |
| 629 atomicIncrement(&m_gcCount); | 633 atomicIncrement(&m_gcCount); |
| 630 } | 634 } |
| 631 | 635 |
| 632 // Taking snapshot shouldn't have any bad side effect. | 636 // Taking snapshot shouldn't have any bad side effect. |
| 633 // TODO(haraken): This snapshot GC causes crashes, so disable | 637 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 634 // it at the moment. Fix the crash and enable it. | 638 // it at the moment. Fix the crash and enable it. |
| 635 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::T
akeSnapshot, BlinkGC::ForcedGC); | 639 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, |
| 640 // BlinkGC::TakeSnapshot, BlinkGC::ForcedGC); |
| 636 preciselyCollectGarbage(); | 641 preciselyCollectGarbage(); |
| 637 EXPECT_TRUE(weakMap->isEmpty()); | 642 EXPECT_TRUE(weakMap->isEmpty()); |
| 638 EXPECT_TRUE(weakMap2.isEmpty()); | 643 EXPECT_TRUE(weakMap2.isEmpty()); |
| 639 } | 644 } |
| 640 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 645 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 641 testing::yieldCurrentThread(); | 646 testing::yieldCurrentThread(); |
| 642 } | 647 } |
| 643 ThreadState::detachCurrentThread(); | 648 ThreadState::detachCurrentThread(); |
| 644 atomicDecrement(&m_threadsToFinish); | 649 atomicDecrement(&m_threadsToFinish); |
| 645 } | 650 } |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1648 { | 1653 { |
| 1649 size_t slack = 0; | 1654 size_t slack = 0; |
| 1650 | 1655 |
| 1651 // When the test starts there may already have been leaked some memory | 1656 // When the test starts there may already have been leaked some memory |
| 1652 // on the heap, so we establish a base line. | 1657 // on the heap, so we establish a base line. |
| 1653 size_t baseLevel = initialObjectPayloadSize; | 1658 size_t baseLevel = initialObjectPayloadSize; |
| 1654 bool testPagesAllocated = !baseLevel; | 1659 bool testPagesAllocated = !baseLevel; |
| 1655 if (testPagesAllocated) | 1660 if (testPagesAllocated) |
| 1656 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); | 1661 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); |
| 1657 | 1662 |
| 1658 // This allocates objects on the general heap which should add a page of mem
ory. | 1663 // This allocates objects on the general heap which should add a page of |
| 1664 // memory. |
| 1659 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); | 1665 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); |
| 1660 slack += 4; | 1666 slack += 4; |
| 1661 memset(alloc32, 40, 32); | 1667 memset(alloc32, 40, 32); |
| 1662 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); | 1668 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); |
| 1663 slack += 4; | 1669 slack += 4; |
| 1664 memset(alloc64, 27, 64); | 1670 memset(alloc64, 27, 64); |
| 1665 | 1671 |
| 1666 size_t total = 96; | 1672 size_t total = 96; |
| 1667 | 1673 |
| 1668 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), | 1674 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), |
| (...skipping 2268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3937 // This is a low-level test where we call checkAndMarkPointer. This method | 3943 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3938 // causes the object start bitmap to be computed which requires the heap | 3944 // causes the object start bitmap to be computed which requires the heap |
| 3939 // to be in a consistent state (e.g. the free allocation area must be put | 3945 // to be in a consistent state (e.g. the free allocation area must be put |
| 3940 // into a free list header). However when we call makeConsistentForGC it | 3946 // into a free list header). However when we call makeConsistentForGC it |
| 3941 // also clears out the freelists so we have to rebuild those before trying | 3947 // also clears out the freelists so we have to rebuild those before trying |
| 3942 // to allocate anything again. We do this by forcing a GC after doing the | 3948 // to allocate anything again. We do this by forcing a GC after doing the |
| 3943 // checkAndMarkPointer tests. | 3949 // checkAndMarkPointer tests. |
| 3944 { | 3950 { |
| 3945 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3951 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3946 CountingVisitor visitor(ThreadState::current()); | 3952 CountingVisitor visitor(ThreadState::current()); |
| 3947 EXPECT_TRUE( | 3953 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not |
| 3948 scope | 3954 // park all threads. |
| 3949 .allThreadsParked()); // Fail the test if we could not park all thr
eads. | |
| 3950 heap.flushHeapDoesNotContainCache(); | 3955 heap.flushHeapDoesNotContainCache(); |
| 3951 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3956 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3952 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i])); | 3957 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i])); |
| 3953 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i])); | 3958 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i])); |
| 3954 } | 3959 } |
| 3955 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3960 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
| 3956 visitor.reset(); | 3961 visitor.reset(); |
| 3957 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress)); | 3962 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress)); |
| 3958 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress)); | 3963 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress)); |
| 3959 EXPECT_EQ(2ul, visitor.count()); | 3964 EXPECT_EQ(2ul, visitor.count()); |
| (...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4884 // weak processing may have taken place. | 4889 // weak processing may have taken place. |
| 4885 if (set3->size()) { | 4890 if (set3->size()) { |
| 4886 Iterator i3 = set3->begin(); | 4891 Iterator i3 = set3->begin(); |
| 4887 EXPECT_EQ(2, i3->first->value()); | 4892 EXPECT_EQ(2, i3->first->value()); |
| 4888 EXPECT_EQ(3, i3->second->value()); | 4893 EXPECT_EQ(3, i3->second->value()); |
| 4889 } | 4894 } |
| 4890 } | 4895 } |
| 4891 preciselyCollectGarbage(); | 4896 preciselyCollectGarbage(); |
| 4892 EXPECT_EQ(0u, set1->size()); | 4897 EXPECT_EQ(0u, set1->size()); |
| 4893 set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt)); | 4898 set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt)); |
| 4894 set1->add(PairWithWeakHandling( | 4899 // This one gets zapped at GC time because nothing holds the 103 alive. |
| 4895 livingInt, | 4900 set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); |
| 4896 IntWrapper::create( | |
| 4897 103))); // This one gets zapped at GC time because nothing holds the
103 alive. | |
| 4898 set1->add(PairWithWeakHandling( | 4901 set1->add(PairWithWeakHandling( |
| 4899 IntWrapper::create(103), | 4902 IntWrapper::create(103), |
| 4900 IntWrapper::create(103))); // This one gets zapped too. | 4903 IntWrapper::create(103))); // This one gets zapped too. |
| 4901 set1->add(PairWithWeakHandling(livingInt, livingInt)); | 4904 set1->add(PairWithWeakHandling(livingInt, livingInt)); |
| 4902 set1->add(PairWithWeakHandling( | 4905 // This one is identical to the previous and doesn't add anything. |
| 4903 livingInt, | 4906 set1->add(PairWithWeakHandling(livingInt, livingInt)); |
| 4904 livingInt)); // This one is identical to the previous and doesn't add any
thing. | |
| 4905 EXPECT_EQ(4u, set1->size()); | 4907 EXPECT_EQ(4u, set1->size()); |
| 4906 preciselyCollectGarbage(); | 4908 preciselyCollectGarbage(); |
| 4907 EXPECT_EQ(2u, set1->size()); | 4909 EXPECT_EQ(2u, set1->size()); |
| 4908 Iterator i1 = set1->begin(); | 4910 Iterator i1 = set1->begin(); |
| 4909 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt); | 4911 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt); |
| 4910 EXPECT_EQ(livingInt, i1->second); | 4912 EXPECT_EQ(livingInt, i1->second); |
| 4911 ++i1; | 4913 ++i1; |
| 4912 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt); | 4914 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt); |
| 4913 EXPECT_EQ(livingInt, i1->second); | 4915 EXPECT_EQ(livingInt, i1->second); |
| 4914 } | 4916 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4965 } | 4967 } |
| 4966 preciselyCollectGarbage(); | 4968 preciselyCollectGarbage(); |
| 4967 | 4969 |
| 4968 EXPECT_EQ(0u, map1->size()); | 4970 EXPECT_EQ(0u, map1->size()); |
| 4969 EXPECT_EQ(3, OffHeapInt::s_destructorCalls); | 4971 EXPECT_EQ(3, OffHeapInt::s_destructorCalls); |
| 4970 | 4972 |
| 4971 OffHeapInt::s_destructorCalls = 0; | 4973 OffHeapInt::s_destructorCalls = 0; |
| 4972 | 4974 |
| 4973 map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), | 4975 map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), |
| 4974 OffHeapInt::create(2000)); | 4976 OffHeapInt::create(2000)); |
| 4975 map1->add( | 4977 map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), |
| 4976 PairWithWeakHandling(livingInt, IntWrapper::create(103)), | 4978 OffHeapInt::create(2001)); // This one gets zapped at GC time |
| 4977 OffHeapInt::create( | 4979 // because nothing holds the 103 alive. |
| 4978 2001)); // This one gets zapped at GC time because nothing holds the
103 alive. | |
| 4979 map1->add( | 4980 map1->add( |
| 4980 PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), | 4981 PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), |
| 4981 OffHeapInt::create(2002)); // This one gets zapped too. | 4982 OffHeapInt::create(2002)); // This one gets zapped too. |
| 4982 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003)); | 4983 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003)); |
| 4983 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); | 4984 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); |
| 4984 map1->add( | 4985 map1->add(PairWithWeakHandling(livingInt, livingInt), |
| 4985 PairWithWeakHandling(livingInt, livingInt), | 4986 dupeInt); // This one is identical to the previous and doesn't add |
| 4986 dupeInt); // This one is identical to the previous and doesn't add anythi
ng. | 4987 // anything. |
| 4987 dupeInt.clear(); | 4988 dupeInt.clear(); |
| 4988 | 4989 |
| 4989 EXPECT_EQ(0, OffHeapInt::s_destructorCalls); | 4990 EXPECT_EQ(0, OffHeapInt::s_destructorCalls); |
| 4990 EXPECT_EQ(4u, map1->size()); | 4991 EXPECT_EQ(4u, map1->size()); |
| 4991 preciselyCollectGarbage(); | 4992 preciselyCollectGarbage(); |
| 4992 EXPECT_EQ(2, OffHeapInt::s_destructorCalls); | 4993 EXPECT_EQ(2, OffHeapInt::s_destructorCalls); |
| 4993 EXPECT_EQ(2u, map1->size()); | 4994 EXPECT_EQ(2u, map1->size()); |
| 4994 Iterator i1 = map1->begin(); | 4995 Iterator i1 = map1->begin(); |
| 4995 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt); | 4996 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt); |
| 4996 EXPECT_EQ(livingInt, i1->key.second); | 4997 EXPECT_EQ(livingInt, i1->key.second); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5048 } | 5049 } |
| 5049 preciselyCollectGarbage(); | 5050 preciselyCollectGarbage(); |
| 5050 | 5051 |
| 5051 EXPECT_EQ(0u, map1->size()); | 5052 EXPECT_EQ(0u, map1->size()); |
| 5052 EXPECT_EQ(3, OffHeapInt::s_destructorCalls); | 5053 EXPECT_EQ(3, OffHeapInt::s_destructorCalls); |
| 5053 | 5054 |
| 5054 OffHeapInt::s_destructorCalls = 0; | 5055 OffHeapInt::s_destructorCalls = 0; |
| 5055 | 5056 |
| 5056 map1->add(OffHeapInt::create(2000), | 5057 map1->add(OffHeapInt::create(2000), |
| 5057 PairWithWeakHandling(IntWrapper::create(103), livingInt)); | 5058 PairWithWeakHandling(IntWrapper::create(103), livingInt)); |
| 5058 map1->add( | 5059 // This one gets zapped at GC time because nothing holds the 103 alive. |
| 5059 OffHeapInt::create(2001), | 5060 map1->add(OffHeapInt::create(2001), |
| 5060 PairWithWeakHandling( | 5061 PairWithWeakHandling(livingInt, IntWrapper::create(103))); |
| 5061 livingInt, | |
| 5062 IntWrapper::create( | |
| 5063 103))); // This one gets zapped at GC time because nothing holds
the 103 alive. | |
| 5064 map1->add(OffHeapInt::create(2002), | 5062 map1->add(OffHeapInt::create(2002), |
| 5065 PairWithWeakHandling( | 5063 PairWithWeakHandling( |
| 5066 IntWrapper::create(103), | 5064 IntWrapper::create(103), |
| 5067 IntWrapper::create(103))); // This one gets zapped too. | 5065 IntWrapper::create(103))); // This one gets zapped too. |
| 5068 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003)); | 5066 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003)); |
| 5069 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); | 5067 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); |
| 5070 map1->add( | 5068 // This one is identical to the previous and doesn't add anything. |
| 5071 dupeInt, | 5069 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); |
| 5072 PairWithWeakHandling( | |
| 5073 livingInt, | |
| 5074 livingInt)); // This one is identical to the previous and doesn't add
anything. | |
| 5075 dupeInt.clear(); | 5070 dupeInt.clear(); |
| 5076 | 5071 |
| 5077 EXPECT_EQ(0, OffHeapInt::s_destructorCalls); | 5072 EXPECT_EQ(0, OffHeapInt::s_destructorCalls); |
| 5078 EXPECT_EQ(4u, map1->size()); | 5073 EXPECT_EQ(4u, map1->size()); |
| 5079 preciselyCollectGarbage(); | 5074 preciselyCollectGarbage(); |
| 5080 EXPECT_EQ(2, OffHeapInt::s_destructorCalls); | 5075 EXPECT_EQ(2, OffHeapInt::s_destructorCalls); |
| 5081 EXPECT_EQ(2u, map1->size()); | 5076 EXPECT_EQ(2u, map1->size()); |
| 5082 Iterator i1 = map1->begin(); | 5077 Iterator i1 = map1->begin(); |
| 5083 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt); | 5078 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt); |
| 5084 EXPECT_EQ(livingInt, i1->value.second); | 5079 EXPECT_EQ(livingInt, i1->value.second); |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5549 // until leaving the safepoint scope. | 5544 // until leaving the safepoint scope. |
| 5550 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 5545 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 5551 parkWorkerThread(); | 5546 parkWorkerThread(); |
| 5552 } | 5547 } |
| 5553 | 5548 |
| 5554 // Wake up the main thread when done sweeping. | 5549 // Wake up the main thread when done sweeping. |
| 5555 wakeMainThread(); | 5550 wakeMainThread(); |
| 5556 | 5551 |
| 5557 // Wait with detach until the main thread says so. This is not strictly | 5552 // Wait with detach until the main thread says so. This is not strictly |
| 5558 // necessary, but it means the worker thread will not do its thread local | 5553 // necessary, but it means the worker thread will not do its thread local |
| 5559 // GCs just yet, making it easier to reason about that no new GC has occurre
d | 5554 // GCs just yet, making it easier to reason about that no new GC has |
| 5560 // and the above sweep was the one finalizing the worker object. | 5555 // occurred and the above sweep was the one finalizing the worker object. |
| 5561 parkWorkerThread(); | 5556 parkWorkerThread(); |
| 5562 | 5557 |
| 5563 ThreadState::detachCurrentThread(); | 5558 ThreadState::detachCurrentThread(); |
| 5564 } | 5559 } |
| 5565 | 5560 |
| 5566 static volatile uintptr_t s_workerObjectPointer; | 5561 static volatile uintptr_t s_workerObjectPointer; |
| 5567 }; | 5562 }; |
| 5568 | 5563 |
| 5569 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; | 5564 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; |
| 5570 | 5565 |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6380 } | 6375 } |
| 6381 | 6376 |
| 6382 DEFINE_INLINE_VIRTUAL_TRACE() {} | 6377 DEFINE_INLINE_VIRTUAL_TRACE() {} |
| 6383 }; | 6378 }; |
| 6384 | 6379 |
| 6385 class TestMixinAllocationB : public TestMixinAllocationA { | 6380 class TestMixinAllocationB : public TestMixinAllocationA { |
| 6386 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationB); | 6381 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationB); |
| 6387 | 6382 |
| 6388 public: | 6383 public: |
| 6389 TestMixinAllocationB() | 6384 TestMixinAllocationB() |
| 6390 : m_a(new TestMixinAllocationA()) // Construct object during a mixin cons
truction. | 6385 : m_a(new TestMixinAllocationA()) // Construct object during a mixin |
| 6386 // construction. |
| 6391 { | 6387 { |
| 6392 // Completely wrong in general, but test only | 6388 // Completely wrong in general, but test only |
| 6393 // runs this constructor while constructing another mixin. | 6389 // runs this constructor while constructing another mixin. |
| 6394 ASSERT(ThreadState::current()->isGCForbidden()); | 6390 ASSERT(ThreadState::current()->isGCForbidden()); |
| 6395 } | 6391 } |
| 6396 | 6392 |
| 6397 DEFINE_INLINE_TRACE() { | 6393 DEFINE_INLINE_TRACE() { |
| 6398 visitor->trace(m_a); | 6394 visitor->trace(m_a); |
| 6399 TestMixinAllocationA::trace(visitor); | 6395 TestMixinAllocationA::trace(visitor); |
| 6400 } | 6396 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6513 parkWorkerThread(); | 6509 parkWorkerThread(); |
| 6514 | 6510 |
| 6515 // Step 6: Finish. | 6511 // Step 6: Finish. |
| 6516 ThreadState::detachCurrentThread(); | 6512 ThreadState::detachCurrentThread(); |
| 6517 wakeMainThread(); | 6513 wakeMainThread(); |
| 6518 } | 6514 } |
| 6519 | 6515 |
| 6520 } // anonymous namespace | 6516 } // anonymous namespace |
| 6521 | 6517 |
| 6522 TEST(HeapTest, CrossThreadWeakPersistent) { | 6518 TEST(HeapTest, CrossThreadWeakPersistent) { |
| 6523 // Create an object in the worker thread, have a CrossThreadWeakPersistent poi
nting to it on the main thread, | 6519 // Create an object in the worker thread, have a CrossThreadWeakPersistent |
| 6524 // clear the reference in the worker thread, run a GC in the worker thread, an
d see if the | 6520 // pointing to it on the main thread, clear the reference in the worker |
| 6521 // thread, run a GC in the worker thread, and see if the |
| 6525 // CrossThreadWeakPersistent is cleared. | 6522 // CrossThreadWeakPersistent is cleared. |
| 6526 | 6523 |
| 6527 DestructorLockingObject::s_destructorCalls = 0; | 6524 DestructorLockingObject::s_destructorCalls = 0; |
| 6528 | 6525 |
| 6529 // Step 1: Initiate a worker thread, and wait for |object| to get allocated on
the worker thread. | 6526 // Step 1: Initiate a worker thread, and wait for |object| to get allocated on |
| 6527 // the worker thread. |
| 6530 MutexLocker mainThreadMutexLocker(mainThreadMutex()); | 6528 MutexLocker mainThreadMutexLocker(mainThreadMutex()); |
| 6531 std::unique_ptr<WebThread> workerThread = | 6529 std::unique_ptr<WebThread> workerThread = |
| 6532 wrapUnique(Platform::current()->createThread("Test Worker Thread")); | 6530 wrapUnique(Platform::current()->createThread("Test Worker Thread")); |
| 6533 DestructorLockingObject* object = nullptr; | 6531 DestructorLockingObject* object = nullptr; |
| 6534 workerThread->getWebTaskRunner()->postTask( | 6532 workerThread->getWebTaskRunner()->postTask( |
| 6535 BLINK_FROM_HERE, | 6533 BLINK_FROM_HERE, |
| 6536 crossThreadBind(workerThreadMainForCrossThreadWeakPersistentTest, | 6534 crossThreadBind(workerThreadMainForCrossThreadWeakPersistentTest, |
| 6537 crossThreadUnretained(&object))); | 6535 crossThreadUnretained(&object))); |
| 6538 parkMainThread(); | 6536 parkMainThread(); |
| 6539 | 6537 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6586 EXPECT_EQ(1u, vector2.size()); | 6584 EXPECT_EQ(1u, vector2.size()); |
| 6587 // TODO(Oilpan): when Vector.h's contiguous container support no longer disables | 6585 // TODO(Oilpan): when Vector.h's contiguous container support no longer disables |
| 6588 // Vector<>s with inline capacity, remove. | 6586 // Vector<>s with inline capacity, remove. |
| 6589 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER) | 6587 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
| 6590 EXPECT_EQ(16u, vector1.capacity()); | 6588 EXPECT_EQ(16u, vector1.capacity()); |
| 6591 EXPECT_EQ(16u, vector2.capacity()); | 6589 EXPECT_EQ(16u, vector2.capacity()); |
| 6592 #endif | 6590 #endif |
| 6593 } | 6591 } |
| 6594 | 6592 |
| 6595 TEST(HeapTest, TestStaticLocals) { | 6593 TEST(HeapTest, TestStaticLocals) { |
| 6596 // Sanity check DEFINE_STATIC_LOCAL()s over heap allocated objects and collect
ions. | 6594 // Sanity check DEFINE_STATIC_LOCAL()s over heap allocated objects and |
| 6595 // collections. |
| 6597 | 6596 |
| 6598 DEFINE_STATIC_LOCAL(IntWrapper, intWrapper, (new IntWrapper(33))); | 6597 DEFINE_STATIC_LOCAL(IntWrapper, intWrapper, (new IntWrapper(33))); |
| 6599 DEFINE_STATIC_LOCAL(PersistentHeapVector<Member<IntWrapper>>, | 6598 DEFINE_STATIC_LOCAL(PersistentHeapVector<Member<IntWrapper>>, |
| 6600 persistentHeapVectorIntWrapper, ()); | 6599 persistentHeapVectorIntWrapper, ()); |
| 6601 DEFINE_STATIC_LOCAL(HeapVector<Member<IntWrapper>>, heapVectorIntWrapper, | 6600 DEFINE_STATIC_LOCAL(HeapVector<Member<IntWrapper>>, heapVectorIntWrapper, |
| 6602 (new HeapVector<Member<IntWrapper>>)); | 6601 (new HeapVector<Member<IntWrapper>>)); |
| 6603 | 6602 |
| 6604 EXPECT_EQ(33, intWrapper.value()); | 6603 EXPECT_EQ(33, intWrapper.value()); |
| 6605 EXPECT_EQ(0u, persistentHeapVectorIntWrapper.size()); | 6604 EXPECT_EQ(0u, persistentHeapVectorIntWrapper.size()); |
| 6606 EXPECT_EQ(0u, heapVectorIntWrapper.size()); | 6605 EXPECT_EQ(0u, heapVectorIntWrapper.size()); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6802 "HeapVector"); | 6801 "HeapVector"); |
| 6803 static_assert( | 6802 static_assert( |
| 6804 WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value, | 6803 WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value, |
| 6805 "HeapDeque"); | 6804 "HeapDeque"); |
| 6806 static_assert(WTF::IsGarbageCollectedType< | 6805 static_assert(WTF::IsGarbageCollectedType< |
| 6807 HeapTerminatedArray<Member<IntWrapper>>>::value, | 6806 HeapTerminatedArray<Member<IntWrapper>>>::value, |
| 6808 "HeapTerminatedArray"); | 6807 "HeapTerminatedArray"); |
| 6809 } | 6808 } |
| 6810 | 6809 |
| 6811 } // namespace blink | 6810 } // namespace blink |
| OLD | NEW |