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 19 matching lines...) Expand all Loading... |
30 | 30 |
31 #include "config.h" | 31 #include "config.h" |
32 | 32 |
33 #include "platform/heap/Handle.h" | 33 #include "platform/heap/Handle.h" |
34 #include "platform/heap/Heap.h" | 34 #include "platform/heap/Heap.h" |
35 #include "platform/heap/HeapLinkedStack.h" | 35 #include "platform/heap/HeapLinkedStack.h" |
36 #include "platform/heap/HeapTerminatedArrayBuilder.h" | 36 #include "platform/heap/HeapTerminatedArrayBuilder.h" |
37 #include "platform/heap/ThreadState.h" | 37 #include "platform/heap/ThreadState.h" |
38 #include "platform/heap/Visitor.h" | 38 #include "platform/heap/Visitor.h" |
39 #include "wtf/HashTraits.h" | 39 #include "wtf/HashTraits.h" |
| 40 #include "wtf/LinkedHashSet.h" |
40 | 41 |
41 #include <gtest/gtest.h> | 42 #include <gtest/gtest.h> |
42 | 43 |
43 namespace WebCore { | 44 namespace WebCore { |
44 | 45 |
45 class ThreadMarker { | 46 class ThreadMarker { |
46 public: | 47 public: |
47 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(
0) { } | 48 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(
0) { } |
48 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i
) { } | 49 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i
) { } |
49 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(rein
terpret_cast<ThreadState*>(-1)), m_num(0) { } | 50 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(rein
terpret_cast<ThreadState*>(-1)), m_num(0) { } |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 unsigned hash() { return IntHash<int>::hash(m_x); } | 303 unsigned hash() { return IntHash<int>::hash(m_x); } |
303 | 304 |
304 protected: | 305 protected: |
305 IntWrapper(int x) : m_x(x) { } | 306 IntWrapper(int x) : m_x(x) { } |
306 | 307 |
307 private: | 308 private: |
308 IntWrapper(); | 309 IntWrapper(); |
309 int m_x; | 310 int m_x; |
310 }; | 311 }; |
311 | 312 |
| 313 class OffHeapInt : public RefCounted<OffHeapInt> { |
| 314 public: |
| 315 static RefPtr<OffHeapInt> create(int x) |
| 316 { |
| 317 return adoptRef(new OffHeapInt(x)); |
| 318 } |
| 319 |
| 320 virtual ~OffHeapInt() |
| 321 { |
| 322 ++s_destructorCalls; |
| 323 } |
| 324 |
| 325 static int s_destructorCalls; |
| 326 |
| 327 int value() const { return m_x; } |
| 328 |
| 329 bool operator==(const OffHeapInt& other) const { return other.value() == val
ue(); } |
| 330 |
| 331 unsigned hash() { return IntHash<int>::hash(m_x); } |
| 332 |
| 333 protected: |
| 334 OffHeapInt(int x) : m_x(x) { } |
| 335 |
| 336 private: |
| 337 OffHeapInt(); |
| 338 int m_x; |
| 339 }; |
| 340 |
312 USED_FROM_MULTIPLE_THREADS(IntWrapper); | 341 USED_FROM_MULTIPLE_THREADS(IntWrapper); |
313 | 342 |
314 int IntWrapper::s_destructorCalls = 0; | 343 int IntWrapper::s_destructorCalls = 0; |
| 344 int OffHeapInt::s_destructorCalls = 0; |
315 | 345 |
316 class ThreadedTesterBase { | 346 class ThreadedTesterBase { |
317 protected: | 347 protected: |
318 static void test(ThreadedTesterBase* tester) | 348 static void test(ThreadedTesterBase* tester) |
319 { | 349 { |
320 for (int i = 0; i < numberOfThreads; i++) | 350 for (int i = 0; i < numberOfThreads; i++) |
321 createThread(&threadFunc, tester, "testing thread"); | 351 createThread(&threadFunc, tester, "testing thread"); |
322 while (tester->m_threadsToFinish) { | 352 while (tester->m_threadsToFinish) { |
323 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); | 353 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); |
324 yield(); | 354 yield(); |
(...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1892 struct ShouldBeTraced { | 1922 struct ShouldBeTraced { |
1893 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { } | 1923 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { } |
1894 void trace(Visitor* visitor) { visitor->trace(m_wrapper); } | 1924 void trace(Visitor* visitor) { visitor->trace(m_wrapper); } |
1895 Member<IntWrapper> m_wrapper; | 1925 Member<IntWrapper> m_wrapper; |
1896 }; | 1926 }; |
1897 | 1927 |
1898 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> { | 1928 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> { |
1899 public: | 1929 public: |
1900 static OffHeapContainer* create() { return new OffHeapContainer(); } | 1930 static OffHeapContainer* create() { return new OffHeapContainer(); } |
1901 | 1931 |
| 1932 static const int iterations = 300; |
| 1933 static const int deadWrappers = 2700; |
| 1934 |
1902 OffHeapContainer() | 1935 OffHeapContainer() |
1903 { | 1936 { |
1904 m_deque1.append(ShouldBeTraced(IntWrapper::create(1))); | 1937 for (int i = 0; i < iterations; i++) { |
1905 m_vector1.append(ShouldBeTraced(IntWrapper::create(2))); | 1938 m_deque1.append(ShouldBeTraced(IntWrapper::create(i))); |
1906 m_deque2.append(IntWrapper::create(3)); | 1939 m_vector1.append(ShouldBeTraced(IntWrapper::create(i))); |
1907 m_vector2.append(IntWrapper::create(4)); | 1940 m_deque2.append(IntWrapper::create(i)); |
1908 m_hashSet.add(IntWrapper::create(5)); | 1941 m_vector2.append(IntWrapper::create(i)); |
1909 m_hashMap.add(this, IntWrapper::create(6)); | 1942 m_hashSet.add(IntWrapper::create(i)); |
1910 m_listHashSet.add(IntWrapper::create(7)); | 1943 m_hashMap.add(i + 103, IntWrapper::create(i)); |
1911 m_ownedVector.append(adoptPtr(new ShouldBeTraced(IntWrapper::create(8)))
); | 1944 m_listHashSet.add(IntWrapper::create(i)); |
| 1945 m_linkedHashSet.add(IntWrapper::create(i)); |
| 1946 m_ownedVector.append(adoptPtr(new ShouldBeTraced(IntWrapper::create(
i)))); |
| 1947 } |
| 1948 |
| 1949 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin()); |
| 1950 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin()); |
| 1951 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin()); |
| 1952 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin()); |
| 1953 HashSet<Member<IntWrapper> >::iterator setIterator(m_hashSet.begin()); |
| 1954 HashMap<int, Member<IntWrapper> >::iterator mapIterator(m_hashMap.begin(
)); |
| 1955 ListHashSet<Member<IntWrapper> >::iterator listSetIterator(m_listHashSet
.begin()); |
| 1956 LinkedHashSet<Member<IntWrapper> >::iterator linkedSetIterator(m_linkedH
ashSet.begin()); |
| 1957 Vector<OwnPtr<ShouldBeTraced> >::iterator ownedVectorIterator(m_ownedVec
tor.begin()); |
| 1958 |
| 1959 for (int i = 0; i < iterations; i++) { |
| 1960 EXPECT_EQ(i, m_vector1[i].m_wrapper->value()); |
| 1961 EXPECT_EQ(i, m_vector2[i]->value()); |
| 1962 EXPECT_EQ(i, d1Iterator->m_wrapper->value()); |
| 1963 EXPECT_EQ(i, v1Iterator->m_wrapper->value()); |
| 1964 EXPECT_EQ(i, d2Iterator->get()->value()); |
| 1965 EXPECT_EQ(i, v2Iterator->get()->value()); |
| 1966 EXPECT_EQ(i, linkedSetIterator->get()->value()); |
| 1967 EXPECT_EQ(i, ownedVectorIterator->get()->m_wrapper->value()); |
| 1968 int value = setIterator->get()->value(); |
| 1969 EXPECT_LE(0, value); |
| 1970 EXPECT_GT(iterations, value); |
| 1971 value = listSetIterator->get()->value(); |
| 1972 EXPECT_LE(0, value); |
| 1973 EXPECT_GT(iterations, value); |
| 1974 value = mapIterator->value.get()->value(); |
| 1975 EXPECT_LE(0, value); |
| 1976 EXPECT_GT(iterations, value); |
| 1977 ++d1Iterator; |
| 1978 ++v1Iterator; |
| 1979 ++d2Iterator; |
| 1980 ++v2Iterator; |
| 1981 ++setIterator; |
| 1982 ++mapIterator; |
| 1983 ++listSetIterator; |
| 1984 ++linkedSetIterator; |
| 1985 ++ownedVectorIterator; |
| 1986 } |
| 1987 EXPECT_EQ(d1Iterator, m_deque1.end()); |
| 1988 EXPECT_EQ(v1Iterator, m_vector1.end()); |
| 1989 EXPECT_EQ(d2Iterator, m_deque2.end()); |
| 1990 EXPECT_EQ(v2Iterator, m_vector2.end()); |
| 1991 EXPECT_EQ(setIterator, m_hashSet.end()); |
| 1992 EXPECT_EQ(mapIterator, m_hashMap.end()); |
| 1993 EXPECT_EQ(listSetIterator, m_listHashSet.end()); |
| 1994 EXPECT_EQ(linkedSetIterator, m_linkedHashSet.end()); |
| 1995 EXPECT_EQ(ownedVectorIterator, m_ownedVector.end()); |
1912 } | 1996 } |
1913 | 1997 |
1914 void trace(Visitor* visitor) | 1998 void trace(Visitor* visitor) |
1915 { | 1999 { |
1916 visitor->trace(m_deque1); | 2000 visitor->trace(m_deque1); |
1917 visitor->trace(m_vector1); | 2001 visitor->trace(m_vector1); |
1918 visitor->trace(m_deque2); | 2002 visitor->trace(m_deque2); |
1919 visitor->trace(m_vector2); | 2003 visitor->trace(m_vector2); |
1920 visitor->trace(m_hashSet); | 2004 visitor->trace(m_hashSet); |
1921 visitor->trace(m_hashMap); | 2005 visitor->trace(m_hashMap); |
1922 visitor->trace(m_listHashSet); | 2006 visitor->trace(m_listHashSet); |
| 2007 visitor->trace(m_linkedHashSet); |
1923 visitor->trace(m_ownedVector); | 2008 visitor->trace(m_ownedVector); |
1924 } | 2009 } |
1925 | 2010 |
1926 Deque<ShouldBeTraced> m_deque1; | 2011 Deque<ShouldBeTraced> m_deque1; |
1927 Vector<ShouldBeTraced> m_vector1; | 2012 Vector<ShouldBeTraced> m_vector1; |
1928 Deque<Member<IntWrapper> > m_deque2; | 2013 Deque<Member<IntWrapper> > m_deque2; |
1929 Vector<Member<IntWrapper> > m_vector2; | 2014 Vector<Member<IntWrapper> > m_vector2; |
1930 HashSet<Member<IntWrapper> > m_hashSet; | 2015 HashSet<Member<IntWrapper> > m_hashSet; |
1931 HashMap<void*, Member<IntWrapper> > m_hashMap; | 2016 HashMap<int, Member<IntWrapper> > m_hashMap; |
1932 ListHashSet<Member<IntWrapper> > m_listHashSet; | 2017 ListHashSet<Member<IntWrapper> > m_listHashSet; |
| 2018 LinkedHashSet<Member<IntWrapper> > m_linkedHashSet; |
1933 Vector<OwnPtr<ShouldBeTraced> > m_ownedVector; | 2019 Vector<OwnPtr<ShouldBeTraced> > m_ownedVector; |
1934 }; | 2020 }; |
1935 | 2021 |
| 2022 const int OffHeapContainer::iterations; |
| 2023 const int OffHeapContainer::deadWrappers; |
1936 | 2024 |
1937 // These class definitions test compile-time asserts with transition | 2025 // These class definitions test compile-time asserts with transition |
1938 // types. They are therefore unused in test code and just need to | 2026 // types. They are therefore unused in test code and just need to |
1939 // compile. This is intentional; do not delete the A and B classes below. | 2027 // compile. This is intentional; do not delete the A and B classes below. |
1940 class A : public WillBeGarbageCollectedMixin { | 2028 class A : public WillBeGarbageCollectedMixin { |
1941 }; | 2029 }; |
1942 | 2030 |
1943 class B : public NoBaseWillBeGarbageCollected<B>, public A { | 2031 class B : public NoBaseWillBeGarbageCollected<B>, public A { |
1944 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B); | 2032 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B); |
1945 public: | 2033 public: |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 keepNumbersAlive[0] = nullptr; | 2467 keepNumbersAlive[0] = nullptr; |
2380 | 2468 |
2381 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 2469 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
2382 | 2470 |
2383 EXPECT_EQ(0u, weakStrong->size()); | 2471 EXPECT_EQ(0u, weakStrong->size()); |
2384 EXPECT_EQ(0u, strongWeak->size()); | 2472 EXPECT_EQ(0u, strongWeak->size()); |
2385 EXPECT_EQ(0u, weakWeak->size()); | 2473 EXPECT_EQ(0u, weakWeak->size()); |
2386 EXPECT_EQ(2u, weakSet->size()); | 2474 EXPECT_EQ(2u, weakSet->size()); |
2387 } | 2475 } |
2388 | 2476 |
| 2477 template<typename Set> |
| 2478 void linkedSetHelper(bool strong) |
| 2479 { |
| 2480 HeapStats initialHeapStats; |
| 2481 clearOutOldGarbage(&initialHeapStats); |
| 2482 IntWrapper::s_destructorCalls = 0; |
| 2483 |
| 2484 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive; |
| 2485 |
| 2486 Persistent<Set> set1 = new Set(); |
| 2487 Persistent<Set> set2 = new Set(); |
| 2488 |
| 2489 const Set& constSet = *set1.get(); |
| 2490 |
| 2491 keepNumbersAlive.append(IntWrapper::create(2)); |
| 2492 keepNumbersAlive.append(IntWrapper::create(103)); |
| 2493 keepNumbersAlive.append(IntWrapper::create(10)); |
| 2494 |
| 2495 set1->add(IntWrapper::create(0)); |
| 2496 set1->add(keepNumbersAlive[0]); |
| 2497 set1->add(keepNumbersAlive[1]); |
| 2498 set1->add(keepNumbersAlive[2]); |
| 2499 |
| 2500 set2->clear(); |
| 2501 set2->add(IntWrapper::create(42)); |
| 2502 set2->clear(); |
| 2503 |
| 2504 EXPECT_EQ(4u, set1->size()); |
| 2505 typename Set::iterator it(set1->begin()); |
| 2506 typename Set::reverse_iterator reverse(set1->rbegin()); |
| 2507 typename Set::const_iterator cit(constSet.begin()); |
| 2508 typename Set::const_reverse_iterator creverse(constSet.rbegin()); |
| 2509 |
| 2510 EXPECT_EQ(0, (*it)->value()); |
| 2511 EXPECT_EQ(0, (*cit)->value()); |
| 2512 ++it; |
| 2513 ++cit; |
| 2514 EXPECT_EQ(2, (*it)->value()); |
| 2515 EXPECT_EQ(2, (*cit)->value()); |
| 2516 --it; |
| 2517 --cit; |
| 2518 EXPECT_EQ(0, (*it)->value()); |
| 2519 EXPECT_EQ(0, (*cit)->value()); |
| 2520 ++it; |
| 2521 ++cit; |
| 2522 ++it; |
| 2523 ++cit; |
| 2524 EXPECT_EQ(103, (*it)->value()); |
| 2525 EXPECT_EQ(103, (*cit)->value()); |
| 2526 ++it; |
| 2527 ++cit; |
| 2528 EXPECT_EQ(10, (*it)->value()); |
| 2529 EXPECT_EQ(10, (*cit)->value()); |
| 2530 ++it; |
| 2531 ++cit; |
| 2532 |
| 2533 EXPECT_EQ(10, (*reverse)->value()); |
| 2534 EXPECT_EQ(10, (*creverse)->value()); |
| 2535 ++reverse; |
| 2536 ++creverse; |
| 2537 EXPECT_EQ(103, (*reverse)->value()); |
| 2538 EXPECT_EQ(103, (*creverse)->value()); |
| 2539 --reverse; |
| 2540 --creverse; |
| 2541 EXPECT_EQ(10, (*reverse)->value()); |
| 2542 EXPECT_EQ(10, (*creverse)->value()); |
| 2543 ++reverse; |
| 2544 ++creverse; |
| 2545 ++reverse; |
| 2546 ++creverse; |
| 2547 EXPECT_EQ(2, (*reverse)->value()); |
| 2548 EXPECT_EQ(2, (*creverse)->value()); |
| 2549 ++reverse; |
| 2550 ++creverse; |
| 2551 EXPECT_EQ(0, (*reverse)->value()); |
| 2552 EXPECT_EQ(0, (*creverse)->value()); |
| 2553 ++reverse; |
| 2554 ++creverse; |
| 2555 |
| 2556 EXPECT_EQ(set1->end(), it); |
| 2557 EXPECT_EQ(constSet.end(), cit); |
| 2558 EXPECT_EQ(set1->rend(), reverse); |
| 2559 EXPECT_EQ(constSet.rend(), creverse); |
| 2560 |
| 2561 typename Set::iterator iX(set2->begin()); |
| 2562 EXPECT_EQ(set2->end(), iX); |
| 2563 |
| 2564 if (strong) |
| 2565 set1->remove(keepNumbersAlive[0]); |
| 2566 |
| 2567 keepNumbersAlive[0] = nullptr; |
| 2568 |
| 2569 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2570 |
| 2571 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size()); |
| 2572 |
| 2573 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls); |
| 2574 |
| 2575 typename Set::iterator i2(set1->begin()); |
| 2576 if (strong) { |
| 2577 EXPECT_EQ(0, (*i2)->value()); |
| 2578 ++i2; |
| 2579 EXPECT_NE(set1->end(), i2); |
| 2580 } |
| 2581 EXPECT_EQ(103, (*i2)->value()); |
| 2582 ++i2; |
| 2583 EXPECT_NE(set1->end(), i2); |
| 2584 EXPECT_EQ(10, (*i2)->value()); |
| 2585 ++i2; |
| 2586 EXPECT_EQ(set1->end(), i2); |
| 2587 } |
| 2588 |
| 2589 TEST(HeapTest, HeapWeakLinkedHashSet) |
| 2590 { |
| 2591 linkedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true); |
| 2592 linkedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false); |
| 2593 } |
| 2594 |
2389 class ThingWithDestructor { | 2595 class ThingWithDestructor { |
2390 public: | 2596 public: |
2391 ThingWithDestructor() | 2597 ThingWithDestructor() |
2392 : m_x(emptyValue) | 2598 : m_x(emptyValue) |
2393 { | 2599 { |
2394 s_liveThingsWithDestructor++; | 2600 s_liveThingsWithDestructor++; |
2395 } | 2601 } |
2396 | 2602 |
2397 ThingWithDestructor(int x) | 2603 ThingWithDestructor(int x) |
2398 : m_x(x) | 2604 : m_x(x) |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3005 TEST(HeapTest, VisitOffHeapCollections) | 3211 TEST(HeapTest, VisitOffHeapCollections) |
3006 { | 3212 { |
3007 HeapStats initialHeapStats; | 3213 HeapStats initialHeapStats; |
3008 clearOutOldGarbage(&initialHeapStats); | 3214 clearOutOldGarbage(&initialHeapStats); |
3009 IntWrapper::s_destructorCalls = 0; | 3215 IntWrapper::s_destructorCalls = 0; |
3010 Persistent<OffHeapContainer> container = OffHeapContainer::create(); | 3216 Persistent<OffHeapContainer> container = OffHeapContainer::create(); |
3011 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3217 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
3012 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 3218 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
3013 container = nullptr; | 3219 container = nullptr; |
3014 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3220 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
3015 EXPECT_EQ(8, IntWrapper::s_destructorCalls); | 3221 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls); |
3016 } | 3222 } |
3017 | 3223 |
3018 TEST(HeapTest, PersistentHeapCollectionTypes) | 3224 TEST(HeapTest, PersistentHeapCollectionTypes) |
3019 { | 3225 { |
3020 HeapStats initialHeapSize; | 3226 HeapStats initialHeapSize; |
3021 IntWrapper::s_destructorCalls = 0; | 3227 IntWrapper::s_destructorCalls = 0; |
3022 | 3228 |
3023 typedef HeapVector<Member<IntWrapper> > Vec; | 3229 typedef HeapVector<Member<IntWrapper> > Vec; |
3024 typedef PersistentHeapVector<Member<IntWrapper> > PVec; | 3230 typedef PersistentHeapVector<Member<IntWrapper> > PVec; |
3025 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; | 3231 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3416 { | 3622 { |
3417 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> >
map; | 3623 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> >
map; |
3418 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor(); | 3624 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor(); |
3419 map.add(hasDestructor, adoptPtr(hasDestructor)); | 3625 map.add(hasDestructor, adoptPtr(hasDestructor)); |
3420 SimpleClassWithDestructor::s_wasDestructed = false; | 3626 SimpleClassWithDestructor::s_wasDestructed = false; |
3421 map.clear(); | 3627 map.clear(); |
3422 ASSERT(SimpleClassWithDestructor::s_wasDestructed); | 3628 ASSERT(SimpleClassWithDestructor::s_wasDestructed); |
3423 } | 3629 } |
3424 | 3630 |
3425 } // WebCore namespace | 3631 } // WebCore namespace |
OLD | NEW |