| 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 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 unsigned hash() { return IntHash<int>::hash(m_x); } | 293 unsigned hash() { return IntHash<int>::hash(m_x); } |
| 293 | 294 |
| 294 protected: | 295 protected: |
| 295 IntWrapper(int x) : m_x(x) { } | 296 IntWrapper(int x) : m_x(x) { } |
| 296 | 297 |
| 297 private: | 298 private: |
| 298 IntWrapper(); | 299 IntWrapper(); |
| 299 int m_x; | 300 int m_x; |
| 300 }; | 301 }; |
| 301 | 302 |
| 303 class OffHeapInt : public RefCounted<OffHeapInt> { |
| 304 public: |
| 305 static RefPtr<OffHeapInt> create(int x) |
| 306 { |
| 307 return adoptRef(new OffHeapInt(x)); |
| 308 } |
| 309 |
| 310 virtual ~OffHeapInt() |
| 311 { |
| 312 ++s_destructorCalls; |
| 313 } |
| 314 |
| 315 static int s_destructorCalls; |
| 316 |
| 317 int value() const { return m_x; } |
| 318 |
| 319 bool operator==(const OffHeapInt& other) const { return other.value() == val
ue(); } |
| 320 |
| 321 unsigned hash() { return IntHash<int>::hash(m_x); } |
| 322 |
| 323 protected: |
| 324 OffHeapInt(int x) : m_x(x) { } |
| 325 |
| 326 private: |
| 327 OffHeapInt(); |
| 328 int m_x; |
| 329 }; |
| 330 |
| 302 USED_FROM_MULTIPLE_THREADS(IntWrapper); | 331 USED_FROM_MULTIPLE_THREADS(IntWrapper); |
| 303 | 332 |
| 304 int IntWrapper::s_destructorCalls = 0; | 333 int IntWrapper::s_destructorCalls = 0; |
| 334 int OffHeapInt::s_destructorCalls = 0; |
| 305 | 335 |
| 306 class ThreadedTesterBase { | 336 class ThreadedTesterBase { |
| 307 protected: | 337 protected: |
| 308 static void test(ThreadedTesterBase* tester) | 338 static void test(ThreadedTesterBase* tester) |
| 309 { | 339 { |
| 310 for (int i = 0; i < numberOfThreads; i++) | 340 for (int i = 0; i < numberOfThreads; i++) |
| 311 createThread(&threadFunc, tester, "testing thread"); | 341 createThread(&threadFunc, tester, "testing thread"); |
| 312 while (tester->m_threadsToFinish) { | 342 while (tester->m_threadsToFinish) { |
| 313 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); | 343 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack
); |
| 314 yield(); | 344 yield(); |
| (...skipping 1559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1874 struct ShouldBeTraced { | 1904 struct ShouldBeTraced { |
| 1875 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { } | 1905 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { } |
| 1876 void trace(Visitor* visitor) { visitor->trace(m_wrapper); } | 1906 void trace(Visitor* visitor) { visitor->trace(m_wrapper); } |
| 1877 Member<IntWrapper> m_wrapper; | 1907 Member<IntWrapper> m_wrapper; |
| 1878 }; | 1908 }; |
| 1879 | 1909 |
| 1880 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> { | 1910 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> { |
| 1881 public: | 1911 public: |
| 1882 static OffHeapContainer* create() { return new OffHeapContainer(); } | 1912 static OffHeapContainer* create() { return new OffHeapContainer(); } |
| 1883 | 1913 |
| 1914 static const int iterations = 300; |
| 1915 static const int deadWrappers = 2400; |
| 1916 |
| 1884 OffHeapContainer() | 1917 OffHeapContainer() |
| 1885 { | 1918 { |
| 1886 m_deque1.append(ShouldBeTraced(IntWrapper::create(1))); | 1919 for (int i = 0; i < iterations; i++) { |
| 1887 m_vector1.append(ShouldBeTraced(IntWrapper::create(2))); | 1920 m_deque1.append(ShouldBeTraced(IntWrapper::create(i))); |
| 1888 m_deque2.append(IntWrapper::create(3)); | 1921 m_vector1.append(ShouldBeTraced(IntWrapper::create(i))); |
| 1889 m_vector2.append(IntWrapper::create(4)); | 1922 m_deque2.append(IntWrapper::create(i)); |
| 1890 m_hashSet.add(IntWrapper::create(5)); | 1923 m_vector2.append(IntWrapper::create(i)); |
| 1891 m_hashMap.add(this, IntWrapper::create(6)); | 1924 m_hashSet.add(IntWrapper::create(i)); |
| 1892 m_listHashSet.add(IntWrapper::create(7)); | 1925 m_hashMap.add(i + 103, IntWrapper::create(i)); |
| 1926 m_listHashSet.add(IntWrapper::create(i)); |
| 1927 m_linkedHashSet.add(IntWrapper::create(i)); |
| 1928 } |
| 1929 |
| 1930 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin()); |
| 1931 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin()); |
| 1932 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin()); |
| 1933 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin()); |
| 1934 HashSet<Member<IntWrapper> >::iterator setIterator(m_hashSet.begin()); |
| 1935 HashMap<int, Member<IntWrapper> >::iterator mapIterator(m_hashMap.begin(
)); |
| 1936 ListHashSet<Member<IntWrapper> >::iterator listSetIterator(m_listHashSet
.begin()); |
| 1937 LinkedHashSet<Member<IntWrapper> >::iterator linkedSetIterator(m_linkedH
ashSet.begin()); |
| 1938 |
| 1939 for (int i = 0; i < iterations; i++) { |
| 1940 EXPECT_EQ(i, m_vector1[i].m_wrapper->value()); |
| 1941 EXPECT_EQ(i, m_vector2[i]->value()); |
| 1942 EXPECT_EQ(i, d1Iterator->m_wrapper->value()); |
| 1943 EXPECT_EQ(i, v1Iterator->m_wrapper->value()); |
| 1944 EXPECT_EQ(i, d2Iterator->get()->value()); |
| 1945 EXPECT_EQ(i, v2Iterator->get()->value()); |
| 1946 EXPECT_EQ(i, linkedSetIterator->get()->value()); |
| 1947 int value = setIterator->get()->value(); |
| 1948 EXPECT_LE(0, value); |
| 1949 EXPECT_GT(iterations, value); |
| 1950 value = listSetIterator->get()->value(); |
| 1951 EXPECT_LE(0, value); |
| 1952 EXPECT_GT(iterations, value); |
| 1953 value = mapIterator->value.get()->value(); |
| 1954 EXPECT_LE(0, value); |
| 1955 EXPECT_GT(iterations, value); |
| 1956 ++d1Iterator; |
| 1957 ++v1Iterator; |
| 1958 ++d2Iterator; |
| 1959 ++v2Iterator; |
| 1960 ++setIterator; |
| 1961 ++mapIterator; |
| 1962 ++listSetIterator; |
| 1963 ++linkedSetIterator; |
| 1964 } |
| 1965 EXPECT_EQ(d1Iterator, m_deque1.end()); |
| 1966 EXPECT_EQ(v1Iterator, m_vector1.end()); |
| 1967 EXPECT_EQ(d2Iterator, m_deque2.end()); |
| 1968 EXPECT_EQ(v2Iterator, m_vector2.end()); |
| 1969 EXPECT_EQ(setIterator, m_hashSet.end()); |
| 1970 EXPECT_EQ(mapIterator, m_hashMap.end()); |
| 1971 EXPECT_EQ(listSetIterator, m_listHashSet.end()); |
| 1972 EXPECT_EQ(linkedSetIterator, m_linkedHashSet.end()); |
| 1893 } | 1973 } |
| 1894 | 1974 |
| 1895 void trace(Visitor* visitor) | 1975 void trace(Visitor* visitor) |
| 1896 { | 1976 { |
| 1897 visitor->trace(m_deque1); | 1977 visitor->trace(m_deque1); |
| 1898 visitor->trace(m_vector1); | 1978 visitor->trace(m_vector1); |
| 1899 visitor->trace(m_deque2); | 1979 visitor->trace(m_deque2); |
| 1900 visitor->trace(m_vector2); | 1980 visitor->trace(m_vector2); |
| 1901 visitor->trace(m_hashSet); | 1981 visitor->trace(m_hashSet); |
| 1902 visitor->trace(m_hashMap); | 1982 visitor->trace(m_hashMap); |
| 1903 visitor->trace(m_listHashSet); | 1983 visitor->trace(m_listHashSet); |
| 1984 visitor->trace(m_linkedHashSet); |
| 1904 } | 1985 } |
| 1905 | 1986 |
| 1906 Deque<ShouldBeTraced> m_deque1; | 1987 Deque<ShouldBeTraced> m_deque1; |
| 1907 Vector<ShouldBeTraced> m_vector1; | 1988 Vector<ShouldBeTraced> m_vector1; |
| 1908 Deque<Member<IntWrapper> > m_deque2; | 1989 Deque<Member<IntWrapper> > m_deque2; |
| 1909 Vector<Member<IntWrapper> > m_vector2; | 1990 Vector<Member<IntWrapper> > m_vector2; |
| 1910 HashSet<Member<IntWrapper> > m_hashSet; | 1991 HashSet<Member<IntWrapper> > m_hashSet; |
| 1911 HashMap<void*, Member<IntWrapper> > m_hashMap; | 1992 HashMap<int, Member<IntWrapper> > m_hashMap; |
| 1912 ListHashSet<Member<IntWrapper> > m_listHashSet; | 1993 ListHashSet<Member<IntWrapper> > m_listHashSet; |
| 1994 LinkedHashSet<Member<IntWrapper> > m_linkedHashSet; |
| 1913 }; | 1995 }; |
| 1914 | 1996 |
| 1997 const int OffHeapContainer::iterations; |
| 1998 const int OffHeapContainer::deadWrappers; |
| 1915 | 1999 |
| 1916 // These class definitions test compile-time asserts with transition | 2000 // These class definitions test compile-time asserts with transition |
| 1917 // types. They are therefore unused in test code and just need to | 2001 // types. They are therefore unused in test code and just need to |
| 1918 // compile. This is intentional; do not delete the A and B classes below. | 2002 // compile. This is intentional; do not delete the A and B classes below. |
| 1919 class A : public WillBeGarbageCollectedMixin { | 2003 class A : public WillBeGarbageCollectedMixin { |
| 1920 }; | 2004 }; |
| 1921 | 2005 |
| 1922 class B : public NoBaseWillBeGarbageCollected<B>, public A { | 2006 class B : public NoBaseWillBeGarbageCollected<B>, public A { |
| 1923 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B); | 2007 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B); |
| 1924 public: | 2008 public: |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2268 keepNumbersAlive[0] = nullptr; | 2352 keepNumbersAlive[0] = nullptr; |
| 2269 | 2353 |
| 2270 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 2354 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2271 | 2355 |
| 2272 EXPECT_EQ(0u, weakStrong->size()); | 2356 EXPECT_EQ(0u, weakStrong->size()); |
| 2273 EXPECT_EQ(0u, strongWeak->size()); | 2357 EXPECT_EQ(0u, strongWeak->size()); |
| 2274 EXPECT_EQ(0u, weakWeak->size()); | 2358 EXPECT_EQ(0u, weakWeak->size()); |
| 2275 EXPECT_EQ(2u, weakSet->size()); | 2359 EXPECT_EQ(2u, weakSet->size()); |
| 2276 } | 2360 } |
| 2277 | 2361 |
| 2362 template<typename Set> |
| 2363 void linkedSetHelper(bool strong) |
| 2364 { |
| 2365 HeapStats initialHeapStats; |
| 2366 clearOutOldGarbage(&initialHeapStats); |
| 2367 IntWrapper::s_destructorCalls = 0; |
| 2368 |
| 2369 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive; |
| 2370 |
| 2371 Persistent<Set> set1 = new Set(); |
| 2372 Persistent<Set> set2 = new Set(); |
| 2373 |
| 2374 const Set& constSet = *set1.get(); |
| 2375 |
| 2376 keepNumbersAlive.append(IntWrapper::create(2)); |
| 2377 keepNumbersAlive.append(IntWrapper::create(103)); |
| 2378 keepNumbersAlive.append(IntWrapper::create(10)); |
| 2379 |
| 2380 set1->add(IntWrapper::create(0)); |
| 2381 set1->add(keepNumbersAlive[0]); |
| 2382 set1->add(keepNumbersAlive[1]); |
| 2383 set1->add(keepNumbersAlive[2]); |
| 2384 |
| 2385 set2->clear(); |
| 2386 set2->add(IntWrapper::create(42)); |
| 2387 set2->clear(); |
| 2388 |
| 2389 EXPECT_EQ(4u, set1->size()); |
| 2390 typename Set::iterator it(set1->begin()); |
| 2391 typename Set::reverse_iterator reverse(set1->rbegin()); |
| 2392 typename Set::const_iterator cit(constSet.begin()); |
| 2393 typename Set::const_reverse_iterator creverse(constSet.rbegin()); |
| 2394 |
| 2395 EXPECT_EQ(0, (*it)->value()); |
| 2396 EXPECT_EQ(0, (*cit)->value()); |
| 2397 ++it; |
| 2398 ++cit; |
| 2399 EXPECT_EQ(2, (*it)->value()); |
| 2400 EXPECT_EQ(2, (*cit)->value()); |
| 2401 --it; |
| 2402 --cit; |
| 2403 EXPECT_EQ(0, (*it)->value()); |
| 2404 EXPECT_EQ(0, (*cit)->value()); |
| 2405 ++it; |
| 2406 ++cit; |
| 2407 ++it; |
| 2408 ++cit; |
| 2409 EXPECT_EQ(103, (*it)->value()); |
| 2410 EXPECT_EQ(103, (*cit)->value()); |
| 2411 ++it; |
| 2412 ++cit; |
| 2413 EXPECT_EQ(10, (*it)->value()); |
| 2414 EXPECT_EQ(10, (*cit)->value()); |
| 2415 ++it; |
| 2416 ++cit; |
| 2417 |
| 2418 EXPECT_EQ(10, (*reverse)->value()); |
| 2419 EXPECT_EQ(10, (*creverse)->value()); |
| 2420 ++reverse; |
| 2421 ++creverse; |
| 2422 EXPECT_EQ(103, (*reverse)->value()); |
| 2423 EXPECT_EQ(103, (*creverse)->value()); |
| 2424 --reverse; |
| 2425 --creverse; |
| 2426 EXPECT_EQ(10, (*reverse)->value()); |
| 2427 EXPECT_EQ(10, (*creverse)->value()); |
| 2428 ++reverse; |
| 2429 ++creverse; |
| 2430 ++reverse; |
| 2431 ++creverse; |
| 2432 EXPECT_EQ(2, (*reverse)->value()); |
| 2433 EXPECT_EQ(2, (*creverse)->value()); |
| 2434 ++reverse; |
| 2435 ++creverse; |
| 2436 EXPECT_EQ(0, (*reverse)->value()); |
| 2437 EXPECT_EQ(0, (*creverse)->value()); |
| 2438 ++reverse; |
| 2439 ++creverse; |
| 2440 |
| 2441 EXPECT_EQ(set1->end(), it); |
| 2442 EXPECT_EQ(constSet.end(), cit); |
| 2443 EXPECT_EQ(set1->rend(), reverse); |
| 2444 EXPECT_EQ(constSet.rend(), creverse); |
| 2445 |
| 2446 typename Set::iterator iX(set2->begin()); |
| 2447 EXPECT_EQ(set2->end(), iX); |
| 2448 |
| 2449 if (strong) |
| 2450 set1->remove(keepNumbersAlive[0]); |
| 2451 |
| 2452 keepNumbersAlive[0] = nullptr; |
| 2453 |
| 2454 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2455 |
| 2456 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size()); |
| 2457 |
| 2458 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls); |
| 2459 |
| 2460 typename Set::iterator i2(set1->begin()); |
| 2461 if (strong) { |
| 2462 EXPECT_EQ(0, (*i2)->value()); |
| 2463 ++i2; |
| 2464 EXPECT_NE(set1->end(), i2); |
| 2465 } |
| 2466 EXPECT_EQ(103, (*i2)->value()); |
| 2467 ++i2; |
| 2468 EXPECT_NE(set1->end(), i2); |
| 2469 EXPECT_EQ(10, (*i2)->value()); |
| 2470 ++i2; |
| 2471 EXPECT_EQ(set1->end(), i2); |
| 2472 } |
| 2473 |
| 2474 TEST(HeapTest, HeapWeakLinkedHashSet) |
| 2475 { |
| 2476 linkedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true); |
| 2477 linkedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false); |
| 2478 } |
| 2479 |
| 2278 class ThingWithDestructor { | 2480 class ThingWithDestructor { |
| 2279 public: | 2481 public: |
| 2280 ThingWithDestructor() | 2482 ThingWithDestructor() |
| 2281 : m_x(emptyValue) | 2483 : m_x(emptyValue) |
| 2282 { | 2484 { |
| 2283 s_liveThingsWithDestructor++; | 2485 s_liveThingsWithDestructor++; |
| 2284 } | 2486 } |
| 2285 | 2487 |
| 2286 ThingWithDestructor(int x) | 2488 ThingWithDestructor(int x) |
| 2287 : m_x(x) | 2489 : m_x(x) |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2894 TEST(HeapTest, VisitOffHeapCollections) | 3096 TEST(HeapTest, VisitOffHeapCollections) |
| 2895 { | 3097 { |
| 2896 HeapStats initialHeapStats; | 3098 HeapStats initialHeapStats; |
| 2897 clearOutOldGarbage(&initialHeapStats); | 3099 clearOutOldGarbage(&initialHeapStats); |
| 2898 IntWrapper::s_destructorCalls = 0; | 3100 IntWrapper::s_destructorCalls = 0; |
| 2899 Persistent<OffHeapContainer> container = OffHeapContainer::create(); | 3101 Persistent<OffHeapContainer> container = OffHeapContainer::create(); |
| 2900 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3102 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2901 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 3103 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
| 2902 container = nullptr; | 3104 container = nullptr; |
| 2903 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); | 3105 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); |
| 2904 EXPECT_EQ(7, IntWrapper::s_destructorCalls); | 3106 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls); |
| 2905 } | 3107 } |
| 2906 | 3108 |
| 2907 TEST(HeapTest, PersistentHeapCollectionTypes) | 3109 TEST(HeapTest, PersistentHeapCollectionTypes) |
| 2908 { | 3110 { |
| 2909 HeapStats initialHeapSize; | 3111 HeapStats initialHeapSize; |
| 2910 IntWrapper::s_destructorCalls = 0; | 3112 IntWrapper::s_destructorCalls = 0; |
| 2911 | 3113 |
| 2912 typedef HeapVector<Member<IntWrapper> > Vec; | 3114 typedef HeapVector<Member<IntWrapper> > Vec; |
| 2913 typedef PersistentHeapVector<Member<IntWrapper> > PVec; | 3115 typedef PersistentHeapVector<Member<IntWrapper> > PVec; |
| 2914 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; | 3116 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3225 { | 3427 { |
| 3226 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> >
map; | 3428 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> >
map; |
| 3227 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor(); | 3429 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor(); |
| 3228 map.add(hasDestructor, adoptPtr(hasDestructor)); | 3430 map.add(hasDestructor, adoptPtr(hasDestructor)); |
| 3229 SimpleClassWithDestructor::s_wasDestructed = false; | 3431 SimpleClassWithDestructor::s_wasDestructed = false; |
| 3230 map.clear(); | 3432 map.clear(); |
| 3231 ASSERT(SimpleClassWithDestructor::s_wasDestructed); | 3433 ASSERT(SimpleClassWithDestructor::s_wasDestructed); |
| 3232 } | 3434 } |
| 3233 | 3435 |
| 3234 } // WebCore namespace | 3436 } // WebCore namespace |
| OLD | NEW |