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 3869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3880 VectorObjectNoTrace n1, n2; | 3880 VectorObjectNoTrace n1, n2; |
3881 dequeNoTrace.append(n1); | 3881 dequeNoTrace.append(n1); |
3882 dequeNoTrace.append(n2); | 3882 dequeNoTrace.append(n2); |
3883 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GC
WithSweep, Heap::ForcedGC); | 3883 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GC
WithSweep, Heap::ForcedGC); |
3884 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls); | 3884 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls); |
3885 } | 3885 } |
3886 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); | 3886 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); |
3887 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls); | 3887 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls); |
3888 } | 3888 } |
3889 | 3889 |
| 3890 class InlinedVectorObject { |
| 3891 ALLOW_ONLY_INLINE_ALLOCATION(); |
| 3892 public: |
| 3893 InlinedVectorObject() |
| 3894 { |
| 3895 } |
| 3896 ~InlinedVectorObject() |
| 3897 { |
| 3898 s_destructorCalls++; |
| 3899 } |
| 3900 DEFINE_INLINE_TRACE() |
| 3901 { |
| 3902 } |
| 3903 |
| 3904 static int s_destructorCalls; |
| 3905 }; |
| 3906 |
| 3907 int InlinedVectorObject::s_destructorCalls = 0; |
| 3908 |
| 3909 } // namespace blink |
| 3910 |
| 3911 WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(blink::InlinedVectorObject); |
| 3912 |
| 3913 namespace blink { |
| 3914 |
| 3915 class InlinedVectorObjectWrapper final : public GarbageCollectedFinalized<Inline
dVectorObjectWrapper> { |
| 3916 public: |
| 3917 InlinedVectorObjectWrapper() |
| 3918 { |
| 3919 InlinedVectorObject i1, i2; |
| 3920 m_vector1.append(i1); |
| 3921 m_vector1.append(i2); |
| 3922 m_vector2.append(i1); |
| 3923 m_vector2.append(i2); // This allocates an out-of-line buffer. |
| 3924 m_vector3.append(i1); |
| 3925 m_vector3.append(i2); |
| 3926 } |
| 3927 |
| 3928 DEFINE_INLINE_TRACE() |
| 3929 { |
| 3930 visitor->trace(m_vector1); |
| 3931 visitor->trace(m_vector2); |
| 3932 visitor->trace(m_vector3); |
| 3933 } |
| 3934 |
| 3935 private: |
| 3936 HeapVector<InlinedVectorObject> m_vector1; |
| 3937 HeapVector<InlinedVectorObject, 1> m_vector2; |
| 3938 HeapVector<InlinedVectorObject, 2> m_vector3; |
| 3939 }; |
| 3940 |
| 3941 TEST(HeapTest, VectorDestructors) |
| 3942 { |
| 3943 clearOutOldGarbage(); |
| 3944 InlinedVectorObject::s_destructorCalls = 0; |
| 3945 { |
| 3946 HeapVector<InlinedVectorObject> vector; |
| 3947 InlinedVectorObject i1, i2; |
| 3948 vector.append(i1); |
| 3949 vector.append(i2); |
| 3950 } |
| 3951 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); |
| 3952 // This is not EXPECT_EQ but EXPECT_LE because a HeapVectorBacking calls |
| 3953 // destructors for all elements in (not the size but) the capacity of |
| 3954 // the vector. Thus the number of destructors called becomes larger |
| 3955 // than the actual number of objects in the vector. |
| 3956 EXPECT_LE(4, InlinedVectorObject::s_destructorCalls); |
| 3957 |
| 3958 InlinedVectorObject::s_destructorCalls = 0; |
| 3959 { |
| 3960 HeapVector<InlinedVectorObject, 1> vector; |
| 3961 InlinedVectorObject i1, i2; |
| 3962 vector.append(i1); |
| 3963 vector.append(i2); // This allocates an out-of-line buffer. |
| 3964 } |
| 3965 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); |
| 3966 EXPECT_LE(4, InlinedVectorObject::s_destructorCalls); |
| 3967 |
| 3968 InlinedVectorObject::s_destructorCalls = 0; |
| 3969 { |
| 3970 HeapVector<InlinedVectorObject, 2> vector; |
| 3971 InlinedVectorObject i1, i2; |
| 3972 vector.append(i1); |
| 3973 vector.append(i2); |
| 3974 } |
| 3975 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); |
| 3976 EXPECT_LE(4, InlinedVectorObject::s_destructorCalls); |
| 3977 |
| 3978 InlinedVectorObject::s_destructorCalls = 0; |
| 3979 { |
| 3980 new InlinedVectorObjectWrapper(); |
| 3981 Heap::collectGarbage(ThreadState::HeapPointersOnStack, ThreadState::GCWi
thSweep, Heap::ForcedGC); |
| 3982 EXPECT_EQ(2, InlinedVectorObject::s_destructorCalls); |
| 3983 } |
| 3984 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::GCWith
Sweep, Heap::ForcedGC); |
| 3985 EXPECT_LE(8, InlinedVectorObject::s_destructorCalls); |
| 3986 } |
| 3987 |
3890 template<typename Set> | 3988 template<typename Set> |
3891 void rawPtrInHashHelper() | 3989 void rawPtrInHashHelper() |
3892 { | 3990 { |
3893 Set set; | 3991 Set set; |
3894 set.add(new int(42)); | 3992 set.add(new int(42)); |
3895 set.add(new int(42)); | 3993 set.add(new int(42)); |
3896 EXPECT_EQ(2u, set.size()); | 3994 EXPECT_EQ(2u, set.size()); |
3897 for (typename Set::iterator it = set.begin(); it != set.end(); ++it) { | 3995 for (typename Set::iterator it = set.begin(); it != set.end(); ++it) { |
3898 EXPECT_EQ(42, **it); | 3996 EXPECT_EQ(42, **it); |
3899 delete *it; | 3997 delete *it; |
(...skipping 1648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5548 // of the old buffer to both ends of the expanded buffer, along with | 5646 // of the old buffer to both ends of the expanded buffer, along with |
5549 // re-adjusting both start&end indices in terms of that expanded buffer. | 5647 // re-adjusting both start&end indices in terms of that expanded buffer. |
5550 EXPECT_EQ(80u, deque->size()); | 5648 EXPECT_EQ(80u, deque->size()); |
5551 i = 0; | 5649 i = 0; |
5552 for (const auto& intWrapper : *deque) { | 5650 for (const auto& intWrapper : *deque) { |
5553 EXPECT_EQ(i + 50, intWrapper->value()); | 5651 EXPECT_EQ(i + 50, intWrapper->value()); |
5554 i++; | 5652 i++; |
5555 } | 5653 } |
5556 } | 5654 } |
5557 | 5655 |
| 5656 class SimpleRefValue : public RefCounted<SimpleRefValue> { |
| 5657 public: |
| 5658 static PassRefPtr<SimpleRefValue> create(int i) |
| 5659 { |
| 5660 return adoptRef(new SimpleRefValue(i)); |
| 5661 } |
| 5662 |
| 5663 int value() const { return m_value; } |
| 5664 private: |
| 5665 explicit SimpleRefValue(int value) |
| 5666 : m_value(value) |
| 5667 { |
| 5668 } |
| 5669 |
| 5670 int m_value; |
| 5671 }; |
| 5672 |
| 5673 class PartObjectWithRef { |
| 5674 ALLOW_ONLY_INLINE_ALLOCATION(); |
| 5675 public: |
| 5676 PartObjectWithRef(int i) |
| 5677 : m_value(SimpleRefValue::create(i)) |
| 5678 { |
| 5679 } |
| 5680 |
| 5681 int value() const { return m_value->value(); } |
| 5682 |
| 5683 private: |
| 5684 RefPtr<SimpleRefValue> m_value; |
| 5685 }; |
| 5686 |
| 5687 } // namespace blink |
| 5688 |
| 5689 WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::PartObjectWithRef); |
| 5690 |
| 5691 namespace blink { |
| 5692 |
| 5693 TEST(HeapTest, DequePartObjectsExpand) |
| 5694 { |
| 5695 // Test expansion of HeapDeque<PartObject> |
| 5696 |
| 5697 using PartDeque = HeapDeque<PartObjectWithRef>; |
| 5698 |
| 5699 Persistent<PartDeque> deque = new PartDeque(); |
| 5700 // Auxillary Deque used to prevent 'inline' buffer expansion. |
| 5701 Persistent<PartDeque> dequeUnused = new PartDeque(); |
| 5702 |
| 5703 // Append a sequence, bringing about repeated expansions of the |
| 5704 // deque's buffer. |
| 5705 int i = 0; |
| 5706 for (; i < 60; ++i) { |
| 5707 deque->append(PartObjectWithRef(i)); |
| 5708 dequeUnused->append(PartObjectWithRef(i)); |
| 5709 } |
| 5710 |
| 5711 EXPECT_EQ(60u, deque->size()); |
| 5712 i = 0; |
| 5713 for (const PartObjectWithRef& part : *deque) { |
| 5714 EXPECT_EQ(i, part.value()); |
| 5715 i++; |
| 5716 } |
| 5717 |
| 5718 // Remove most of the queued objects and have the buffer's start index |
| 5719 // 'point' somewhere into the buffer, just behind the end index. |
| 5720 for (i = 0; i < 50; ++i) |
| 5721 deque->takeFirst(); |
| 5722 |
| 5723 EXPECT_EQ(10u, deque->size()); |
| 5724 i = 0; |
| 5725 for (const PartObjectWithRef& part : *deque) { |
| 5726 EXPECT_EQ(50 + i, part.value()); |
| 5727 i++; |
| 5728 } |
| 5729 |
| 5730 // Append even more, eventually causing an expansion of the underlying |
| 5731 // buffer once the end index wraps around and reaches the start index. |
| 5732 for (i = 0; i < 70; ++i) |
| 5733 deque->append(PartObjectWithRef(60 + i)); |
| 5734 |
| 5735 // Verify that the final buffer expansion copied the start and end segments |
| 5736 // of the old buffer to both ends of the expanded buffer, along with |
| 5737 // re-adjusting both start&end indices in terms of that expanded buffer. |
| 5738 EXPECT_EQ(80u, deque->size()); |
| 5739 i = 0; |
| 5740 for (const PartObjectWithRef& part : *deque) { |
| 5741 EXPECT_EQ(i + 50, part.value()); |
| 5742 i++; |
| 5743 } |
| 5744 |
| 5745 for (i = 0; i < 70; ++i) |
| 5746 deque->append(PartObjectWithRef(130 + i)); |
| 5747 |
| 5748 EXPECT_EQ(150u, deque->size()); |
| 5749 i = 0; |
| 5750 for (const PartObjectWithRef& part : *deque) { |
| 5751 EXPECT_EQ(i + 50, part.value()); |
| 5752 i++; |
| 5753 } |
| 5754 } |
| 5755 |
| 5756 TEST(HeapTest, HeapVectorPartObjects) |
| 5757 { |
| 5758 HeapVector<PartObjectWithRef> vector1; |
| 5759 HeapVector<PartObjectWithRef> vector2; |
| 5760 |
| 5761 for (int i = 0; i < 10; ++i) { |
| 5762 vector1.append(PartObjectWithRef(i)); |
| 5763 vector2.append(PartObjectWithRef(i)); |
| 5764 } |
| 5765 |
| 5766 vector1.reserveCapacity(150); |
| 5767 EXPECT_EQ(150u, vector1.capacity()); |
| 5768 EXPECT_EQ(10u, vector1.size()); |
| 5769 |
| 5770 vector2.reserveCapacity(100); |
| 5771 EXPECT_EQ(100u, vector2.capacity()); |
| 5772 EXPECT_EQ(10u, vector2.size()); |
| 5773 |
| 5774 for (int i = 0; i < 4; ++i) { |
| 5775 vector1.append(PartObjectWithRef(10 + i)); |
| 5776 vector2.append(PartObjectWithRef(10 + i)); |
| 5777 vector2.append(PartObjectWithRef(10 + i)); |
| 5778 } |
| 5779 |
| 5780 // Shrinking heap vector backing stores always succeeds, |
| 5781 // so these two will not currently exercise the code path |
| 5782 // where shrinking causes copying into a new, small buffer. |
| 5783 vector2.shrinkToReasonableCapacity(); |
| 5784 EXPECT_EQ(18u, vector2.size()); |
| 5785 |
| 5786 vector1.shrinkToReasonableCapacity(); |
| 5787 EXPECT_EQ(14u, vector1.size()); |
| 5788 } |
| 5789 |
5558 namespace { | 5790 namespace { |
5559 | 5791 |
5560 enum GrowthDirection { | 5792 enum GrowthDirection { |
5561 GrowsTowardsHigher, | 5793 GrowsTowardsHigher, |
5562 GrowsTowardsLower, | 5794 GrowsTowardsLower, |
5563 }; | 5795 }; |
5564 | 5796 |
5565 NEVER_INLINE NO_SANITIZE_ADDRESS GrowthDirection stackGrowthDirection() | 5797 NEVER_INLINE NO_SANITIZE_ADDRESS GrowthDirection stackGrowthDirection() |
5566 { | 5798 { |
5567 // Disable ASan, otherwise its stack checking (use-after-return) will | 5799 // Disable ASan, otherwise its stack checking (use-after-return) will |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5692 { | 5924 { |
5693 Persistent<ClassWithMember> object = ClassWithMember::create(); | 5925 Persistent<ClassWithMember> object = ClassWithMember::create(); |
5694 EXPECT_EQ(0, object->traceCount()); | 5926 EXPECT_EQ(0, object->traceCount()); |
5695 TestMixinAllocatingObject* mixin = TestMixinAllocatingObject::create(object.
get()); | 5927 TestMixinAllocatingObject* mixin = TestMixinAllocatingObject::create(object.
get()); |
5696 EXPECT_TRUE(mixin); | 5928 EXPECT_TRUE(mixin); |
5697 EXPECT_GT(object->traceCount(), 0); | 5929 EXPECT_GT(object->traceCount(), 0); |
5698 EXPECT_GT(mixin->traceCount(), 0); | 5930 EXPECT_GT(mixin->traceCount(), 0); |
5699 } | 5931 } |
5700 | 5932 |
5701 } // namespace blink | 5933 } // namespace blink |
OLD | NEW |