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