OLD | NEW |
| (Empty) |
1 // Copyright 2015 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/slots-buffer.h" | |
6 | |
7 #include "src/assembler.h" | |
8 #include "src/heap/heap.h" | |
9 #include "src/objects-inl.h" | |
10 | |
11 namespace v8 { | |
12 namespace internal { | |
13 | |
14 bool SlotsBuffer::IsTypedSlot(ObjectSlot slot) { | |
15 return reinterpret_cast<uintptr_t>(slot) < NUMBER_OF_SLOT_TYPES; | |
16 } | |
17 | |
18 | |
19 bool SlotsBuffer::AddTo(SlotsBufferAllocator* allocator, | |
20 SlotsBuffer** buffer_address, SlotType type, | |
21 Address addr, AdditionMode mode) { | |
22 SlotsBuffer* buffer = *buffer_address; | |
23 if (buffer == NULL || !buffer->HasSpaceForTypedSlot()) { | |
24 if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) { | |
25 allocator->DeallocateChain(buffer_address); | |
26 return false; | |
27 } | |
28 buffer = allocator->AllocateBuffer(buffer); | |
29 *buffer_address = buffer; | |
30 } | |
31 DCHECK(buffer->HasSpaceForTypedSlot()); | |
32 buffer->Add(reinterpret_cast<ObjectSlot>(type)); | |
33 buffer->Add(reinterpret_cast<ObjectSlot>(addr)); | |
34 return true; | |
35 } | |
36 | |
37 | |
38 void SlotsBuffer::RemoveInvalidSlots(Heap* heap, SlotsBuffer* buffer) { | |
39 // Remove entries by replacing them with an old-space slot containing a smi | |
40 // that is located in an unmovable page. | |
41 const ObjectSlot kRemovedEntry = HeapObject::RawField( | |
42 heap->empty_fixed_array(), FixedArrayBase::kLengthOffset); | |
43 DCHECK(Page::FromAddress(reinterpret_cast<Address>(kRemovedEntry)) | |
44 ->NeverEvacuate()); | |
45 | |
46 while (buffer != NULL) { | |
47 SlotsBuffer::ObjectSlot* slots = buffer->slots_; | |
48 intptr_t slots_count = buffer->idx_; | |
49 | |
50 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) { | |
51 ObjectSlot slot = slots[slot_idx]; | |
52 if (!IsTypedSlot(slot)) { | |
53 Object* object = *slot; | |
54 // Slots are invalid when they currently: | |
55 // - do not point to a heap object (SMI) | |
56 // - point to a heap object in new space | |
57 // - are not within a live heap object on a valid pointer slot | |
58 // - point to a heap object not on an evacuation candidate | |
59 // TODO(mlippautz): Move InNewSpace check above IsSlotInLiveObject once | |
60 // we filter out unboxed double slots eagerly. | |
61 if (!object->IsHeapObject() || | |
62 !heap->mark_compact_collector()->IsSlotInLiveObject( | |
63 reinterpret_cast<Address>(slot)) || | |
64 heap->InNewSpace(object) || | |
65 !Page::FromAddress(reinterpret_cast<Address>(object)) | |
66 ->IsEvacuationCandidate()) { | |
67 // TODO(hpayer): Instead of replacing slots with kRemovedEntry we | |
68 // could shrink the slots buffer in-place. | |
69 slots[slot_idx] = kRemovedEntry; | |
70 } | |
71 } else { | |
72 ++slot_idx; | |
73 DCHECK(slot_idx < slots_count); | |
74 } | |
75 } | |
76 buffer = buffer->next(); | |
77 } | |
78 } | |
79 | |
80 | |
81 void SlotsBuffer::RemoveObjectSlots(Heap* heap, SlotsBuffer* buffer, | |
82 Address start_slot, Address end_slot) { | |
83 // Remove entries by replacing them with an old-space slot containing a smi | |
84 // that is located in an unmovable page. | |
85 const ObjectSlot kRemovedEntry = HeapObject::RawField( | |
86 heap->empty_fixed_array(), FixedArrayBase::kLengthOffset); | |
87 DCHECK(Page::FromAddress(reinterpret_cast<Address>(kRemovedEntry)) | |
88 ->NeverEvacuate()); | |
89 | |
90 while (buffer != NULL) { | |
91 SlotsBuffer::ObjectSlot* slots = buffer->slots_; | |
92 intptr_t slots_count = buffer->idx_; | |
93 bool is_typed_slot = false; | |
94 | |
95 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) { | |
96 ObjectSlot slot = slots[slot_idx]; | |
97 if (!IsTypedSlot(slot)) { | |
98 Address slot_address = reinterpret_cast<Address>(slot); | |
99 if (slot_address >= start_slot && slot_address < end_slot) { | |
100 // TODO(hpayer): Instead of replacing slots with kRemovedEntry we | |
101 // could shrink the slots buffer in-place. | |
102 slots[slot_idx] = kRemovedEntry; | |
103 if (is_typed_slot) { | |
104 slots[slot_idx - 1] = kRemovedEntry; | |
105 } | |
106 } | |
107 is_typed_slot = false; | |
108 } else { | |
109 is_typed_slot = true; | |
110 DCHECK(slot_idx < slots_count); | |
111 } | |
112 } | |
113 buffer = buffer->next(); | |
114 } | |
115 } | |
116 | |
117 | |
118 void SlotsBuffer::VerifySlots(Heap* heap, SlotsBuffer* buffer) { | |
119 while (buffer != NULL) { | |
120 SlotsBuffer::ObjectSlot* slots = buffer->slots_; | |
121 intptr_t slots_count = buffer->idx_; | |
122 | |
123 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) { | |
124 ObjectSlot slot = slots[slot_idx]; | |
125 if (!IsTypedSlot(slot)) { | |
126 Object* object = *slot; | |
127 if (object->IsHeapObject()) { | |
128 HeapObject* heap_object = HeapObject::cast(object); | |
129 CHECK(!heap->InNewSpace(object)); | |
130 heap->mark_compact_collector()->VerifyIsSlotInLiveObject( | |
131 reinterpret_cast<Address>(slot), heap_object); | |
132 } | |
133 } else { | |
134 ++slot_idx; | |
135 DCHECK(slot_idx < slots_count); | |
136 } | |
137 } | |
138 buffer = buffer->next(); | |
139 } | |
140 } | |
141 | |
142 | |
143 SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) { | |
144 return new SlotsBuffer(next_buffer); | |
145 } | |
146 | |
147 | |
148 void SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) { | |
149 delete buffer; | |
150 } | |
151 | |
152 | |
153 void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) { | |
154 SlotsBuffer* buffer = *buffer_address; | |
155 while (buffer != NULL) { | |
156 SlotsBuffer* next_buffer = buffer->next(); | |
157 DeallocateBuffer(buffer); | |
158 buffer = next_buffer; | |
159 } | |
160 *buffer_address = NULL; | |
161 } | |
162 | |
163 } // namespace internal | |
164 } // namespace v8 | |
OLD | NEW |