| 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 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 m_state->heap().resume(); | 298 m_state->heap().resume(); |
| 299 } | 299 } |
| 300 } | 300 } |
| 301 | 301 |
| 302 private: | 302 private: |
| 303 ThreadState* m_state; | 303 ThreadState* m_state; |
| 304 SafePointScope m_safePointScope; | 304 SafePointScope m_safePointScope; |
| 305 bool m_parkedAllThreads; // False if we fail to park all threads | 305 bool m_parkedAllThreads; // False if we fail to park all threads |
| 306 }; | 306 }; |
| 307 | 307 |
| 308 #define DEFINE_VISITOR_METHODS(Type) \ | |
| 309 void mark(const Type* object, TraceCallback callback) override { \ | |
| 310 if (object) \ | |
| 311 m_count++; \ | |
| 312 } \ | |
| 313 bool isMarked(const Type*) override { return false; } \ | |
| 314 bool ensureMarked(const Type* objectPointer) override { \ | |
| 315 return ensureMarked(objectPointer); \ | |
| 316 } | |
| 317 | |
| 318 class CountingVisitor : public Visitor { | |
| 319 public: | |
| 320 explicit CountingVisitor(ThreadState* state) | |
| 321 : Visitor(state, VisitorMarkingMode::ThreadLocalMarking), | |
| 322 m_scope(&state->heap().stackFrameDepth()), | |
| 323 m_count(0) {} | |
| 324 | |
| 325 void mark(const void* object, TraceCallback) override { | |
| 326 if (object) | |
| 327 m_count++; | |
| 328 } | |
| 329 | |
| 330 void markHeader(HeapObjectHeader* header, TraceCallback callback) override { | |
| 331 ASSERT(header->payload()); | |
| 332 m_count++; | |
| 333 } | |
| 334 | |
| 335 void registerDelayedMarkNoTracing(const void*) override {} | |
| 336 void registerWeakMembers(const void*, const void*, WeakCallback) override {} | |
| 337 void registerWeakTable(const void*, | |
| 338 EphemeronCallback, | |
| 339 EphemeronCallback) override {} | |
| 340 #if DCHECK_IS_ON() | |
| 341 bool weakTableRegistered(const void*) override { return false; } | |
| 342 #endif | |
| 343 void registerWeakCellWithCallback(void**, WeakCallback) override {} | |
| 344 bool ensureMarked(const void* objectPointer) override { | |
| 345 if (!objectPointer || | |
| 346 HeapObjectHeader::fromPayload(objectPointer)->isMarked()) | |
| 347 return false; | |
| 348 markNoTracing(objectPointer); | |
| 349 return true; | |
| 350 } | |
| 351 | |
| 352 size_t count() { return m_count; } | |
| 353 void reset() { m_count = 0; } | |
| 354 | |
| 355 private: | |
| 356 StackFrameDepthScope m_scope; | |
| 357 size_t m_count; | |
| 358 }; | |
| 359 | |
| 360 #undef DEFINE_VISITOR_METHODS | |
| 361 | |
| 362 class SimpleObject : public GarbageCollected<SimpleObject> { | 308 class SimpleObject : public GarbageCollected<SimpleObject> { |
| 363 public: | 309 public: |
| 364 static SimpleObject* create() { return new SimpleObject(); } | 310 static SimpleObject* create() { return new SimpleObject(); } |
| 365 DEFINE_INLINE_TRACE() {} | 311 DEFINE_INLINE_TRACE() {} |
| 366 char getPayload(int i) { return payload[i]; } | 312 char getPayload(int i) { return payload[i]; } |
| 367 // This virtual method is unused but it is here to make sure | 313 // This virtual method is unused but it is here to make sure |
| 368 // that this object has a vtable. This object is used | 314 // that this object has a vtable. This object is used |
| 369 // as the super class for objects that also have garbage | 315 // as the super class for objects that also have garbage |
| 370 // collected mixins and having a virtual here makes sure | 316 // collected mixins and having a virtual here makes sure |
| 371 // that adjustment is needed both for marking and for isAlive | 317 // that adjustment is needed both for marking and for isAlive |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 | 959 |
| 1014 private: | 960 private: |
| 1015 RefCountedAndGarbageCollected2() : m_refCount(0) {} | 961 RefCountedAndGarbageCollected2() : m_refCount(0) {} |
| 1016 | 962 |
| 1017 int m_refCount; | 963 int m_refCount; |
| 1018 SelfKeepAlive<RefCountedAndGarbageCollected2> m_keepAlive; | 964 SelfKeepAlive<RefCountedAndGarbageCollected2> m_keepAlive; |
| 1019 }; | 965 }; |
| 1020 | 966 |
| 1021 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; | 967 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; |
| 1022 | 968 |
| 1023 #define DEFINE_VISITOR_METHODS(Type) \ | |
| 1024 void mark(const Type* object, TraceCallback callback) override { \ | |
| 1025 mark(object); \ | |
| 1026 } | |
| 1027 | |
| 1028 class RefCountedGarbageCollectedVisitor : public CountingVisitor { | |
| 1029 public: | |
| 1030 RefCountedGarbageCollectedVisitor(ThreadState* state, | |
| 1031 int expected, | |
| 1032 void** objects) | |
| 1033 : CountingVisitor(state), | |
| 1034 m_count(0), | |
| 1035 m_expectedCount(expected), | |
| 1036 m_expectedObjects(objects) {} | |
| 1037 | |
| 1038 void mark(const void* ptr) { markNoTrace(ptr); } | |
| 1039 | |
| 1040 virtual void markNoTrace(const void* ptr) { | |
| 1041 if (!ptr) | |
| 1042 return; | |
| 1043 if (m_count < m_expectedCount) | |
| 1044 EXPECT_TRUE(expectedObject(ptr)); | |
| 1045 else | |
| 1046 EXPECT_FALSE(expectedObject(ptr)); | |
| 1047 m_count++; | |
| 1048 } | |
| 1049 | |
| 1050 void mark(const void* ptr, TraceCallback) override { mark(ptr); } | |
| 1051 | |
| 1052 void markHeader(HeapObjectHeader* header, TraceCallback callback) override { | |
| 1053 mark(header->payload()); | |
| 1054 } | |
| 1055 | |
| 1056 bool validate() { return m_count >= m_expectedCount; } | |
| 1057 void reset() { m_count = 0; } | |
| 1058 | |
| 1059 private: | |
| 1060 bool expectedObject(const void* ptr) { | |
| 1061 for (int i = 0; i < m_expectedCount; i++) { | |
| 1062 if (m_expectedObjects[i] == ptr) | |
| 1063 return true; | |
| 1064 } | |
| 1065 return false; | |
| 1066 } | |
| 1067 | |
| 1068 int m_count; | |
| 1069 int m_expectedCount; | |
| 1070 void** m_expectedObjects; | |
| 1071 }; | |
| 1072 | |
| 1073 #undef DEFINE_VISITOR_METHODS | |
| 1074 | |
| 1075 class Weak : public Bar { | 969 class Weak : public Bar { |
| 1076 public: | 970 public: |
| 1077 static Weak* create(Bar* strong, Bar* weak) { return new Weak(strong, weak); } | 971 static Weak* create(Bar* strong, Bar* weak) { return new Weak(strong, weak); } |
| 1078 | 972 |
| 1079 DEFINE_INLINE_VIRTUAL_TRACE() { | 973 DEFINE_INLINE_VIRTUAL_TRACE() { |
| 1080 visitor->trace(m_strongBar); | 974 visitor->trace(m_strongBar); |
| 1081 visitor->template registerWeakMembers<Weak, &Weak::zapWeakMembers>(this); | 975 visitor->template registerWeakMembers<Weak, &Weak::zapWeakMembers>(this); |
| 1082 } | 976 } |
| 1083 | 977 |
| 1084 void zapWeakMembers(Visitor* visitor) { | 978 void zapWeakMembers(Visitor* visitor) { |
| (...skipping 2653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3738 // increased to 1. | 3632 // increased to 1. |
| 3739 preciselyCollectGarbage(); | 3633 preciselyCollectGarbage(); |
| 3740 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls); | 3634 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls); |
| 3741 } | 3635 } |
| 3742 // Both persistent handle is gone and ref count is zero so the | 3636 // Both persistent handle is gone and ref count is zero so the |
| 3743 // object can be collected. | 3637 // object can be collected. |
| 3744 preciselyCollectGarbage(); | 3638 preciselyCollectGarbage(); |
| 3745 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls); | 3639 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls); |
| 3746 } | 3640 } |
| 3747 | 3641 |
| 3748 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers) { | |
| 3749 RefCountedAndGarbageCollected::s_destructorCalls = 0; | |
| 3750 RefCountedAndGarbageCollected2::s_destructorCalls = 0; | |
| 3751 { | |
| 3752 RefCountedAndGarbageCollected* pointer1 = 0; | |
| 3753 RefCountedAndGarbageCollected2* pointer2 = 0; | |
| 3754 { | |
| 3755 Persistent<RefCountedAndGarbageCollected> object1 = | |
| 3756 RefCountedAndGarbageCollected::create(); | |
| 3757 Persistent<RefCountedAndGarbageCollected2> object2 = | |
| 3758 RefCountedAndGarbageCollected2::create(); | |
| 3759 pointer1 = object1.get(); | |
| 3760 pointer2 = object2.get(); | |
| 3761 void* objects[2] = {object1.get(), object2.get()}; | |
| 3762 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); | |
| 3763 RefCountedGarbageCollectedVisitor visitor(ThreadState::current(), 2, | |
| 3764 objects); | |
| 3765 ThreadState::current()->visitPersistents(&visitor); | |
| 3766 EXPECT_TRUE(visitor.validate()); | |
| 3767 } | |
| 3768 conservativelyCollectGarbage(); | |
| 3769 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | |
| 3770 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | |
| 3771 | |
| 3772 conservativelyCollectGarbage(); | |
| 3773 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | |
| 3774 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | |
| 3775 | |
| 3776 { | |
| 3777 // At this point, the reference counts of object1 and object2 are 0. | |
| 3778 // Only pointer1 and pointer2 keep references to object1 and object2. | |
| 3779 void* objects[] = {0}; | |
| 3780 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); | |
| 3781 RefCountedGarbageCollectedVisitor visitor(ThreadState::current(), 0, | |
| 3782 objects); | |
| 3783 ThreadState::current()->visitPersistents(&visitor); | |
| 3784 EXPECT_TRUE(visitor.validate()); | |
| 3785 } | |
| 3786 | |
| 3787 { | |
| 3788 Persistent<RefCountedAndGarbageCollected> object1(pointer1); | |
| 3789 Persistent<RefCountedAndGarbageCollected2> object2(pointer2); | |
| 3790 void* objects[2] = {object1.get(), object2.get()}; | |
| 3791 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); | |
| 3792 RefCountedGarbageCollectedVisitor visitor(ThreadState::current(), 2, | |
| 3793 objects); | |
| 3794 ThreadState::current()->visitPersistents(&visitor); | |
| 3795 EXPECT_TRUE(visitor.validate()); | |
| 3796 } | |
| 3797 conservativelyCollectGarbage(); | |
| 3798 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | |
| 3799 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | |
| 3800 | |
| 3801 conservativelyCollectGarbage(); | |
| 3802 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | |
| 3803 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | |
| 3804 } | |
| 3805 | |
| 3806 preciselyCollectGarbage(); | |
| 3807 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls); | |
| 3808 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls); | |
| 3809 } | |
| 3810 | |
| 3811 TEST(HeapTest, WeakMembers) { | 3642 TEST(HeapTest, WeakMembers) { |
| 3812 Bar::s_live = 0; | 3643 Bar::s_live = 0; |
| 3813 { | 3644 { |
| 3814 Persistent<Bar> h1 = Bar::create(); | 3645 Persistent<Bar> h1 = Bar::create(); |
| 3815 Persistent<Weak> h4; | 3646 Persistent<Weak> h4; |
| 3816 Persistent<WithWeakMember> h5; | 3647 Persistent<WithWeakMember> h5; |
| 3817 preciselyCollectGarbage(); | 3648 preciselyCollectGarbage(); |
| 3818 ASSERT_EQ(1u, Bar::s_live); // h1 is live. | 3649 ASSERT_EQ(1u, Bar::s_live); // h1 is live. |
| 3819 { | 3650 { |
| 3820 Bar* h2 = Bar::create(); | 3651 Bar* h2 = Bar::create(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3904 } | 3735 } |
| 3905 | 3736 |
| 3906 TEST(HeapTest, Comparisons) { | 3737 TEST(HeapTest, Comparisons) { |
| 3907 Persistent<Bar> barPersistent = Bar::create(); | 3738 Persistent<Bar> barPersistent = Bar::create(); |
| 3908 Persistent<Foo> fooPersistent = Foo::create(barPersistent); | 3739 Persistent<Foo> fooPersistent = Foo::create(barPersistent); |
| 3909 EXPECT_TRUE(barPersistent != fooPersistent); | 3740 EXPECT_TRUE(barPersistent != fooPersistent); |
| 3910 barPersistent = fooPersistent; | 3741 barPersistent = fooPersistent; |
| 3911 EXPECT_TRUE(barPersistent == fooPersistent); | 3742 EXPECT_TRUE(barPersistent == fooPersistent); |
| 3912 } | 3743 } |
| 3913 | 3744 |
| 3745 #if DCHECK_IS_ON() |
| 3746 namespace { |
| 3747 |
| 3748 static size_t s_checkMarkCount = 0; |
| 3749 |
| 3750 bool reportMarkedPointer(HeapObjectHeader*) { |
| 3751 s_checkMarkCount++; |
| 3752 // Do not try to mark the located heap object. |
| 3753 return true; |
| 3754 } |
| 3755 } |
| 3756 #endif |
| 3757 |
| 3914 TEST(HeapTest, CheckAndMarkPointer) { | 3758 TEST(HeapTest, CheckAndMarkPointer) { |
| 3759 #if DCHECK_IS_ON() |
| 3915 ThreadHeap& heap = ThreadState::current()->heap(); | 3760 ThreadHeap& heap = ThreadState::current()->heap(); |
| 3916 clearOutOldGarbage(); | 3761 clearOutOldGarbage(); |
| 3917 | 3762 |
| 3918 Vector<Address> objectAddresses; | 3763 Vector<Address> objectAddresses; |
| 3919 Vector<Address> endAddresses; | 3764 Vector<Address> endAddresses; |
| 3920 Address largeObjectAddress; | 3765 Address largeObjectAddress; |
| 3921 Address largeObjectEndAddress; | 3766 Address largeObjectEndAddress; |
| 3922 for (int i = 0; i < 10; i++) { | 3767 for (int i = 0; i < 10; i++) { |
| 3923 SimpleObject* object = SimpleObject::create(); | 3768 SimpleObject* object = SimpleObject::create(); |
| 3924 Address objectAddress = reinterpret_cast<Address>(object); | 3769 Address objectAddress = reinterpret_cast<Address>(object); |
| 3925 objectAddresses.push_back(objectAddress); | 3770 objectAddresses.push_back(objectAddress); |
| 3926 endAddresses.push_back(objectAddress + sizeof(SimpleObject) - 1); | 3771 endAddresses.push_back(objectAddress + sizeof(SimpleObject) - 1); |
| 3927 } | 3772 } |
| 3928 LargeHeapObject* largeObject = LargeHeapObject::create(); | 3773 LargeHeapObject* largeObject = LargeHeapObject::create(); |
| 3929 largeObjectAddress = reinterpret_cast<Address>(largeObject); | 3774 largeObjectAddress = reinterpret_cast<Address>(largeObject); |
| 3930 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; | 3775 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; |
| 3931 | 3776 |
| 3932 // This is a low-level test where we call checkAndMarkPointer. This method | 3777 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3933 // causes the object start bitmap to be computed which requires the heap | 3778 // causes the object start bitmap to be computed which requires the heap |
| 3934 // to be in a consistent state (e.g. the free allocation area must be put | 3779 // to be in a consistent state (e.g. the free allocation area must be put |
| 3935 // into a free list header). However when we call makeConsistentForGC it | 3780 // into a free list header). However when we call makeConsistentForGC it |
| 3936 // also clears out the freelists so we have to rebuild those before trying | 3781 // also clears out the freelists so we have to rebuild those before trying |
| 3937 // to allocate anything again. We do this by forcing a GC after doing the | 3782 // to allocate anything again. We do this by forcing a GC after doing the |
| 3938 // checkAndMarkPointer tests. | 3783 // checkAndMarkPointer tests. |
| 3939 { | 3784 { |
| 3940 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3785 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3941 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); | 3786 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); |
| 3942 CountingVisitor visitor(ThreadState::current()); | 3787 Visitor visitor(ThreadState::current(), |
| 3788 VisitorMarkingMode::ThreadLocalMarking); |
| 3943 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not | 3789 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not |
| 3944 // park all threads. | 3790 // park all threads. |
| 3945 heap.flushHeapDoesNotContainCache(); | 3791 heap.flushHeapDoesNotContainCache(); |
| 3946 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3792 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3947 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i])); | 3793 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i], |
| 3948 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i])); | 3794 reportMarkedPointer)); |
| 3795 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i], |
| 3796 reportMarkedPointer)); |
| 3949 } | 3797 } |
| 3950 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3798 EXPECT_EQ(objectAddresses.size() * 2, s_checkMarkCount); |
| 3951 visitor.reset(); | 3799 s_checkMarkCount = 0; |
| 3952 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress)); | 3800 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress, |
| 3953 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress)); | 3801 reportMarkedPointer)); |
| 3954 EXPECT_EQ(2ul, visitor.count()); | 3802 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress, |
| 3955 visitor.reset(); | 3803 reportMarkedPointer)); |
| 3804 EXPECT_EQ(2ul, s_checkMarkCount); |
| 3805 s_checkMarkCount = 0ul; |
| 3956 } | 3806 } |
| 3957 // This forces a GC without stack scanning which results in the objects | 3807 // This forces a GC without stack scanning which results in the objects |
| 3958 // being collected. This will also rebuild the above mentioned freelists, | 3808 // being collected. This will also rebuild the above mentioned freelists, |
| 3959 // however we don't rely on that below since we don't have any allocations. | 3809 // however we don't rely on that below since we don't have any allocations. |
| 3960 clearOutOldGarbage(); | 3810 clearOutOldGarbage(); |
| 3961 { | 3811 { |
| 3962 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3812 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3963 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); | 3813 ThreadState::GCForbiddenScope gcScope(ThreadState::current()); |
| 3964 CountingVisitor visitor(ThreadState::current()); | 3814 Visitor visitor(ThreadState::current(), |
| 3815 VisitorMarkingMode::ThreadLocalMarking); |
| 3965 EXPECT_TRUE(scope.allThreadsParked()); | 3816 EXPECT_TRUE(scope.allThreadsParked()); |
| 3966 heap.flushHeapDoesNotContainCache(); | 3817 heap.flushHeapDoesNotContainCache(); |
| 3967 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3818 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3968 // We would like to assert that checkAndMarkPointer returned false | 3819 // We would like to assert that checkAndMarkPointer returned false |
| 3969 // here because the pointers no longer point into a valid object | 3820 // here because the pointers no longer point into a valid object |
| 3970 // (it's been freed by the GCs. But checkAndMarkPointer will return | 3821 // (it's been freed by the GCs. But checkAndMarkPointer will return |
| 3971 // true for any pointer that points into a heap page, regardless of | 3822 // true for any pointer that points into a heap page, regardless of |
| 3972 // whether it points at a valid object (this ensures the | 3823 // whether it points at a valid object (this ensures the |
| 3973 // correctness of the page-based on-heap address caches), so we | 3824 // correctness of the page-based on-heap address caches), so we |
| 3974 // can't make that assert. | 3825 // can't make that assert. |
| 3975 heap.checkAndMarkPointer(&visitor, objectAddresses[i]); | 3826 heap.checkAndMarkPointer(&visitor, objectAddresses[i], |
| 3976 heap.checkAndMarkPointer(&visitor, endAddresses[i]); | 3827 reportMarkedPointer); |
| 3828 heap.checkAndMarkPointer(&visitor, endAddresses[i], reportMarkedPointer); |
| 3977 } | 3829 } |
| 3978 EXPECT_EQ(0ul, visitor.count()); | 3830 EXPECT_EQ(0ul, s_checkMarkCount); |
| 3979 heap.checkAndMarkPointer(&visitor, largeObjectAddress); | 3831 heap.checkAndMarkPointer(&visitor, largeObjectAddress, reportMarkedPointer); |
| 3980 heap.checkAndMarkPointer(&visitor, largeObjectEndAddress); | 3832 heap.checkAndMarkPointer(&visitor, largeObjectEndAddress, |
| 3981 EXPECT_EQ(0ul, visitor.count()); | 3833 reportMarkedPointer); |
| 3834 EXPECT_EQ(0ul, s_checkMarkCount); |
| 3982 } | 3835 } |
| 3983 // This round of GC is important to make sure that the object start | 3836 // This round of GC is important to make sure that the object start |
| 3984 // bitmap are cleared out and that the free lists are rebuild. | 3837 // bitmap are cleared out and that the free lists are rebuild. |
| 3985 clearOutOldGarbage(); | 3838 clearOutOldGarbage(); |
| 3839 #endif |
| 3986 } | 3840 } |
| 3987 | 3841 |
| 3988 TEST(HeapTest, PersistentHeapCollectionTypes) { | 3842 TEST(HeapTest, PersistentHeapCollectionTypes) { |
| 3989 IntWrapper::s_destructorCalls = 0; | 3843 IntWrapper::s_destructorCalls = 0; |
| 3990 | 3844 |
| 3991 typedef HeapVector<Member<IntWrapper>> Vec; | 3845 typedef HeapVector<Member<IntWrapper>> Vec; |
| 3992 typedef PersistentHeapVector<Member<IntWrapper>> PVec; | 3846 typedef PersistentHeapVector<Member<IntWrapper>> PVec; |
| 3993 typedef PersistentHeapHashSet<Member<IntWrapper>> PSet; | 3847 typedef PersistentHeapHashSet<Member<IntWrapper>> PSet; |
| 3994 typedef PersistentHeapListHashSet<Member<IntWrapper>> PListSet; | 3848 typedef PersistentHeapListHashSet<Member<IntWrapper>> PListSet; |
| 3995 typedef PersistentHeapLinkedHashSet<Member<IntWrapper>> PLinkedSet; | 3849 typedef PersistentHeapLinkedHashSet<Member<IntWrapper>> PLinkedSet; |
| (...skipping 1623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5619 DISALLOW_NEW(); | 5473 DISALLOW_NEW(); |
| 5620 | 5474 |
| 5621 public: | 5475 public: |
| 5622 PartObject() : m_obj(SimpleObject::create()) {} | 5476 PartObject() : m_obj(SimpleObject::create()) {} |
| 5623 DEFINE_INLINE_TRACE() { visitor->trace(m_obj); } | 5477 DEFINE_INLINE_TRACE() { visitor->trace(m_obj); } |
| 5624 | 5478 |
| 5625 private: | 5479 private: |
| 5626 Member<SimpleObject> m_obj; | 5480 Member<SimpleObject> m_obj; |
| 5627 }; | 5481 }; |
| 5628 | 5482 |
| 5629 TEST(HeapTest, TraceIfNeeded) { | |
| 5630 ThreadState::GCForbiddenScope scope(ThreadState::current()); | |
| 5631 CountingVisitor visitor(ThreadState::current()); | |
| 5632 | |
| 5633 { | |
| 5634 TraceIfNeededTester<RefPtr<OffHeapInt>>* m_offHeap = | |
| 5635 TraceIfNeededTester<RefPtr<OffHeapInt>>::create(OffHeapInt::create(42)); | |
| 5636 visitor.reset(); | |
| 5637 m_offHeap->trace(&visitor); | |
| 5638 EXPECT_EQ(0u, visitor.count()); | |
| 5639 } | |
| 5640 | |
| 5641 { | |
| 5642 TraceIfNeededTester<PartObject>* m_part = | |
| 5643 TraceIfNeededTester<PartObject>::create(); | |
| 5644 visitor.reset(); | |
| 5645 m_part->trace(&visitor); | |
| 5646 EXPECT_EQ(1u, visitor.count()); | |
| 5647 } | |
| 5648 | |
| 5649 { | |
| 5650 TraceIfNeededTester<Member<SimpleObject>>* m_obj = | |
| 5651 TraceIfNeededTester<Member<SimpleObject>>::create( | |
| 5652 Member<SimpleObject>(SimpleObject::create())); | |
| 5653 visitor.reset(); | |
| 5654 m_obj->trace(&visitor); | |
| 5655 EXPECT_EQ(1u, visitor.count()); | |
| 5656 } | |
| 5657 | |
| 5658 { | |
| 5659 TraceIfNeededTester<HeapVector<Member<SimpleObject>>>* m_vec = | |
| 5660 TraceIfNeededTester<HeapVector<Member<SimpleObject>>>::create(); | |
| 5661 m_vec->obj().push_back(SimpleObject::create()); | |
| 5662 visitor.reset(); | |
| 5663 m_vec->trace(&visitor); | |
| 5664 EXPECT_EQ(2u, visitor.count()); | |
| 5665 } | |
| 5666 } | |
| 5667 | |
| 5668 class AllocatesOnAssignment { | 5483 class AllocatesOnAssignment { |
| 5669 public: | 5484 public: |
| 5670 AllocatesOnAssignment(std::nullptr_t) : m_value(nullptr) {} | 5485 AllocatesOnAssignment(std::nullptr_t) : m_value(nullptr) {} |
| 5671 AllocatesOnAssignment(int x) : m_value(new IntWrapper(x)) {} | 5486 AllocatesOnAssignment(int x) : m_value(new IntWrapper(x)) {} |
| 5672 AllocatesOnAssignment(IntWrapper* x) : m_value(x) {} | 5487 AllocatesOnAssignment(IntWrapper* x) : m_value(x) {} |
| 5673 | 5488 |
| 5674 AllocatesOnAssignment& operator=(const AllocatesOnAssignment x) { | 5489 AllocatesOnAssignment& operator=(const AllocatesOnAssignment x) { |
| 5675 m_value = x.m_value; | 5490 m_value = x.m_value; |
| 5676 return *this; | 5491 return *this; |
| 5677 } | 5492 } |
| (...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6561 "HeapVector"); | 6376 "HeapVector"); |
| 6562 static_assert( | 6377 static_assert( |
| 6563 WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value, | 6378 WTF::IsGarbageCollectedType<HeapDeque<Member<IntWrapper>>>::value, |
| 6564 "HeapDeque"); | 6379 "HeapDeque"); |
| 6565 static_assert(WTF::IsGarbageCollectedType< | 6380 static_assert(WTF::IsGarbageCollectedType< |
| 6566 HeapTerminatedArray<Member<IntWrapper>>>::value, | 6381 HeapTerminatedArray<Member<IntWrapper>>>::value, |
| 6567 "HeapTerminatedArray"); | 6382 "HeapTerminatedArray"); |
| 6568 } | 6383 } |
| 6569 | 6384 |
| 6570 } // namespace blink | 6385 } // namespace blink |
| OLD | NEW |