• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IsTypedSlot(ObjectSlot slot)14 bool SlotsBuffer::IsTypedSlot(ObjectSlot slot) {
15   return reinterpret_cast<uintptr_t>(slot) < NUMBER_OF_SLOT_TYPES;
16 }
17 
18 
AddTo(SlotsBufferAllocator * allocator,SlotsBuffer ** buffer_address,SlotType type,Address addr,AdditionMode mode)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 
RemoveInvalidSlots(Heap * heap,SlotsBuffer * buffer)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         if (!object->IsHeapObject() || heap->InNewSpace(object) ||
60             !heap->mark_compact_collector()->IsSlotInLiveObject(
61                 reinterpret_cast<Address>(slot)) ||
62             !Page::FromAddress(reinterpret_cast<Address>(object))
63                  ->IsEvacuationCandidate()) {
64           // TODO(hpayer): Instead of replacing slots with kRemovedEntry we
65           // could shrink the slots buffer in-place.
66           slots[slot_idx] = kRemovedEntry;
67         }
68       } else {
69         ++slot_idx;
70         DCHECK(slot_idx < slots_count);
71       }
72     }
73     buffer = buffer->next();
74   }
75 }
76 
77 
RemoveObjectSlots(Heap * heap,SlotsBuffer * buffer,Address start_slot,Address end_slot)78 void SlotsBuffer::RemoveObjectSlots(Heap* heap, SlotsBuffer* buffer,
79                                     Address start_slot, Address end_slot) {
80   // Remove entries by replacing them with an old-space slot containing a smi
81   // that is located in an unmovable page.
82   const ObjectSlot kRemovedEntry = HeapObject::RawField(
83       heap->empty_fixed_array(), FixedArrayBase::kLengthOffset);
84   DCHECK(Page::FromAddress(reinterpret_cast<Address>(kRemovedEntry))
85              ->NeverEvacuate());
86 
87   while (buffer != NULL) {
88     SlotsBuffer::ObjectSlot* slots = buffer->slots_;
89     intptr_t slots_count = buffer->idx_;
90     bool is_typed_slot = false;
91 
92     for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) {
93       ObjectSlot slot = slots[slot_idx];
94       if (!IsTypedSlot(slot)) {
95         Address slot_address = reinterpret_cast<Address>(slot);
96         if (slot_address >= start_slot && slot_address < end_slot) {
97           // TODO(hpayer): Instead of replacing slots with kRemovedEntry we
98           // could shrink the slots buffer in-place.
99           slots[slot_idx] = kRemovedEntry;
100           if (is_typed_slot) {
101             slots[slot_idx - 1] = kRemovedEntry;
102           }
103         }
104         is_typed_slot = false;
105       } else {
106         is_typed_slot = true;
107         DCHECK(slot_idx < slots_count);
108       }
109     }
110     buffer = buffer->next();
111   }
112 }
113 
114 
VerifySlots(Heap * heap,SlotsBuffer * buffer)115 void SlotsBuffer::VerifySlots(Heap* heap, SlotsBuffer* buffer) {
116   while (buffer != NULL) {
117     SlotsBuffer::ObjectSlot* slots = buffer->slots_;
118     intptr_t slots_count = buffer->idx_;
119 
120     for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) {
121       ObjectSlot slot = slots[slot_idx];
122       if (!IsTypedSlot(slot)) {
123         Object* object = *slot;
124         if (object->IsHeapObject()) {
125           HeapObject* heap_object = HeapObject::cast(object);
126           CHECK(!heap->InNewSpace(object));
127           heap->mark_compact_collector()->VerifyIsSlotInLiveObject(
128               reinterpret_cast<Address>(slot), heap_object);
129         }
130       } else {
131         ++slot_idx;
132         DCHECK(slot_idx < slots_count);
133       }
134     }
135     buffer = buffer->next();
136   }
137 }
138 
139 
AllocateBuffer(SlotsBuffer * next_buffer)140 SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) {
141   return new SlotsBuffer(next_buffer);
142 }
143 
144 
DeallocateBuffer(SlotsBuffer * buffer)145 void SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) {
146   delete buffer;
147 }
148 
149 
DeallocateChain(SlotsBuffer ** buffer_address)150 void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) {
151   SlotsBuffer* buffer = *buffer_address;
152   while (buffer != NULL) {
153     SlotsBuffer* next_buffer = buffer->next();
154     DeallocateBuffer(buffer);
155     buffer = next_buffer;
156   }
157   *buffer_address = NULL;
158 }
159 
160 }  // namespace internal
161 }  // namespace v8
162