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 |