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 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 static PassRefPtr<RefCountedAndGarbageCollected> create() | 701 static PassRefPtr<RefCountedAndGarbageCollected> create() |
| 702 { | 702 { |
| 703 return adoptRef(new RefCountedAndGarbageCollected()); | 703 return adoptRef(new RefCountedAndGarbageCollected()); |
| 704 } | 704 } |
| 705 | 705 |
| 706 ~RefCountedAndGarbageCollected() | 706 ~RefCountedAndGarbageCollected() |
| 707 { | 707 { |
| 708 ++s_destructorCalls; | 708 ++s_destructorCalls; |
| 709 } | 709 } |
| 710 | 710 |
| 711 // These are here with their default implementations so you can break in | |
| 712 // them in the debugger. | |
| 713 void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref( ); } | |
| 714 void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::de ref(); } | |
| 715 | |
| 711 void trace(Visitor*) { } | 716 void trace(Visitor*) { } |
| 712 | 717 |
| 713 static int s_destructorCalls; | 718 static int s_destructorCalls; |
| 714 | 719 |
| 715 private: | 720 private: |
| 716 RefCountedAndGarbageCollected() | 721 RefCountedAndGarbageCollected() |
| 717 { | 722 { |
| 718 } | 723 } |
| 719 }; | 724 }; |
| 720 | 725 |
| (...skipping 1492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2213 found++; | 2218 found++; |
| 2214 int value = (*it)->value(); | 2219 int value = (*it)->value(); |
| 2215 EXPECT_TRUE(value >= 0 && value < 1100); | 2220 EXPECT_TRUE(value >= 0 && value < 1100); |
| 2216 ++it; | 2221 ++it; |
| 2217 } | 2222 } |
| 2218 EXPECT_EQ(expected, found); | 2223 EXPECT_EQ(expected, found); |
| 2219 } | 2224 } |
| 2220 | 2225 |
| 2221 TEST(HeapTest, HeapWeakCollectionSimple) | 2226 TEST(HeapTest, HeapWeakCollectionSimple) |
| 2222 { | 2227 { |
| 2223 | 2228 HeapStats initialHeapStats; |
| 2229 clearOutOldGarbage(&initialHeapStats); | |
| 2224 IntWrapper::s_destructorCalls = 0; | 2230 IntWrapper::s_destructorCalls = 0; |
| 2225 | 2231 |
| 2226 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive; | 2232 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive; |
| 2227 | 2233 |
| 2228 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong; | 2234 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong; |
| 2229 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak; | 2235 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak; |
| 2230 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWea k; | 2236 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWea k; |
| 2231 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet; | 2237 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet; |
| 2232 | 2238 |
| 2233 Persistent<WeakStrong> weakStrong = new WeakStrong(); | 2239 Persistent<WeakStrong> weakStrong = new WeakStrong(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2258 keepNumbersAlive[0] = nullptr; | 2264 keepNumbersAlive[0] = nullptr; |
| 2259 | 2265 |
| 2260 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 2266 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2261 | 2267 |
| 2262 EXPECT_EQ(0u, weakStrong->size()); | 2268 EXPECT_EQ(0u, weakStrong->size()); |
| 2263 EXPECT_EQ(0u, strongWeak->size()); | 2269 EXPECT_EQ(0u, strongWeak->size()); |
| 2264 EXPECT_EQ(0u, weakWeak->size()); | 2270 EXPECT_EQ(0u, weakWeak->size()); |
| 2265 EXPECT_EQ(2u, weakSet->size()); | 2271 EXPECT_EQ(2u, weakSet->size()); |
| 2266 } | 2272 } |
| 2267 | 2273 |
| 2274 class ThingWithDestructor { | |
| 2275 public: | |
| 2276 ThingWithDestructor() : m_x(emptyValue) { } | |
| 2277 ThingWithDestructor(int x) : m_x(x) { ASSERT(x != emptyValue); } | |
| 2278 | |
| 2279 ~ThingWithDestructor() | |
| 2280 { | |
| 2281 if (m_x != emptyValue) | |
|
wibling-chromium
2014/03/28 10:35:23
Does the constructor get called more than once?
Erik Corry
2014/03/30 20:11:36
Thanks for pointing this out. There was a bug in
| |
| 2282 s_destructorCalls++; | |
| 2283 m_x = emptyValue; | |
| 2284 } | |
| 2285 | |
| 2286 int value() { return m_x; } | |
| 2287 | |
| 2288 static int s_destructorCalls; | |
| 2289 | |
| 2290 unsigned hash() { return IntHash<int>::hash(m_x); } | |
| 2291 | |
| 2292 private: | |
| 2293 static const int emptyValue = 0; | |
| 2294 int m_x; | |
| 2295 }; | |
| 2296 | |
| 2297 int ThingWithDestructor::s_destructorCalls; | |
| 2298 | |
| 2299 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> { | |
| 2300 static const bool needsDestruction = true; | |
| 2301 }; | |
| 2302 | |
| 2303 static void heapMapDestructorHelper(bool clearMaps) | |
| 2304 { | |
| 2305 HeapStats initialHeapStats; | |
| 2306 clearOutOldGarbage(&initialHeapStats); | |
| 2307 ThingWithDestructor::s_destructorCalls = 0; | |
| 2308 | |
| 2309 typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageColle cted> > RefMap; | |
| 2310 | |
| 2311 typedef HeapHashMap< | |
| 2312 WeakMember<IntWrapper>, | |
| 2313 ThingWithDestructor, | |
| 2314 DefaultHash<WeakMember<IntWrapper> >::Hash, | |
| 2315 HashTraits<WeakMember<IntWrapper> >, | |
| 2316 ThingWithDestructorTraits> Map; | |
| 2317 | |
| 2318 Persistent<Map> map(new Map()); | |
| 2319 Persistent<RefMap> refMap(new RefMap()); | |
| 2320 | |
| 2321 Persistent<IntWrapper> luck(IntWrapper::create(103)); | |
| 2322 | |
| 2323 int baseLine, refBaseLine; | |
| 2324 | |
| 2325 { | |
| 2326 Map stackMap; | |
| 2327 RefMap stackRefMap; | |
| 2328 | |
| 2329 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2330 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2331 | |
| 2332 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729)); | |
| 2333 stackMap.add(luck, ThingWithDestructor(8128)); | |
| 2334 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::c reate()); | |
| 2335 stackRefMap.add(luck, RefCountedAndGarbageCollected::create()); | |
| 2336 | |
| 2337 baseLine = ThingWithDestructor::s_destructorCalls; | |
| 2338 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls; | |
| 2339 | |
| 2340 // Although the heap maps are on-stack, we can't expect prompt | |
| 2341 // finalization of the elements, so when they go out of scope here we | |
| 2342 // will not necessarily have called the relevant destructors. | |
| 2343 } | |
| 2344 | |
| 2345 // The RefCountedAndGarbageCollected things need an extra GC to discover | |
| 2346 // that they are no longer ref counted. | |
| 2347 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2348 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2349 EXPECT_EQ(baseLine + 2, ThingWithDestructor::s_destructorCalls); | |
| 2350 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls) ; | |
| 2351 | |
| 2352 // Now use maps kept alive with persistents. Here we don't expect any | |
| 2353 // destructors to be called before there have been GCs. | |
| 2354 | |
| 2355 map->add(IntWrapper::create(42), ThingWithDestructor(1729)); | |
| 2356 map->add(luck, ThingWithDestructor(8128)); | |
| 2357 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create()) ; | |
| 2358 refMap->add(luck, RefCountedAndGarbageCollected::create()); | |
| 2359 | |
| 2360 baseLine = ThingWithDestructor::s_destructorCalls; | |
| 2361 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls; | |
| 2362 | |
| 2363 luck.clear(); | |
| 2364 if (clearMaps) { | |
| 2365 map->clear(); // Clear map. | |
| 2366 refMap->clear(); // Clear map. | |
| 2367 } else { | |
| 2368 map.clear(); // Clear Persistent handle, not map. | |
| 2369 refMap.clear(); // Clear Persistent handle, not map. | |
| 2370 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2371 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2372 } | |
| 2373 | |
| 2374 EXPECT_EQ(baseLine + 2, ThingWithDestructor::s_destructorCalls); | |
| 2375 | |
| 2376 // Need a GC to make sure that the RefCountedAndGarbageCollected thing | |
| 2377 // noticies it's been decremented to zero. | |
| 2378 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2379 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls) ; | |
| 2380 } | |
| 2381 | |
| 2382 TEST(HeapTest, HeapMapDestructor) | |
| 2383 { | |
| 2384 heapMapDestructorHelper(true); | |
| 2385 heapMapDestructorHelper(false); | |
| 2386 } | |
| 2387 | |
| 2268 typedef HeapHashSet<PairWeakStrong> WeakStrongSet; | 2388 typedef HeapHashSet<PairWeakStrong> WeakStrongSet; |
| 2269 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet; | 2389 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet; |
| 2270 typedef HeapHashSet<PairStrongWeak> StrongWeakSet; | 2390 typedef HeapHashSet<PairStrongWeak> StrongWeakSet; |
| 2271 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet; | 2391 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet; |
| 2272 | 2392 |
| 2273 void checkPairSets( | 2393 void checkPairSets( |
| 2274 Persistent<WeakStrongSet>& weakStrong, | 2394 Persistent<WeakStrongSet>& weakStrong, |
| 2275 Persistent<StrongWeakSet>& strongWeak, | 2395 Persistent<StrongWeakSet>& strongWeak, |
| 2276 Persistent<WeakUnwrappedSet>& weakUnwrapped, | 2396 Persistent<WeakUnwrappedSet>& weakUnwrapped, |
| 2277 Persistent<UnwrappedWeakSet>& unwrappedWeak, | 2397 Persistent<UnwrappedWeakSet>& unwrappedWeak, |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2837 HeapHashMap<void*, IntVector>::iterator it = map->find(key); | 2957 HeapHashMap<void*, IntVector>::iterator it = map->find(key); |
| 2838 EXPECT_EQ(0u, map->get(key).size()); | 2958 EXPECT_EQ(0u, map->get(key).size()); |
| 2839 | 2959 |
| 2840 it->value.append(IntWrapper::create(42)); | 2960 it->value.append(IntWrapper::create(42)); |
| 2841 EXPECT_EQ(1u, map->get(key).size()); | 2961 EXPECT_EQ(1u, map->get(key).size()); |
| 2842 | 2962 |
| 2843 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map); | 2963 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map); |
| 2844 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 2964 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2845 EXPECT_EQ(1u, map->get(key).size()); | 2965 EXPECT_EQ(1u, map->get(key).size()); |
| 2846 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 2966 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
| 2967 | |
| 2968 keepAlive = nullptr; | |
| 2969 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | |
| 2970 EXPECT_EQ(1, IntWrapper::s_destructorCalls); | |
| 2847 } | 2971 } |
| 2848 | 2972 |
| 2849 TEST(heap, GarbageCollectedMixin) | 2973 TEST(heap, GarbageCollectedMixin) |
| 2850 { | 2974 { |
| 2851 HeapStats initialHeapStats; | 2975 HeapStats initialHeapStats; |
| 2852 clearOutOldGarbage(&initialHeapStats); | 2976 clearOutOldGarbage(&initialHeapStats); |
| 2853 | 2977 |
| 2854 Persistent<UseMixin> usemixin = UseMixin::create(); | 2978 Persistent<UseMixin> usemixin = UseMixin::create(); |
| 2855 ASSERT_EQ(0, UseMixin::s_traceCount); | 2979 ASSERT_EQ(0, UseMixin::s_traceCount); |
| 2856 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 2980 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3055 // Check that the wrapper allocated during finalization is not | 3179 // Check that the wrapper allocated during finalization is not |
| 3056 // swept away and zapped later in the same sweeping phase. | 3180 // swept away and zapped later in the same sweeping phase. |
| 3057 EXPECT_EQ(42, wrapper->value()); | 3181 EXPECT_EQ(42, wrapper->value()); |
| 3058 | 3182 |
| 3059 wrapper.clear(); | 3183 wrapper.clear(); |
| 3060 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3184 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 3061 EXPECT_EQ(10, IntWrapper::s_destructorCalls); | 3185 EXPECT_EQ(10, IntWrapper::s_destructorCalls); |
| 3062 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls); | 3186 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls); |
| 3063 } | 3187 } |
| 3064 | 3188 |
| 3189 class Fluff { | |
|
Mads Ager (chromium)
2014/03/28 11:12:39
Ehm, move meaningful names, please?
Erik Corry
2014/03/30 20:11:36
Done.
| |
| 3190 public: | |
| 3191 Fluff() { } | |
| 3192 ~Fluff() | |
| 3193 { | |
| 3194 ASSERT(!s_wasDestructed); | |
| 3195 s_wasDestructed = true; | |
| 3196 } | |
| 3197 static bool s_wasDestructed; | |
| 3198 }; | |
| 3199 | |
| 3200 bool Fluff::s_wasDestructed; | |
| 3201 | |
| 3202 TEST(HeapTest, Flaf) | |
|
Mads Ager (chromium)
2014/03/28 11:12:39
DestructorsCalledOnMapClear?
Erik Corry
2014/03/30 20:11:36
Done.
| |
| 3203 { | |
| 3204 HeapHashMap<Fluff*, OwnPtr<Fluff> > map; | |
| 3205 Fluff* fluff = new Fluff(); | |
| 3206 map.add(fluff, adoptPtr(fluff)); | |
| 3207 Fluff::s_wasDestructed = false; | |
| 3208 map.clear(); | |
| 3209 ASSERT(Fluff::s_wasDestructed); | |
| 3210 } | |
| 3211 | |
| 3065 } // WebCore namespace | 3212 } // WebCore namespace |
| OLD | NEW |