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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 | 175 |
176 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeakPair; | 176 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> StrongWeakPair; |
177 | 177 |
178 struct PairWithWeakHandling : public StrongWeakPair { | 178 struct PairWithWeakHandling : public StrongWeakPair { |
179 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 179 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
180 | 180 |
181 public: | 181 public: |
182 // Regular constructor. | 182 // Regular constructor. |
183 PairWithWeakHandling(IntWrapper* one, IntWrapper* two) | 183 PairWithWeakHandling(IntWrapper* one, IntWrapper* two) |
184 : StrongWeakPair(one, two) { | 184 : StrongWeakPair(one, two) { |
185 ASSERT(one); // We use null first field to indicate empty slots in the hash | 185 DCHECK(one); // We use null first field to indicate empty slots in the hash |
186 // table. | 186 // table. |
187 } | 187 } |
188 | 188 |
189 // The HashTable (via the HashTrait) calls this constructor with a | 189 // The HashTable (via the HashTrait) calls this constructor with a |
190 // placement new to mark slots in the hash table as being deleted. We will | 190 // placement new to mark slots in the hash table as being deleted. We will |
191 // never call trace or the destructor on these slots. We mark ourselves | 191 // never call trace or the destructor on these slots. We mark ourselves |
192 // deleted | 192 // deleted |
193 // with a pointer to -1 in the first field. | 193 // with a pointer to -1 in the first field. |
194 PairWithWeakHandling(WTF::HashTableDeletedValueType) | 194 PairWithWeakHandling(WTF::HashTableDeletedValueType) |
195 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr) {} | 195 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr) {} |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 : public SimpleClassHashTraits<blink::KeyWithCopyingMoveConstructor> {}; | 325 : public SimpleClassHashTraits<blink::KeyWithCopyingMoveConstructor> {}; |
326 | 326 |
327 } // namespace WTF | 327 } // namespace WTF |
328 | 328 |
329 namespace blink { | 329 namespace blink { |
330 | 330 |
331 class TestGCScope { | 331 class TestGCScope { |
332 public: | 332 public: |
333 explicit TestGCScope(BlinkGC::StackState state) | 333 explicit TestGCScope(BlinkGC::StackState state) |
334 : state_(ThreadState::Current()), safe_point_scope_(state) { | 334 : state_(ThreadState::Current()), safe_point_scope_(state) { |
335 ASSERT(state_->CheckThread()); | 335 DCHECK(state_->CheckThread()); |
336 state_->PreGC(); | 336 state_->PreGC(); |
337 } | 337 } |
338 | 338 |
339 ~TestGCScope() { | 339 ~TestGCScope() { |
340 state_->PostGC(BlinkGC::kGCWithSweep); | 340 state_->PostGC(BlinkGC::kGCWithSweep); |
341 state_->PreSweep(BlinkGC::kGCWithSweep); | 341 state_->PreSweep(BlinkGC::kGCWithSweep); |
342 } | 342 } |
343 | 343 |
344 private: | 344 private: |
345 ThreadState* state_; | 345 ThreadState* state_; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 const int ThreadedTesterBase::kNumberOfThreads; | 511 const int ThreadedTesterBase::kNumberOfThreads; |
512 | 512 |
513 class ThreadedHeapTester : public ThreadedTesterBase { | 513 class ThreadedHeapTester : public ThreadedTesterBase { |
514 public: | 514 public: |
515 static void Test() { ThreadedTesterBase::Test(new ThreadedHeapTester); } | 515 static void Test() { ThreadedTesterBase::Test(new ThreadedHeapTester); } |
516 | 516 |
517 ~ThreadedHeapTester() override { | 517 ~ThreadedHeapTester() override { |
518 // Verify that the threads cleared their CTPs when | 518 // Verify that the threads cleared their CTPs when |
519 // terminating, preventing access to a finalized heap. | 519 // terminating, preventing access to a finalized heap. |
520 for (auto& global_int_wrapper : cross_persistents_) { | 520 for (auto& global_int_wrapper : cross_persistents_) { |
521 ASSERT(global_int_wrapper.get()); | 521 DCHECK(global_int_wrapper.get()); |
522 EXPECT_FALSE(global_int_wrapper.get()->Get()); | 522 EXPECT_FALSE(global_int_wrapper.get()->Get()); |
523 } | 523 } |
524 } | 524 } |
525 | 525 |
526 protected: | 526 protected: |
527 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; | 527 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; |
528 | 528 |
529 Mutex mutex_; | 529 Mutex mutex_; |
530 Vector<std::unique_ptr<GlobalIntWrapperPersistent>> cross_persistents_; | 530 Vector<std::unique_ptr<GlobalIntWrapperPersistent>> cross_persistents_; |
531 | 531 |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
930 : public GarbageCollectedFinalized<RefCountedAndGarbageCollected> { | 930 : public GarbageCollectedFinalized<RefCountedAndGarbageCollected> { |
931 public: | 931 public: |
932 static RefCountedAndGarbageCollected* Create() { | 932 static RefCountedAndGarbageCollected* Create() { |
933 return new RefCountedAndGarbageCollected; | 933 return new RefCountedAndGarbageCollected; |
934 } | 934 } |
935 | 935 |
936 ~RefCountedAndGarbageCollected() { ++destructor_calls_; } | 936 ~RefCountedAndGarbageCollected() { ++destructor_calls_; } |
937 | 937 |
938 void Ref() { | 938 void Ref() { |
939 if (UNLIKELY(!ref_count_)) { | 939 if (UNLIKELY(!ref_count_)) { |
940 ASSERT(ThreadState::Current()->FindPageFromAddress( | 940 #if DCHECK_IS_ON() |
| 941 DCHECK(ThreadState::Current()->FindPageFromAddress( |
941 reinterpret_cast<Address>(this))); | 942 reinterpret_cast<Address>(this))); |
| 943 #endif |
942 keep_alive_ = this; | 944 keep_alive_ = this; |
943 } | 945 } |
944 ++ref_count_; | 946 ++ref_count_; |
945 } | 947 } |
946 | 948 |
947 void Deref() { | 949 void Deref() { |
948 ASSERT(ref_count_ > 0); | 950 DCHECK_GT(ref_count_, 0); |
949 if (!--ref_count_) | 951 if (!--ref_count_) |
950 keep_alive_.Clear(); | 952 keep_alive_.Clear(); |
951 } | 953 } |
952 | 954 |
953 DEFINE_INLINE_TRACE() {} | 955 DEFINE_INLINE_TRACE() {} |
954 | 956 |
955 static int destructor_calls_; | 957 static int destructor_calls_; |
956 | 958 |
957 private: | 959 private: |
958 RefCountedAndGarbageCollected() : ref_count_(0) {} | 960 RefCountedAndGarbageCollected() : ref_count_(0) {} |
959 | 961 |
960 int ref_count_; | 962 int ref_count_; |
961 SelfKeepAlive<RefCountedAndGarbageCollected> keep_alive_; | 963 SelfKeepAlive<RefCountedAndGarbageCollected> keep_alive_; |
962 }; | 964 }; |
963 | 965 |
964 int RefCountedAndGarbageCollected::destructor_calls_ = 0; | 966 int RefCountedAndGarbageCollected::destructor_calls_ = 0; |
965 | 967 |
966 class RefCountedAndGarbageCollected2 | 968 class RefCountedAndGarbageCollected2 |
967 : public HeapTestOtherSuperClass, | 969 : public HeapTestOtherSuperClass, |
968 public GarbageCollectedFinalized<RefCountedAndGarbageCollected2> { | 970 public GarbageCollectedFinalized<RefCountedAndGarbageCollected2> { |
969 public: | 971 public: |
970 static RefCountedAndGarbageCollected2* Create() { | 972 static RefCountedAndGarbageCollected2* Create() { |
971 return new RefCountedAndGarbageCollected2; | 973 return new RefCountedAndGarbageCollected2; |
972 } | 974 } |
973 | 975 |
974 ~RefCountedAndGarbageCollected2() { ++destructor_calls_; } | 976 ~RefCountedAndGarbageCollected2() { ++destructor_calls_; } |
975 | 977 |
976 void Ref() { | 978 void Ref() { |
977 if (UNLIKELY(!ref_count_)) { | 979 if (UNLIKELY(!ref_count_)) { |
978 ASSERT(ThreadState::Current()->FindPageFromAddress( | 980 #if DCHECK_IS_ON() |
| 981 DCHECK(ThreadState::Current()->FindPageFromAddress( |
979 reinterpret_cast<Address>(this))); | 982 reinterpret_cast<Address>(this))); |
| 983 #endif |
980 keep_alive_ = this; | 984 keep_alive_ = this; |
981 } | 985 } |
982 ++ref_count_; | 986 ++ref_count_; |
983 } | 987 } |
984 | 988 |
985 void Deref() { | 989 void Deref() { |
986 ASSERT(ref_count_ > 0); | 990 DCHECK_GT(ref_count_, 0); |
987 if (!--ref_count_) | 991 if (!--ref_count_) |
988 keep_alive_.Clear(); | 992 keep_alive_.Clear(); |
989 } | 993 } |
990 | 994 |
991 DEFINE_INLINE_TRACE() {} | 995 DEFINE_INLINE_TRACE() {} |
992 | 996 |
993 static int destructor_calls_; | 997 static int destructor_calls_; |
994 | 998 |
995 private: | 999 private: |
996 RefCountedAndGarbageCollected2() : ref_count_(0) {} | 1000 RefCountedAndGarbageCollected2() : ref_count_(0) {} |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1208 did_call_will_finalize_ = true; | 1212 did_call_will_finalize_ = true; |
1209 } | 1213 } |
1210 | 1214 |
1211 static ObserverMap& Observe(Observable& target) { | 1215 static ObserverMap& Observe(Observable& target) { |
1212 ObserverMap& map = Observers(); | 1216 ObserverMap& map = Observers(); |
1213 ObserverMap::AddResult result = map.insert(&target, nullptr); | 1217 ObserverMap::AddResult result = map.insert(&target, nullptr); |
1214 if (result.is_new_entry) { | 1218 if (result.is_new_entry) { |
1215 result.stored_value->value = | 1219 result.stored_value->value = |
1216 WTF::MakeUnique<FinalizationObserverWithHashMap>(target); | 1220 WTF::MakeUnique<FinalizationObserverWithHashMap>(target); |
1217 } else { | 1221 } else { |
1218 ASSERT(result.stored_value->value); | 1222 DCHECK(result.stored_value->value); |
1219 } | 1223 } |
1220 return map; | 1224 return map; |
1221 } | 1225 } |
1222 | 1226 |
1223 static void ClearObservers() { | 1227 static void ClearObservers() { |
1224 delete observer_map_; | 1228 delete observer_map_; |
1225 observer_map_ = nullptr; | 1229 observer_map_ = nullptr; |
1226 } | 1230 } |
1227 | 1231 |
1228 static bool did_call_will_finalize_; | 1232 static bool did_call_will_finalize_; |
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2084 EXPECT_EQ(1u, Bar::live_); | 2088 EXPECT_EQ(1u, Bar::live_); |
2085 } | 2089 } |
2086 PreciselyCollectGarbage(); | 2090 PreciselyCollectGarbage(); |
2087 EXPECT_EQ(0u, Bar::live_); | 2091 EXPECT_EQ(0u, Bar::live_); |
2088 } | 2092 } |
2089 | 2093 |
2090 TEST(HeapTest, MarkTest) { | 2094 TEST(HeapTest, MarkTest) { |
2091 { | 2095 { |
2092 Bar::live_ = 0; | 2096 Bar::live_ = 0; |
2093 Persistent<Bar> bar = Bar::Create(); | 2097 Persistent<Bar> bar = Bar::Create(); |
2094 ASSERT(ThreadState::Current()->FindPageFromAddress(bar)); | 2098 #if DCHECK_IS_ON() |
| 2099 DCHECK(ThreadState::Current()->FindPageFromAddress(bar)); |
| 2100 #endif |
2095 EXPECT_EQ(1u, Bar::live_); | 2101 EXPECT_EQ(1u, Bar::live_); |
2096 { | 2102 { |
2097 Foo* foo = Foo::Create(bar); | 2103 Foo* foo = Foo::Create(bar); |
2098 ASSERT(ThreadState::Current()->FindPageFromAddress(foo)); | 2104 #if DCHECK_IS_ON() |
| 2105 DCHECK(ThreadState::Current()->FindPageFromAddress(foo)); |
| 2106 #endif |
2099 EXPECT_EQ(2u, Bar::live_); | 2107 EXPECT_EQ(2u, Bar::live_); |
2100 EXPECT_TRUE(reinterpret_cast<Address>(foo) != | 2108 EXPECT_TRUE(reinterpret_cast<Address>(foo) != |
2101 reinterpret_cast<Address>(bar.Get())); | 2109 reinterpret_cast<Address>(bar.Get())); |
2102 ConservativelyCollectGarbage(); | 2110 ConservativelyCollectGarbage(); |
2103 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive. | 2111 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive. |
2104 EXPECT_EQ(2u, Bar::live_); | 2112 EXPECT_EQ(2u, Bar::live_); |
2105 } | 2113 } |
2106 PreciselyCollectGarbage(); | 2114 PreciselyCollectGarbage(); |
2107 EXPECT_EQ(1u, Bar::live_); | 2115 EXPECT_EQ(1u, Bar::live_); |
2108 } | 2116 } |
2109 PreciselyCollectGarbage(); | 2117 PreciselyCollectGarbage(); |
2110 EXPECT_EQ(0u, Bar::live_); | 2118 EXPECT_EQ(0u, Bar::live_); |
2111 } | 2119 } |
2112 | 2120 |
2113 TEST(HeapTest, DeepTest) { | 2121 TEST(HeapTest, DeepTest) { |
2114 const unsigned kDepth = 100000; | 2122 const unsigned kDepth = 100000; |
2115 Bar::live_ = 0; | 2123 Bar::live_ = 0; |
2116 { | 2124 { |
2117 Bar* bar = Bar::Create(); | 2125 Bar* bar = Bar::Create(); |
2118 ASSERT(ThreadState::Current()->FindPageFromAddress(bar)); | 2126 #if DCHECK_IS_ON() |
| 2127 DCHECK(ThreadState::Current()->FindPageFromAddress(bar)); |
| 2128 #endif |
2119 Foo* foo = Foo::Create(bar); | 2129 Foo* foo = Foo::Create(bar); |
2120 ASSERT(ThreadState::Current()->FindPageFromAddress(foo)); | 2130 #if DCHECK_IS_ON() |
| 2131 DCHECK(ThreadState::Current()->FindPageFromAddress(foo)); |
| 2132 #endif |
2121 EXPECT_EQ(2u, Bar::live_); | 2133 EXPECT_EQ(2u, Bar::live_); |
2122 for (unsigned i = 0; i < kDepth; i++) { | 2134 for (unsigned i = 0; i < kDepth; i++) { |
2123 Foo* foo2 = Foo::Create(foo); | 2135 Foo* foo2 = Foo::Create(foo); |
2124 foo = foo2; | 2136 foo = foo2; |
2125 ASSERT(ThreadState::Current()->FindPageFromAddress(foo)); | 2137 #if DCHECK_IS_ON() |
| 2138 DCHECK(ThreadState::Current()->FindPageFromAddress(foo)); |
| 2139 #endif |
2126 } | 2140 } |
2127 EXPECT_EQ(kDepth + 2, Bar::live_); | 2141 EXPECT_EQ(kDepth + 2, Bar::live_); |
2128 ConservativelyCollectGarbage(); | 2142 ConservativelyCollectGarbage(); |
2129 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive. | 2143 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive. |
2130 EXPECT_EQ(kDepth + 2, Bar::live_); | 2144 EXPECT_EQ(kDepth + 2, Bar::live_); |
2131 } | 2145 } |
2132 PreciselyCollectGarbage(); | 2146 PreciselyCollectGarbage(); |
2133 EXPECT_EQ(0u, Bar::live_); | 2147 EXPECT_EQ(0u, Bar::live_); |
2134 } | 2148 } |
2135 | 2149 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2258 ThreadHeap& heap = ThreadState::Current()->Heap(); | 2272 ThreadHeap& heap = ThreadState::Current()->Heap(); |
2259 ClearOutOldGarbage(); | 2273 ClearOutOldGarbage(); |
2260 size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting(); | 2274 size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting(); |
2261 size_t initial_allocated_space = heap.HeapStats().AllocatedSpace(); | 2275 size_t initial_allocated_space = heap.HeapStats().AllocatedSpace(); |
2262 IntWrapper::destructor_calls_ = 0; | 2276 IntWrapper::destructor_calls_ = 0; |
2263 LargeHeapObject::destructor_calls_ = 0; | 2277 LargeHeapObject::destructor_calls_ = 0; |
2264 { | 2278 { |
2265 int slack = | 2279 int slack = |
2266 8; // LargeHeapObject points to an IntWrapper that is also allocated. | 2280 8; // LargeHeapObject points to an IntWrapper that is also allocated. |
2267 Persistent<LargeHeapObject> object = LargeHeapObject::Create(); | 2281 Persistent<LargeHeapObject> object = LargeHeapObject::Create(); |
2268 ASSERT(ThreadState::Current()->FindPageFromAddress(object)); | 2282 #if DCHECK_IS_ON() |
2269 ASSERT(ThreadState::Current()->FindPageFromAddress( | 2283 DCHECK(ThreadState::Current()->FindPageFromAddress(object)); |
| 2284 DCHECK(ThreadState::Current()->FindPageFromAddress( |
2270 reinterpret_cast<char*>(object.Get()) + sizeof(LargeHeapObject) - 1)); | 2285 reinterpret_cast<char*>(object.Get()) + sizeof(LargeHeapObject) - 1)); |
| 2286 #endif |
2271 ClearOutOldGarbage(); | 2287 ClearOutOldGarbage(); |
2272 size_t after_allocation = heap.HeapStats().AllocatedSpace(); | 2288 size_t after_allocation = heap.HeapStats().AllocatedSpace(); |
2273 { | 2289 { |
2274 object->Set(0, 'a'); | 2290 object->Set(0, 'a'); |
2275 EXPECT_EQ('a', object->Get(0)); | 2291 EXPECT_EQ('a', object->Get(0)); |
2276 object->Set(object->length() - 1, 'b'); | 2292 object->Set(object->length() - 1, 'b'); |
2277 EXPECT_EQ('b', object->Get(object->length() - 1)); | 2293 EXPECT_EQ('b', object->Get(object->length() - 1)); |
2278 size_t expected_large_heap_object_payload_size = | 2294 size_t expected_large_heap_object_payload_size = |
2279 ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject)); | 2295 ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject)); |
2280 size_t expected_object_payload_size = | 2296 size_t expected_object_payload_size = |
(...skipping 3369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5650 } | 5666 } |
5651 #endif | 5667 #endif |
5652 #endif | 5668 #endif |
5653 | 5669 |
5654 static bool AllocateAndReturnBool() { | 5670 static bool AllocateAndReturnBool() { |
5655 ConservativelyCollectGarbage(); | 5671 ConservativelyCollectGarbage(); |
5656 return true; | 5672 return true; |
5657 } | 5673 } |
5658 | 5674 |
5659 static bool CheckGCForbidden() { | 5675 static bool CheckGCForbidden() { |
5660 ASSERT(ThreadState::Current()->IsGCForbidden()); | 5676 DCHECK(ThreadState::Current()->IsGCForbidden()); |
5661 return true; | 5677 return true; |
5662 } | 5678 } |
5663 | 5679 |
5664 class MixinClass : public GarbageCollectedMixin { | 5680 class MixinClass : public GarbageCollectedMixin { |
5665 public: | 5681 public: |
5666 MixinClass() : dummy_(CheckGCForbidden()) {} | 5682 MixinClass() : dummy_(CheckGCForbidden()) {} |
5667 | 5683 |
5668 private: | 5684 private: |
5669 bool dummy_; | 5685 bool dummy_; |
5670 }; | 5686 }; |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6204 // Disable ASan, otherwise its stack checking (use-after-return) will | 6220 // Disable ASan, otherwise its stack checking (use-after-return) will |
6205 // confuse the direction check. | 6221 // confuse the direction check. |
6206 static char* previous = nullptr; | 6222 static char* previous = nullptr; |
6207 char dummy; | 6223 char dummy; |
6208 if (!previous) { | 6224 if (!previous) { |
6209 previous = &dummy; | 6225 previous = &dummy; |
6210 GrowthDirection result = StackGrowthDirection(); | 6226 GrowthDirection result = StackGrowthDirection(); |
6211 previous = nullptr; | 6227 previous = nullptr; |
6212 return result; | 6228 return result; |
6213 } | 6229 } |
6214 ASSERT(&dummy != previous); | 6230 DCHECK_NE(&dummy, previous); |
6215 return &dummy < previous ? kGrowsTowardsLower : kGrowsTowardsHigher; | 6231 return &dummy < previous ? kGrowsTowardsLower : kGrowsTowardsHigher; |
6216 } | 6232 } |
6217 | 6233 |
6218 } // namespace | 6234 } // namespace |
6219 | 6235 |
6220 TEST(HeapTest, StackGrowthDirection) { | 6236 TEST(HeapTest, StackGrowthDirection) { |
6221 // The implementation of marking probes stack usage as it runs, | 6237 // The implementation of marking probes stack usage as it runs, |
6222 // and has a builtin assumption that the stack grows towards | 6238 // and has a builtin assumption that the stack grows towards |
6223 // lower addresses. | 6239 // lower addresses. |
6224 EXPECT_EQ(kGrowsTowardsLower, StackGrowthDirection()); | 6240 EXPECT_EQ(kGrowsTowardsLower, StackGrowthDirection()); |
6225 } | 6241 } |
6226 | 6242 |
6227 class TestMixinAllocationA : public GarbageCollected<TestMixinAllocationA>, | 6243 class TestMixinAllocationA : public GarbageCollected<TestMixinAllocationA>, |
6228 public GarbageCollectedMixin { | 6244 public GarbageCollectedMixin { |
6229 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationA); | 6245 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationA); |
6230 | 6246 |
6231 public: | 6247 public: |
6232 TestMixinAllocationA() { | 6248 TestMixinAllocationA() { |
6233 // Completely wrong in general, but test only | 6249 // Completely wrong in general, but test only |
6234 // runs this constructor while constructing another mixin. | 6250 // runs this constructor while constructing another mixin. |
6235 ASSERT(ThreadState::Current()->IsGCForbidden()); | 6251 DCHECK(ThreadState::Current()->IsGCForbidden()); |
6236 } | 6252 } |
6237 | 6253 |
6238 DEFINE_INLINE_VIRTUAL_TRACE() {} | 6254 DEFINE_INLINE_VIRTUAL_TRACE() {} |
6239 }; | 6255 }; |
6240 | 6256 |
6241 class TestMixinAllocationB : public TestMixinAllocationA { | 6257 class TestMixinAllocationB : public TestMixinAllocationA { |
6242 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationB); | 6258 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationB); |
6243 | 6259 |
6244 public: | 6260 public: |
6245 TestMixinAllocationB() | 6261 TestMixinAllocationB() |
6246 : a_(new TestMixinAllocationA()) // Construct object during a mixin | 6262 : a_(new TestMixinAllocationA()) // Construct object during a mixin |
6247 // construction. | 6263 // construction. |
6248 { | 6264 { |
6249 // Completely wrong in general, but test only | 6265 // Completely wrong in general, but test only |
6250 // runs this constructor while constructing another mixin. | 6266 // runs this constructor while constructing another mixin. |
6251 ASSERT(ThreadState::Current()->IsGCForbidden()); | 6267 DCHECK(ThreadState::Current()->IsGCForbidden()); |
6252 } | 6268 } |
6253 | 6269 |
6254 DEFINE_INLINE_TRACE() { | 6270 DEFINE_INLINE_TRACE() { |
6255 visitor->Trace(a_); | 6271 visitor->Trace(a_); |
6256 TestMixinAllocationA::Trace(visitor); | 6272 TestMixinAllocationA::Trace(visitor); |
6257 } | 6273 } |
6258 | 6274 |
6259 private: | 6275 private: |
6260 Member<TestMixinAllocationA> a_; | 6276 Member<TestMixinAllocationA> a_; |
6261 }; | 6277 }; |
6262 | 6278 |
6263 class TestMixinAllocationC final : public TestMixinAllocationB { | 6279 class TestMixinAllocationC final : public TestMixinAllocationB { |
6264 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationC); | 6280 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocationC); |
6265 | 6281 |
6266 public: | 6282 public: |
6267 TestMixinAllocationC() { ASSERT(!ThreadState::Current()->IsGCForbidden()); } | 6283 TestMixinAllocationC() { DCHECK(!ThreadState::Current()->IsGCForbidden()); } |
6268 | 6284 |
6269 DEFINE_INLINE_TRACE() { TestMixinAllocationB::Trace(visitor); } | 6285 DEFINE_INLINE_TRACE() { TestMixinAllocationB::Trace(visitor); } |
6270 }; | 6286 }; |
6271 | 6287 |
6272 TEST(HeapTest, NestedMixinConstruction) { | 6288 TEST(HeapTest, NestedMixinConstruction) { |
6273 TestMixinAllocationC* object = new TestMixinAllocationC(); | 6289 TestMixinAllocationC* object = new TestMixinAllocationC(); |
6274 EXPECT_TRUE(object); | 6290 EXPECT_TRUE(object); |
6275 } | 6291 } |
6276 | 6292 |
6277 class ObjectWithLargeAmountsOfAllocationInConstructor { | 6293 class ObjectWithLargeAmountsOfAllocationInConstructor { |
6278 public: | 6294 public: |
6279 ObjectWithLargeAmountsOfAllocationInConstructor( | 6295 ObjectWithLargeAmountsOfAllocationInConstructor( |
6280 size_t number_of_large_objects_to_allocate, | 6296 size_t number_of_large_objects_to_allocate, |
6281 ClassWithMember* member) { | 6297 ClassWithMember* member) { |
6282 // Should a constructor allocate plenty in its constructor, | 6298 // Should a constructor allocate plenty in its constructor, |
6283 // and it is a base of GC mixin, GCs will remain locked out | 6299 // and it is a base of GC mixin, GCs will remain locked out |
6284 // regardless, as we cannot safely trace the leftmost GC | 6300 // regardless, as we cannot safely trace the leftmost GC |
6285 // mixin base. | 6301 // mixin base. |
6286 ASSERT(ThreadState::Current()->IsGCForbidden()); | 6302 DCHECK(ThreadState::Current()->IsGCForbidden()); |
6287 for (size_t i = 0; i < number_of_large_objects_to_allocate; i++) { | 6303 for (size_t i = 0; i < number_of_large_objects_to_allocate; i++) { |
6288 LargeHeapObject* large_object = LargeHeapObject::Create(); | 6304 LargeHeapObject* large_object = LargeHeapObject::Create(); |
6289 EXPECT_TRUE(large_object); | 6305 EXPECT_TRUE(large_object); |
6290 EXPECT_EQ(0, member->TraceCount()); | 6306 EXPECT_EQ(0, member->TraceCount()); |
6291 } | 6307 } |
6292 } | 6308 } |
6293 }; | 6309 }; |
6294 | 6310 |
6295 class TestMixinAllocatingObject final | 6311 class TestMixinAllocatingObject final |
6296 : public TestMixinAllocationB, | 6312 : public TestMixinAllocationB, |
6297 public ObjectWithLargeAmountsOfAllocationInConstructor { | 6313 public ObjectWithLargeAmountsOfAllocationInConstructor { |
6298 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocatingObject); | 6314 USING_GARBAGE_COLLECTED_MIXIN(TestMixinAllocatingObject); |
6299 | 6315 |
6300 public: | 6316 public: |
6301 static TestMixinAllocatingObject* Create(ClassWithMember* member) { | 6317 static TestMixinAllocatingObject* Create(ClassWithMember* member) { |
6302 return new TestMixinAllocatingObject(member); | 6318 return new TestMixinAllocatingObject(member); |
6303 } | 6319 } |
6304 | 6320 |
6305 DEFINE_INLINE_TRACE() { | 6321 DEFINE_INLINE_TRACE() { |
6306 visitor->Trace(trace_counter_); | 6322 visitor->Trace(trace_counter_); |
6307 TestMixinAllocationB::Trace(visitor); | 6323 TestMixinAllocationB::Trace(visitor); |
6308 } | 6324 } |
6309 | 6325 |
6310 int TraceCount() const { return trace_counter_->TraceCount(); } | 6326 int TraceCount() const { return trace_counter_->TraceCount(); } |
6311 | 6327 |
6312 private: | 6328 private: |
6313 TestMixinAllocatingObject(ClassWithMember* member) | 6329 TestMixinAllocatingObject(ClassWithMember* member) |
6314 : ObjectWithLargeAmountsOfAllocationInConstructor(600, member), | 6330 : ObjectWithLargeAmountsOfAllocationInConstructor(600, member), |
6315 trace_counter_(TraceCounter::Create()) { | 6331 trace_counter_(TraceCounter::Create()) { |
6316 ASSERT(!ThreadState::Current()->IsGCForbidden()); | 6332 DCHECK(!ThreadState::Current()->IsGCForbidden()); |
6317 ConservativelyCollectGarbage(); | 6333 ConservativelyCollectGarbage(); |
6318 EXPECT_GT(member->TraceCount(), 0); | 6334 EXPECT_GT(member->TraceCount(), 0); |
6319 EXPECT_GT(TraceCount(), 0); | 6335 EXPECT_GT(TraceCount(), 0); |
6320 } | 6336 } |
6321 | 6337 |
6322 Member<TraceCounter> trace_counter_; | 6338 Member<TraceCounter> trace_counter_; |
6323 }; | 6339 }; |
6324 | 6340 |
6325 TEST(HeapTest, MixinConstructionNoGC) { | 6341 TEST(HeapTest, MixinConstructionNoGC) { |
6326 Persistent<ClassWithMember> object = ClassWithMember::Create(); | 6342 Persistent<ClassWithMember> object = ClassWithMember::Create(); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6682 map.insert(key, IntWrapper::Create(i)); | 6698 map.insert(key, IntWrapper::Create(i)); |
6683 } | 6699 } |
6684 | 6700 |
6685 EXPECT_FALSE(string.Impl()->HasOneRef()); | 6701 EXPECT_FALSE(string.Impl()->HasOneRef()); |
6686 map.Clear(); | 6702 map.Clear(); |
6687 | 6703 |
6688 EXPECT_TRUE(string.Impl()->HasOneRef()); | 6704 EXPECT_TRUE(string.Impl()->HasOneRef()); |
6689 } | 6705 } |
6690 | 6706 |
6691 } // namespace blink | 6707 } // namespace blink |
OLD | NEW |