Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: Source/heap/HeapTest.cpp

Issue 216723002: Make sure all destructors are called in HeapHashMap and HeapHashSet (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: CR feedback Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/heap/Heap.h ('k') | Source/heap/Visitor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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()
2277 : m_x(emptyValue)
2278 {
2279 s_liveThingsWithDestructor++;
2280 }
2281
2282 ThingWithDestructor(int x)
2283 : m_x(x)
2284 {
2285 s_liveThingsWithDestructor++;
2286 }
2287
2288 ThingWithDestructor(const ThingWithDestructor&other)
2289 {
2290 *this = other;
2291 s_liveThingsWithDestructor++;
2292 }
2293
2294 ~ThingWithDestructor()
2295 {
2296 s_liveThingsWithDestructor--;
2297 }
2298
2299 int value() { return m_x; }
2300
2301 static int s_liveThingsWithDestructor;
2302
2303 unsigned hash() { return IntHash<int>::hash(m_x); }
2304
2305 private:
2306 static const int emptyValue = 0;
2307 int m_x;
2308 };
2309
2310 int ThingWithDestructor::s_liveThingsWithDestructor;
2311
2312 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2313 static const bool needsDestruction = true;
2314 };
2315
2316 static void heapMapDestructorHelper(bool clearMaps)
2317 {
2318 HeapStats initialHeapStats;
2319 clearOutOldGarbage(&initialHeapStats);
2320 ThingWithDestructor::s_liveThingsWithDestructor = 0;
2321
2322 typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageColle cted> > RefMap;
2323
2324 typedef HeapHashMap<
2325 WeakMember<IntWrapper>,
2326 ThingWithDestructor,
2327 DefaultHash<WeakMember<IntWrapper> >::Hash,
2328 HashTraits<WeakMember<IntWrapper> >,
2329 ThingWithDestructorTraits> Map;
2330
2331 Persistent<Map> map(new Map());
2332 Persistent<RefMap> refMap(new RefMap());
2333
2334 Persistent<IntWrapper> luck(IntWrapper::create(103));
2335
2336 int baseLine, refBaseLine;
2337
2338 {
2339 Map stackMap;
2340 RefMap stackRefMap;
2341
2342 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2343 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2344
2345 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2346 stackMap.add(luck, ThingWithDestructor(8128));
2347 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::c reate());
2348 stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2349
2350 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2351 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2352
2353 // Although the heap maps are on-stack, we can't expect prompt
2354 // finalization of the elements, so when they go out of scope here we
2355 // will not necessarily have called the relevant destructors.
2356 }
2357
2358 // The RefCountedAndGarbageCollected things need an extra GC to discover
2359 // that they are no longer ref counted.
2360 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2361 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2362 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2363 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls) ;
2364
2365 // Now use maps kept alive with persistents. Here we don't expect any
2366 // destructors to be called before there have been GCs.
2367
2368 map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2369 map->add(luck, ThingWithDestructor(8128));
2370 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create()) ;
2371 refMap->add(luck, RefCountedAndGarbageCollected::create());
2372
2373 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2374 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2375
2376 luck.clear();
2377 if (clearMaps) {
2378 map->clear(); // Clear map.
2379 refMap->clear(); // Clear map.
2380 } else {
2381 map.clear(); // Clear Persistent handle, not map.
2382 refMap.clear(); // Clear Persistent handle, not map.
2383 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2384 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2385 }
2386
2387 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2388
2389 // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2390 // noticies it's been decremented to zero.
2391 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2392 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls) ;
2393 }
2394
2395 TEST(HeapTest, HeapMapDestructor)
2396 {
2397 heapMapDestructorHelper(true);
2398 heapMapDestructorHelper(false);
2399 }
2400
2268 typedef HeapHashSet<PairWeakStrong> WeakStrongSet; 2401 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2269 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet; 2402 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2270 typedef HeapHashSet<PairStrongWeak> StrongWeakSet; 2403 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2271 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet; 2404 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2272 2405
2273 void checkPairSets( 2406 void checkPairSets(
2274 Persistent<WeakStrongSet>& weakStrong, 2407 Persistent<WeakStrongSet>& weakStrong,
2275 Persistent<StrongWeakSet>& strongWeak, 2408 Persistent<StrongWeakSet>& strongWeak,
2276 Persistent<WeakUnwrappedSet>& weakUnwrapped, 2409 Persistent<WeakUnwrappedSet>& weakUnwrapped,
2277 Persistent<UnwrappedWeakSet>& unwrappedWeak, 2410 Persistent<UnwrappedWeakSet>& unwrappedWeak,
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 HeapHashMap<void*, IntVector>::iterator it = map->find(key); 2970 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
2838 EXPECT_EQ(0u, map->get(key).size()); 2971 EXPECT_EQ(0u, map->get(key).size());
2839 2972
2840 it->value.append(IntWrapper::create(42)); 2973 it->value.append(IntWrapper::create(42));
2841 EXPECT_EQ(1u, map->get(key).size()); 2974 EXPECT_EQ(1u, map->get(key).size());
2842 2975
2843 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map); 2976 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
2844 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); 2977 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2845 EXPECT_EQ(1u, map->get(key).size()); 2978 EXPECT_EQ(1u, map->get(key).size());
2846 EXPECT_EQ(0, IntWrapper::s_destructorCalls); 2979 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2980
2981 keepAlive = nullptr;
2982 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2983 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
2847 } 2984 }
2848 2985
2849 TEST(heap, GarbageCollectedMixin) 2986 TEST(heap, GarbageCollectedMixin)
2850 { 2987 {
2851 HeapStats initialHeapStats; 2988 HeapStats initialHeapStats;
2852 clearOutOldGarbage(&initialHeapStats); 2989 clearOutOldGarbage(&initialHeapStats);
2853 2990
2854 Persistent<UseMixin> usemixin = UseMixin::create(); 2991 Persistent<UseMixin> usemixin = UseMixin::create();
2855 ASSERT_EQ(0, UseMixin::s_traceCount); 2992 ASSERT_EQ(0, UseMixin::s_traceCount);
2856 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); 2993 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
3055 // Check that the wrapper allocated during finalization is not 3192 // Check that the wrapper allocated during finalization is not
3056 // swept away and zapped later in the same sweeping phase. 3193 // swept away and zapped later in the same sweeping phase.
3057 EXPECT_EQ(42, wrapper->value()); 3194 EXPECT_EQ(42, wrapper->value());
3058 3195
3059 wrapper.clear(); 3196 wrapper.clear();
3060 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); 3197 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3061 EXPECT_EQ(10, IntWrapper::s_destructorCalls); 3198 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3062 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls); 3199 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3063 } 3200 }
3064 3201
3202 class SimpleClassWithDestructor {
3203 public:
3204 SimpleClassWithDestructor() { }
3205 ~SimpleClassWithDestructor()
3206 {
3207 ASSERT(!s_wasDestructed);
3208 s_wasDestructed = true;
3209 }
3210 static bool s_wasDestructed;
3211 };
3212
3213 bool SimpleClassWithDestructor::s_wasDestructed;
3214
3215 TEST(HeapTest, DestructorsCalledOnMapClear)
3216 {
3217 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3218 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3219 map.add(hasDestructor, adoptPtr(hasDestructor));
3220 SimpleClassWithDestructor::s_wasDestructed = false;
3221 map.clear();
3222 ASSERT(SimpleClassWithDestructor::s_wasDestructed);
3223 }
3224
3065 } // WebCore namespace 3225 } // WebCore namespace
OLDNEW
« no previous file with comments | « Source/heap/Heap.h ('k') | Source/heap/Visitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698