| 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 |