1 // Copyright 2018 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 #ifndef V8_HEAP_EVACUATION_ALLOCATOR_INL_H_
6 #define V8_HEAP_EVACUATION_ALLOCATOR_INL_H_
7
8 #include "src/common/globals.h"
9 #include "src/heap/evacuation-allocator.h"
10 #include "src/heap/spaces-inl.h"
11
12 namespace v8 {
13 namespace internal {
14
Allocate(AllocationSpace space,int object_size,AllocationOrigin origin,AllocationAlignment alignment)15 AllocationResult EvacuationAllocator::Allocate(AllocationSpace space,
16 int object_size,
17 AllocationOrigin origin,
18 AllocationAlignment alignment) {
19 switch (space) {
20 case NEW_SPACE:
21 return AllocateInNewSpace(object_size, origin, alignment);
22 case OLD_SPACE:
23 return compaction_spaces_.Get(OLD_SPACE)->AllocateRaw(object_size,
24 alignment, origin);
25 case MAP_SPACE:
26 return compaction_spaces_.Get(MAP_SPACE)->AllocateRaw(object_size,
27 alignment, origin);
28 case CODE_SPACE:
29 return compaction_spaces_.Get(CODE_SPACE)
30 ->AllocateRaw(object_size, alignment, origin);
31 default:
32 UNREACHABLE();
33 }
34 }
35
FreeLast(AllocationSpace space,HeapObject object,int object_size)36 void EvacuationAllocator::FreeLast(AllocationSpace space, HeapObject object,
37 int object_size) {
38 switch (space) {
39 case NEW_SPACE:
40 FreeLastInNewSpace(object, object_size);
41 return;
42 case OLD_SPACE:
43 FreeLastInOldSpace(object, object_size);
44 return;
45 case MAP_SPACE:
46 FreeLastInMapSpace(object, object_size);
47 return;
48 default:
49 // Only new and old space supported.
50 UNREACHABLE();
51 }
52 }
53
FreeLastInNewSpace(HeapObject object,int object_size)54 void EvacuationAllocator::FreeLastInNewSpace(HeapObject object,
55 int object_size) {
56 if (!new_space_lab_.TryFreeLast(object, object_size)) {
57 // We couldn't free the last object so we have to write a proper filler.
58 heap_->CreateFillerObjectAt(object.address(), object_size,
59 ClearRecordedSlots::kNo);
60 }
61 }
62
FreeLastInOldSpace(HeapObject object,int object_size)63 void EvacuationAllocator::FreeLastInOldSpace(HeapObject object,
64 int object_size) {
65 if (!compaction_spaces_.Get(OLD_SPACE)->TryFreeLast(object.address(),
66 object_size)) {
67 // We couldn't free the last object so we have to write a proper filler.
68 heap_->CreateFillerObjectAt(object.address(), object_size,
69 ClearRecordedSlots::kNo);
70 }
71 }
72
FreeLastInMapSpace(HeapObject object,int object_size)73 void EvacuationAllocator::FreeLastInMapSpace(HeapObject object,
74 int object_size) {
75 if (!compaction_spaces_.Get(MAP_SPACE)->TryFreeLast(object.address(),
76 object_size)) {
77 // We couldn't free the last object so we have to write a proper filler.
78 heap_->CreateFillerObjectAt(object.address(), object_size,
79 ClearRecordedSlots::kNo);
80 }
81 }
82
AllocateInLAB(int object_size,AllocationAlignment alignment)83 AllocationResult EvacuationAllocator::AllocateInLAB(
84 int object_size, AllocationAlignment alignment) {
85 AllocationResult allocation;
86 if (!new_space_lab_.IsValid() && !NewLocalAllocationBuffer()) {
87 return AllocationResult::Failure();
88 }
89 allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
90 if (allocation.IsFailure()) {
91 if (!NewLocalAllocationBuffer()) {
92 return AllocationResult::Failure();
93 } else {
94 allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
95 CHECK(!allocation.IsFailure());
96 }
97 }
98 return allocation;
99 }
100
NewLocalAllocationBuffer()101 bool EvacuationAllocator::NewLocalAllocationBuffer() {
102 if (lab_allocation_will_fail_) return false;
103 AllocationResult result =
104 new_space_->AllocateRawSynchronized(kLabSize, kTaggedAligned);
105 if (result.IsFailure()) {
106 lab_allocation_will_fail_ = true;
107 return false;
108 }
109 LocalAllocationBuffer saved_lab = std::move(new_space_lab_);
110 new_space_lab_ = LocalAllocationBuffer::FromResult(heap_, result, kLabSize);
111 DCHECK(new_space_lab_.IsValid());
112 if (!new_space_lab_.TryMerge(&saved_lab)) {
113 saved_lab.CloseAndMakeIterable();
114 }
115 return true;
116 }
117
AllocateInNewSpace(int object_size,AllocationOrigin origin,AllocationAlignment alignment)118 AllocationResult EvacuationAllocator::AllocateInNewSpace(
119 int object_size, AllocationOrigin origin, AllocationAlignment alignment) {
120 if (object_size > kMaxLabObjectSize) {
121 return new_space_->AllocateRawSynchronized(object_size, alignment, origin);
122 }
123 return AllocateInLAB(object_size, alignment);
124 }
125
126 } // namespace internal
127 } // namespace v8
128
129 #endif // V8_HEAP_EVACUATION_ALLOCATOR_INL_H_
130