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 4254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4265 Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHea
pInt::create(1).get())); | 4265 Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHea
pInt::create(1).get())); |
4266 | 4266 |
4267 UseMixin::s_traceCount = 0; | 4267 UseMixin::s_traceCount = 0; |
4268 Mixin* mixin = UseMixin::create(); | 4268 Mixin* mixin = UseMixin::create(); |
4269 Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0)); | 4269 Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0)); |
4270 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 4270 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
4271 // The closure should have a persistent handle to the mixin. | 4271 // The closure should have a persistent handle to the mixin. |
4272 EXPECT_EQ(1, UseMixin::s_traceCount); | 4272 EXPECT_EQ(1, UseMixin::s_traceCount); |
4273 } | 4273 } |
4274 | 4274 |
| 4275 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet; |
| 4276 |
| 4277 // These special traits will remove a set from a map when the set is empty. |
| 4278 struct EmptyClearingHastSetTraits : HashTraits<WeakSet> { |
| 4279 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCol
lections; |
| 4280 static bool shouldRemoveFromCollection(Visitor* visitor, WeakSet& set) |
| 4281 { |
| 4282 return set.isEmpty(); // Remove this set from any maps it is in. |
| 4283 } |
| 4284 static void traceInCollection(Visitor* visitor, WeakSet& set, WebCore::Shoul
dWeakPointersBeMarkedStrongly strongify) |
| 4285 { |
| 4286 // We just trace normally, which will invoke the normal weak handling |
| 4287 // of the set, removing individual items. |
| 4288 set.trace(visitor); |
| 4289 } |
| 4290 }; |
| 4291 |
| 4292 // This is an example to show how you can remove entries from a T->WeakSet map |
| 4293 // when the weak sets become empty. For this example we are using a type that |
| 4294 // is given to use (HeapHashSet) rather than a type of our own. This means: |
| 4295 // 1) We can't just override the HashTrait for the type since this would affect |
| 4296 // all collections that use this kind of weak set. Instead we have our own |
| 4297 // traits and use a map with custom traits for the value type. These traits |
| 4298 // are the 5th template parameter, so we have to supply default values for |
| 4299 // the 3rd and 4th template parameters |
| 4300 // 2) We can't just inherit from WeakHandlingHashTraits, since that trait |
| 4301 // assumes we can add methods to the type, but we can't add methods to |
| 4302 // HeapHashSet. |
| 4303 TEST(HeapTest, RemoveEmptySets) |
| 4304 { |
| 4305 HeapStats initialHeapSize; |
| 4306 clearOutOldGarbage(&initialHeapSize); |
| 4307 OffHeapInt::s_destructorCalls = 0; |
| 4308 |
| 4309 Persistent<IntWrapper> livingInt(IntWrapper::create(42)); |
| 4310 |
| 4311 typedef RefPtr<OffHeapInt> Key; |
| 4312 typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash, HashTraits<Ke
y>, EmptyClearingHastSetTraits> Map; |
| 4313 Persistent<Map> map(new Map()); |
| 4314 map->add(OffHeapInt::create(1), WeakSet()); |
| 4315 { |
| 4316 WeakSet& set = map->begin()->value; |
| 4317 set.add(IntWrapper::create(103)); // Weak set can't hold this long. |
| 4318 set.add(livingInt); // This prevents the set from being emptied. |
| 4319 EXPECT_EQ(2u, set.size()); |
| 4320 } |
| 4321 |
| 4322 // The set we add here is empty, so the entry will be removed from the map |
| 4323 // at the next GC. |
| 4324 map->add(OffHeapInt::create(2), WeakSet()); |
| 4325 EXPECT_EQ(2u, map->size()); |
| 4326 |
| 4327 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 4328 EXPECT_EQ(1u, map->size()); // The one with key 2 was removed. |
| 4329 EXPECT_EQ(1, OffHeapInt::s_destructorCalls); |
| 4330 { |
| 4331 WeakSet& set = map->begin()->value; |
| 4332 EXPECT_EQ(1u, set.size()); |
| 4333 } |
| 4334 |
| 4335 livingInt.clear(); // The weak set can no longer keep the '42' alive now. |
| 4336 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 4337 if (map->size() == 1u) { |
| 4338 // If the weak processing for the set ran after the weak processing for |
| 4339 // the map, then the set was not empty, and so the entry in the map was |
| 4340 // not removed yet. |
| 4341 WeakSet& set = map->begin()->value; |
| 4342 EXPECT_EQ(0u, set.size()); |
| 4343 } |
| 4344 |
| 4345 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 4346 EXPECT_EQ(0u, map->size()); |
| 4347 } |
| 4348 |
4275 } // WebCore namespace | 4349 } // WebCore namespace |
OLD | NEW |