Line data Source code
1 : // Copyright 2017 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/heap/heap-inl.h"
6 : #include "src/heap/heap-write-barrier-inl.h"
7 : #include "src/heap/spaces-inl.h"
8 : #include "src/isolate.h"
9 : #include "test/unittests/test-utils.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 : using SpacesTest = TestWithIsolate;
15 :
16 15419 : TEST_F(SpacesTest, CompactionSpaceMerge) {
17 : Heap* heap = i_isolate()->heap();
18 : OldSpace* old_space = heap->old_space();
19 2 : EXPECT_TRUE(old_space != nullptr);
20 :
21 : CompactionSpace* compaction_space =
22 : new CompactionSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
23 2 : EXPECT_TRUE(compaction_space != nullptr);
24 :
25 2 : for (Page* p : *old_space) {
26 : // Unlink free lists from the main space to avoid reusing the memory for
27 : // compaction spaces.
28 : old_space->UnlinkFreeListCategories(p);
29 : }
30 :
31 : // Cannot loop until "Available()" since we initially have 0 bytes available
32 : // and would thus neither grow, nor be able to allocate an object.
33 : const int kNumObjects = 10;
34 : const int kNumObjectsPerPage =
35 1 : compaction_space->AreaSize() / kMaxRegularHeapObjectSize;
36 : const int kExpectedPages =
37 1 : (kNumObjects + kNumObjectsPerPage - 1) / kNumObjectsPerPage;
38 21 : for (int i = 0; i < kNumObjects; i++) {
39 : HeapObject object =
40 20 : compaction_space->AllocateRawUnaligned(kMaxRegularHeapObjectSize)
41 : .ToObjectChecked();
42 : heap->CreateFillerObjectAt(object->address(), kMaxRegularHeapObjectSize,
43 10 : ClearRecordedSlots::kNo);
44 : }
45 1 : int pages_in_old_space = old_space->CountTotalPages();
46 1 : int pages_in_compaction_space = compaction_space->CountTotalPages();
47 1 : EXPECT_EQ(kExpectedPages, pages_in_compaction_space);
48 1 : old_space->MergeCompactionSpace(compaction_space);
49 2 : EXPECT_EQ(pages_in_old_space + pages_in_compaction_space,
50 0 : old_space->CountTotalPages());
51 :
52 1 : delete compaction_space;
53 1 : }
54 :
55 15419 : TEST_F(SpacesTest, WriteBarrierFromHeapObject) {
56 : constexpr Address address1 = Page::kPageSize;
57 : HeapObject object1 = HeapObject::unchecked_cast(Object(address1));
58 : MemoryChunk* chunk1 = MemoryChunk::FromHeapObject(object1);
59 : heap_internals::MemoryChunk* slim_chunk1 =
60 : heap_internals::MemoryChunk::FromHeapObject(object1);
61 2 : EXPECT_EQ(static_cast<void*>(chunk1), static_cast<void*>(slim_chunk1));
62 : constexpr Address address2 = 2 * Page::kPageSize - 1;
63 : HeapObject object2 = HeapObject::unchecked_cast(Object(address2));
64 : MemoryChunk* chunk2 = MemoryChunk::FromHeapObject(object2);
65 : heap_internals::MemoryChunk* slim_chunk2 =
66 : heap_internals::MemoryChunk::FromHeapObject(object2);
67 2 : EXPECT_EQ(static_cast<void*>(chunk2), static_cast<void*>(slim_chunk2));
68 1 : }
69 :
70 15419 : TEST_F(SpacesTest, WriteBarrierIsMarking) {
71 : const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
72 : char memory[kSizeOfMemoryChunk];
73 : memset(&memory, 0, kSizeOfMemoryChunk);
74 : MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
75 : heap_internals::MemoryChunk* slim_chunk =
76 : reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
77 : EXPECT_FALSE(chunk->IsFlagSet(MemoryChunk::INCREMENTAL_MARKING));
78 1 : EXPECT_FALSE(slim_chunk->IsMarking());
79 : chunk->SetFlag(MemoryChunk::INCREMENTAL_MARKING);
80 : EXPECT_TRUE(chunk->IsFlagSet(MemoryChunk::INCREMENTAL_MARKING));
81 1 : EXPECT_TRUE(slim_chunk->IsMarking());
82 : chunk->ClearFlag(MemoryChunk::INCREMENTAL_MARKING);
83 : EXPECT_FALSE(chunk->IsFlagSet(MemoryChunk::INCREMENTAL_MARKING));
84 2 : EXPECT_FALSE(slim_chunk->IsMarking());
85 1 : }
86 :
87 15419 : TEST_F(SpacesTest, WriteBarrierInYoungGenerationToSpace) {
88 : const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
89 : char memory[kSizeOfMemoryChunk];
90 : memset(&memory, 0, kSizeOfMemoryChunk);
91 : MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
92 : heap_internals::MemoryChunk* slim_chunk =
93 : reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
94 : EXPECT_FALSE(chunk->InYoungGeneration());
95 2 : EXPECT_FALSE(slim_chunk->InYoungGeneration());
96 : chunk->SetFlag(MemoryChunk::TO_PAGE);
97 : EXPECT_TRUE(chunk->InYoungGeneration());
98 1 : EXPECT_TRUE(slim_chunk->InYoungGeneration());
99 : chunk->ClearFlag(MemoryChunk::TO_PAGE);
100 : EXPECT_FALSE(chunk->InYoungGeneration());
101 2 : EXPECT_FALSE(slim_chunk->InYoungGeneration());
102 1 : }
103 :
104 15419 : TEST_F(SpacesTest, WriteBarrierInYoungGenerationFromSpace) {
105 : const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
106 : char memory[kSizeOfMemoryChunk];
107 : memset(&memory, 0, kSizeOfMemoryChunk);
108 : MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
109 : heap_internals::MemoryChunk* slim_chunk =
110 : reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
111 : EXPECT_FALSE(chunk->InYoungGeneration());
112 2 : EXPECT_FALSE(slim_chunk->InYoungGeneration());
113 : chunk->SetFlag(MemoryChunk::FROM_PAGE);
114 : EXPECT_TRUE(chunk->InYoungGeneration());
115 1 : EXPECT_TRUE(slim_chunk->InYoungGeneration());
116 : chunk->ClearFlag(MemoryChunk::FROM_PAGE);
117 : EXPECT_FALSE(chunk->InYoungGeneration());
118 2 : EXPECT_FALSE(slim_chunk->InYoungGeneration());
119 1 : }
120 :
121 15419 : TEST_F(SpacesTest, CodeRangeAddressReuse) {
122 : CodeRangeAddressHint hint;
123 : // Create code ranges.
124 1 : Address code_range1 = hint.GetAddressHint(100);
125 1 : Address code_range2 = hint.GetAddressHint(200);
126 1 : Address code_range3 = hint.GetAddressHint(100);
127 :
128 : // Since the addresses are random, we cannot check that they are different.
129 :
130 : // Free two code ranges.
131 1 : hint.NotifyFreedCodeRange(code_range1, 100);
132 1 : hint.NotifyFreedCodeRange(code_range2, 200);
133 :
134 : // The next two code ranges should reuse the freed addresses.
135 1 : Address code_range4 = hint.GetAddressHint(100);
136 1 : EXPECT_EQ(code_range4, code_range1);
137 1 : Address code_range5 = hint.GetAddressHint(200);
138 1 : EXPECT_EQ(code_range5, code_range2);
139 :
140 : // Free the third code range and check address reuse.
141 1 : hint.NotifyFreedCodeRange(code_range3, 100);
142 1 : Address code_range6 = hint.GetAddressHint(100);
143 1 : EXPECT_EQ(code_range6, code_range3);
144 1 : }
145 :
146 : } // namespace internal
147 9249 : } // namespace v8
|