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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 friend struct InlinedThingTraits; | 149 friend struct InlinedThingTraits; |
150 }; | 150 }; |
151 | 151 |
152 struct InlinedThingHash { | 152 struct InlinedThingHash { |
153 static unsigned hash(const InlinedThing& key) { return WTF::PtrHash<IntWrapp
er*>::hash(key.m_intWrapper); } | 153 static unsigned hash(const InlinedThing& key) { return WTF::PtrHash<IntWrapp
er*>::hash(key.m_intWrapper); } |
154 static bool equal(const InlinedThing& a, const InlinedThing& b) { return a.m
_intWrapper == b.m_intWrapper; } | 154 static bool equal(const InlinedThing& a, const InlinedThing& b) { return a.m
_intWrapper == b.m_intWrapper; } |
155 static const bool safeToCompareToEmptyOrDeleted = true; | 155 static const bool safeToCompareToEmptyOrDeleted = true; |
156 }; | 156 }; |
157 | 157 |
158 struct InlinedThingTraits : public WTF::GenericHashTraits<InlinedThing> { | 158 struct InlinedThingTraits : public WTF::GenericHashTraits<InlinedThing> { |
159 static const bool needsVisiting = true; | 159 static const bool needsMarking = true; |
160 static const bool emptyValueIsZero = true; | 160 static const bool emptyValueIsZero = true; |
161 static void constructDeletedValue(InlinedThing& slot) { slot.m_intWrapper =
reinterpret_cast<IntWrapper*>(-1); } | 161 static void constructDeletedValue(InlinedThing& slot) { slot.m_intWrapper =
reinterpret_cast<IntWrapper*>(-1); } |
162 static bool isDeletedValue(const InlinedThing& slot) { return slot.m_intWrap
per.raw() == reinterpret_cast<IntWrapper*>(-1); } | 162 static bool isDeletedValue(const InlinedThing& slot) { return slot.m_intWrap
per.raw() == reinterpret_cast<IntWrapper*>(-1); } |
163 }; | 163 }; |
164 | 164 |
165 } // namespace WebCore | 165 } // namespace WebCore |
166 | 166 |
167 namespace WTF { | 167 namespace WTF { |
168 | 168 |
169 template<> | 169 template<> |
170 struct VectorTraits<WebCore::InlinedThing> : public SimpleClassVectorTraits { | 170 struct VectorTraits<WebCore::InlinedThing> : public SimpleClassVectorTraits { |
171 static const bool needsVisiting = true; | 171 static const bool needsMarking = true; |
172 }; | 172 }; |
173 | 173 |
174 } // namespace WTF | 174 } // namespace WTF |
175 | 175 |
176 namespace WebCore { | 176 namespace WebCore { |
177 | 177 |
178 struct IntWrapperTranslator { | 178 struct IntWrapperTranslator { |
179 static unsigned hash(int x) { return IntHash<unsigned>::hash(x); } | 179 static unsigned hash(int x) { return IntHash<unsigned>::hash(x); } |
180 static bool equal(const Member<IntWrapper>& wrapped, int x) { return x == wr
apped->value(); } | 180 static bool equal(const Member<IntWrapper>& wrapped, int x) { return x == wr
apped->value(); } |
181 static void translate(Member<IntWrapper>& dest, int value, unsigned unused) | 181 static void translate(Member<IntWrapper>& dest, int value, unsigned unused) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 | 257 |
258 DEFINE_GC_INFO(RefCountedAndGarbageCollected2); | 258 DEFINE_GC_INFO(RefCountedAndGarbageCollected2); |
259 | 259 |
260 int HeapTestSuperClass::s_destructorCalls = 0; | 260 int HeapTestSuperClass::s_destructorCalls = 0; |
261 int HeapTestSubClass::s_destructorCalls = 0; | 261 int HeapTestSubClass::s_destructorCalls = 0; |
262 int RefCountedAndGarbageCollected::s_destructorCalls = 0; | 262 int RefCountedAndGarbageCollected::s_destructorCalls = 0; |
263 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; | 263 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; |
264 int IntWrapper::s_destructorCalls = 0; | 264 int IntWrapper::s_destructorCalls = 0; |
265 | 265 |
266 #define DEFINE_VISITOR_METHODS(Type) \ | 266 #define DEFINE_VISITOR_METHODS(Type) \ |
267 virtual void visit(const Type* object, TraceCallback callback) \ | 267 virtual void mark(const Type* object, TraceCallback callback) \ |
268 { \ | 268 { \ |
269 if (object) \ | 269 if (object) \ |
270 m_count++; \ | 270 m_count++; \ |
271 } \ | 271 } \ |
272 virtual bool isMarked(const Type*) { return false; } | 272 virtual bool isMarked(const Type*) { return false; } |
273 | 273 |
274 class CountingVisitor : public Visitor { | 274 class CountingVisitor : public Visitor { |
275 public: | 275 public: |
276 CountingVisitor() | 276 CountingVisitor() |
277 : m_count(0) | 277 : m_count(0) |
278 { | 278 { |
279 } | 279 } |
280 | 280 |
281 virtual void visit(const void* object, TraceCallback) | 281 virtual void mark(const void* object, TraceCallback) |
282 { | 282 { |
283 if (object) | 283 if (object) |
284 m_count++; | 284 m_count++; |
285 } | 285 } |
286 | 286 |
287 virtual void visit(HeapObjectHeader* header, TraceCallback callback) | 287 virtual void mark(HeapObjectHeader* header, TraceCallback callback) |
288 { | 288 { |
289 ASSERT(header->payload()); | 289 ASSERT(header->payload()); |
290 m_count++; | 290 m_count++; |
291 } | 291 } |
292 | 292 |
293 virtual void visit(FinalizedHeapObjectHeader* header, TraceCallback callback
) | 293 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) |
294 { | 294 { |
295 ASSERT(header->payload()); | 295 ASSERT(header->payload()); |
296 m_count++; | 296 m_count++; |
297 } | 297 } |
298 | 298 |
299 virtual void registerWeakPointers(const void*, WeakPointerCallback) { } | 299 virtual void registerWeakPointers(const void*, WeakPointerCallback) { } |
300 virtual bool isMarked(const void*) { return false; } | 300 virtual bool isMarked(const void*) { return false; } |
301 | 301 |
302 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) | 302 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS) |
303 | 303 |
304 size_t count() { return m_count; } | 304 size_t count() { return m_count; } |
305 void reset() { m_count = 0; } | 305 void reset() { m_count = 0; } |
306 | 306 |
307 private: | 307 private: |
308 size_t m_count; | 308 size_t m_count; |
309 }; | 309 }; |
310 | 310 |
311 class RefCountedGarbageCollectedVisitor : public CountingVisitor { | 311 class RefCountedGarbageCollectedVisitor : public CountingVisitor { |
312 public: | 312 public: |
313 RefCountedGarbageCollectedVisitor(int expected, void** objects) | 313 RefCountedGarbageCollectedVisitor(int expected, void** objects) |
314 : m_count(0) | 314 : m_count(0) |
315 , m_expectedCount(expected) | 315 , m_expectedCount(expected) |
316 , m_expectedObjects(objects) | 316 , m_expectedObjects(objects) |
317 { | 317 { |
318 } | 318 } |
319 | 319 |
320 void visit(const void* ptr) | 320 void mark(const void* ptr) |
321 { | 321 { |
322 visitNoTrace(ptr); | 322 markNoTrace(ptr); |
323 } | 323 } |
324 | 324 |
325 virtual void visitNoTrace(const void* ptr) | 325 virtual void markNoTrace(const void* ptr) |
326 { | 326 { |
327 if (!ptr) | 327 if (!ptr) |
328 return; | 328 return; |
329 if (m_count < m_expectedCount) | 329 if (m_count < m_expectedCount) |
330 EXPECT_TRUE(expectedObject(ptr)); | 330 EXPECT_TRUE(expectedObject(ptr)); |
331 else | 331 else |
332 EXPECT_FALSE(expectedObject(ptr)); | 332 EXPECT_FALSE(expectedObject(ptr)); |
333 m_count++; | 333 m_count++; |
334 } | 334 } |
335 virtual void visit(const void* ptr, TraceCallback) | 335 virtual void mark(const void* ptr, TraceCallback) |
336 { | 336 { |
337 visit(ptr); | 337 mark(ptr); |
338 } | 338 } |
339 | 339 |
340 virtual void visit(const Node* ptr, TraceCallback callback) | 340 virtual void mark(const Node* ptr, TraceCallback callback) |
341 { | 341 { |
342 visit(ptr); | 342 mark(ptr); |
343 } | 343 } |
344 | 344 |
345 virtual void visit(HeapObjectHeader* header, TraceCallback callback) | 345 virtual void mark(HeapObjectHeader* header, TraceCallback callback) |
346 { | 346 { |
347 visit(header->payload()); | 347 mark(header->payload()); |
348 } | 348 } |
349 | 349 |
350 virtual void visit(FinalizedHeapObjectHeader* header, TraceCallback callback
) | 350 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) |
351 { | 351 { |
352 visit(header->payload()); | 352 mark(header->payload()); |
353 } | 353 } |
354 | 354 |
355 bool validate() { return m_count >= m_expectedCount; } | 355 bool validate() { return m_count >= m_expectedCount; } |
356 void reset() { m_count = 0; } | 356 void reset() { m_count = 0; } |
357 | 357 |
358 private: | 358 private: |
359 bool expectedObject(const void* ptr) | 359 bool expectedObject(const void* ptr) |
360 { | 360 { |
361 for (int i = 0; i < m_expectedCount; i++) { | 361 for (int i = 0; i < m_expectedCount; i++) { |
362 if (m_expectedObjects[i] == ptr) | 362 if (m_expectedObjects[i] == ptr) |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 static void memberTest(); | 632 static void memberTest(); |
633 static void weakOnHeapTest(); | 633 static void weakOnHeapTest(); |
634 static void hashSet(); | 634 static void hashSet(); |
635 static void vectorsOfThings(); | 635 static void vectorsOfThings(); |
636 static void hashSetMembers(); | 636 static void hashSetMembers(); |
637 static void hashMap(); | 637 static void hashMap(); |
638 static void hashMapMembers(); | 638 static void hashMapMembers(); |
639 static void hashMapMembers2(); | 639 static void hashMapMembers2(); |
640 static void hashMapFinalizers(); | 640 static void hashMapFinalizers(); |
641 static void onStackHeapCollections(); | 641 static void onStackHeapCollections(); |
642 static void checkAndVisitPointer(); | 642 static void checkAndMarkPointer(); |
643 static void heapCollectionWithFinalizers(); | 643 static void heapCollectionWithFinalizers(); |
644 static void weakOffHeap(); | 644 static void weakOffHeap(); |
645 static void heapVectorWithInlineCapacity(); | 645 static void heapVectorWithInlineCapacity(); |
646 static void heapCollectionTypes(); | 646 static void heapCollectionTypes(); |
647 static void heapWeakCollectionSimple(); | 647 static void heapWeakCollectionSimple(); |
648 static void heapWeakCollectionTypes(); | 648 static void heapWeakCollectionTypes(); |
649 static void collectionsEmbedded(); | 649 static void collectionsEmbedded(); |
650 static void largeObjects(); | 650 static void largeObjects(); |
651 | 651 |
652 // Do several GCs to make sure that later GCs don't free up old memory from | 652 // Do several GCs to make sure that later GCs don't free up old memory from |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 } | 708 } |
709 | 709 |
710 static Foo* create(Foo* foo) | 710 static Foo* create(Foo* foo) |
711 { | 711 { |
712 return new Foo(foo); | 712 return new Foo(foo); |
713 } | 713 } |
714 | 714 |
715 virtual void trace(Visitor* visitor) | 715 virtual void trace(Visitor* visitor) |
716 { | 716 { |
717 if (m_pointsToFoo) | 717 if (m_pointsToFoo) |
718 visitor->visit(static_cast<Foo*>(m_bar)); | 718 visitor->mark(static_cast<Foo*>(m_bar)); |
719 else | 719 else |
720 visitor->visit(m_bar); | 720 visitor->mark(m_bar); |
721 } | 721 } |
722 | 722 |
723 private: | 723 private: |
724 Foo(Bar* bar) | 724 Foo(Bar* bar) |
725 : Bar() | 725 : Bar() |
726 , m_bar(bar) | 726 , m_bar(bar) |
727 , m_pointsToFoo(false) | 727 , m_pointsToFoo(false) |
728 { | 728 { |
729 } | 729 } |
730 | 730 |
(...skipping 11 matching lines...) Expand all Loading... |
742 class Bars : public Bar { | 742 class Bars : public Bar { |
743 public: | 743 public: |
744 static Bars* create() | 744 static Bars* create() |
745 { | 745 { |
746 return new Bars(); | 746 return new Bars(); |
747 } | 747 } |
748 | 748 |
749 virtual void trace(Visitor* visitor) | 749 virtual void trace(Visitor* visitor) |
750 { | 750 { |
751 for (unsigned i = 0; i < m_width; i++) | 751 for (unsigned i = 0; i < m_width; i++) |
752 visitor->visit(m_bars[i]); | 752 visitor->mark(m_bars[i]); |
753 } | 753 } |
754 | 754 |
755 unsigned getWidth() const | 755 unsigned getWidth() const |
756 { | 756 { |
757 return m_width; | 757 return m_width; |
758 } | 758 } |
759 | 759 |
760 static const unsigned width = 7500; | 760 static const unsigned width = 7500; |
761 private: | 761 private: |
762 Bars() : m_width(0) | 762 Bars() : m_width(0) |
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 { | 1895 { |
1896 m_state->leaveGC(); | 1896 m_state->leaveGC(); |
1897 if (!m_state->isInGC()) | 1897 if (!m_state->isInGC()) |
1898 ThreadState::resumeThreads(); | 1898 ThreadState::resumeThreads(); |
1899 } | 1899 } |
1900 | 1900 |
1901 private: | 1901 private: |
1902 ThreadState* m_state; | 1902 ThreadState* m_state; |
1903 }; | 1903 }; |
1904 | 1904 |
1905 void HeapTester::checkAndVisitPointer() | 1905 void HeapTester::checkAndMarkPointer() |
1906 { | 1906 { |
1907 HeapStats initialHeapStats; | 1907 HeapStats initialHeapStats; |
1908 clearOutOldGarbage(&initialHeapStats); | 1908 clearOutOldGarbage(&initialHeapStats); |
1909 | 1909 |
1910 Vector<Address> objectAddresses; | 1910 Vector<Address> objectAddresses; |
1911 Vector<Address> endAddresses; | 1911 Vector<Address> endAddresses; |
1912 Address largeObjectAddress; | 1912 Address largeObjectAddress; |
1913 Address largeObjectEndAddress; | 1913 Address largeObjectEndAddress; |
1914 CountingVisitor visitor; | 1914 CountingVisitor visitor; |
1915 { | 1915 { |
1916 for (int i = 0; i < 10; i++) { | 1916 for (int i = 0; i < 10; i++) { |
1917 SimpleObject* object = SimpleObject::create(); | 1917 SimpleObject* object = SimpleObject::create(); |
1918 Address objectAddress = reinterpret_cast<Address>(object); | 1918 Address objectAddress = reinterpret_cast<Address>(object); |
1919 objectAddresses.append(objectAddress); | 1919 objectAddresses.append(objectAddress); |
1920 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); | 1920 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); |
1921 } | 1921 } |
1922 LargeObject* largeObject = LargeObject::create(); | 1922 LargeObject* largeObject = LargeObject::create(); |
1923 largeObjectAddress = reinterpret_cast<Address>(largeObject); | 1923 largeObjectAddress = reinterpret_cast<Address>(largeObject); |
1924 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1; | 1924 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1; |
1925 { | 1925 { |
1926 TestGCScope scope; | 1926 TestGCScope scope; |
1927 for (size_t i = 0; i < objectAddresses.size(); i++) { | 1927 for (size_t i = 0; i < objectAddresses.size(); i++) { |
1928 EXPECT_TRUE(Heap::checkAndVisitPointer(&visitor, objectAddresses
[i])); | 1928 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[
i])); |
1929 EXPECT_TRUE(Heap::checkAndVisitPointer(&visitor, endAddresses[i]
)); | 1929 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])
); |
1930 } | 1930 } |
1931 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 1931 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
1932 visitor.reset(); | 1932 visitor.reset(); |
1933 EXPECT_TRUE(Heap::checkAndVisitPointer(&visitor, largeObjectAddress)
); | 1933 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress))
; |
1934 EXPECT_TRUE(Heap::checkAndVisitPointer(&visitor, largeObjectEndAddre
ss)); | 1934 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddres
s)); |
1935 EXPECT_EQ(2ul, visitor.count()); | 1935 EXPECT_EQ(2ul, visitor.count()); |
1936 visitor.reset(); | 1936 visitor.reset(); |
1937 } | 1937 } |
1938 } | 1938 } |
1939 clearOutOldGarbage(&initialHeapStats); | 1939 clearOutOldGarbage(&initialHeapStats); |
1940 { | 1940 { |
1941 TestGCScope scope; | 1941 TestGCScope scope; |
1942 for (size_t i = 0; i < objectAddresses.size(); i++) { | 1942 for (size_t i = 0; i < objectAddresses.size(); i++) { |
1943 EXPECT_FALSE(Heap::checkAndVisitPointer(&visitor, objectAddresses[i]
)); | 1943 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i])
); |
1944 EXPECT_FALSE(Heap::checkAndVisitPointer(&visitor, endAddresses[i])); | 1944 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); |
1945 } | 1945 } |
1946 EXPECT_EQ(0ul, visitor.count()); | 1946 EXPECT_EQ(0ul, visitor.count()); |
1947 EXPECT_FALSE(Heap::checkAndVisitPointer(&visitor, largeObjectAddress)); | 1947 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); |
1948 EXPECT_FALSE(Heap::checkAndVisitPointer(&visitor, largeObjectEndAddress)
); | 1948 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress))
; |
1949 EXPECT_EQ(0ul, visitor.count()); | 1949 EXPECT_EQ(0ul, visitor.count()); |
1950 } | 1950 } |
1951 // This round of GC is important to make sure that the object start | 1951 // This round of GC is important to make sure that the object start |
1952 // bitmap are cleared out. | 1952 // bitmap are cleared out. |
1953 clearOutOldGarbage(&initialHeapStats); | 1953 clearOutOldGarbage(&initialHeapStats); |
1954 } | 1954 } |
1955 | 1955 |
1956 class OffHeapWithDestructor { | 1956 class OffHeapWithDestructor { |
1957 public: | 1957 public: |
1958 OffHeapWithDestructor() : m_x((int*)this) | 1958 OffHeapWithDestructor() : m_x((int*)this) |
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2798 HeapTester::heapWeakCollectionSimple(); | 2798 HeapTester::heapWeakCollectionSimple(); |
2799 } | 2799 } |
2800 | 2800 |
2801 TEST(heap, HeapWeakCollectionTypes) | 2801 TEST(heap, HeapWeakCollectionTypes) |
2802 { | 2802 { |
2803 HeapTester::heapWeakCollectionTypes(); | 2803 HeapTester::heapWeakCollectionTypes(); |
2804 } | 2804 } |
2805 | 2805 |
2806 TEST(heap, CheckAndVisitPointer) | 2806 TEST(heap, CheckAndVisitPointer) |
2807 { | 2807 { |
2808 HeapTester::checkAndVisitPointer(); | 2808 HeapTester::checkAndMarkPointer(); |
2809 } | 2809 } |
2810 | 2810 |
2811 TEST(heap, HeapCollectionWithFinalizers) | 2811 TEST(heap, HeapCollectionWithFinalizers) |
2812 { | 2812 { |
2813 HeapTester::heapCollectionWithFinalizers(); | 2813 HeapTester::heapCollectionWithFinalizers(); |
2814 } | 2814 } |
2815 | 2815 |
2816 } // namespace WebCore | 2816 } // namespace WebCore |
OLD | NEW |