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 |