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,AllocationOrigin origin,AllocationAlignment alignment)15 AllocationResult LocalAllocator::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 CODE_SPACE:
26       return compaction_spaces_.Get(CODE_SPACE)
27           ->AllocateRaw(object_size, alignment, origin);
28     default:
29       UNREACHABLE();
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   }
46 }
47 
FreeLastInNewSpace(HeapObject object,int object_size)48 void LocalAllocator::FreeLastInNewSpace(HeapObject object, int object_size) {
49   if (!new_space_lab_.TryFreeLast(object, object_size)) {
50     // We couldn't free the last object so we have to write a proper filler.
51     heap_->CreateFillerObjectAt(object.address(), object_size,
52                                 ClearRecordedSlots::kNo);
53   }
54 }
55 
FreeLastInOldSpace(HeapObject object,int object_size)56 void LocalAllocator::FreeLastInOldSpace(HeapObject object, int object_size) {
57   if (!compaction_spaces_.Get(OLD_SPACE)->TryFreeLast(object, object_size)) {
58     // We couldn't free the last object so we have to write a proper filler.
59     heap_->CreateFillerObjectAt(object.address(), object_size,
60                                 ClearRecordedSlots::kNo);
61   }
62 }
63 
AllocateInLAB(int object_size,AllocationAlignment alignment)64 AllocationResult LocalAllocator::AllocateInLAB(int object_size,
65                                                AllocationAlignment alignment) {
66   AllocationResult allocation;
67   if (!new_space_lab_.IsValid() && !NewLocalAllocationBuffer()) {
68     return AllocationResult::Retry(OLD_SPACE);
69   }
70   allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
71   if (allocation.IsRetry()) {
72     if (!NewLocalAllocationBuffer()) {
73       return AllocationResult::Retry(OLD_SPACE);
74     } else {
75       allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
76       CHECK(!allocation.IsRetry());
77     }
78   }
79   return allocation;
80 }
81 
NewLocalAllocationBuffer()82 bool LocalAllocator::NewLocalAllocationBuffer() {
83   if (lab_allocation_will_fail_) return false;
84   LocalAllocationBuffer saved_lab_ = new_space_lab_;
85   AllocationResult result =
86       new_space_->AllocateRawSynchronized(kLabSize, kWordAligned);
87   new_space_lab_ = LocalAllocationBuffer::FromResult(heap_, result, kLabSize);
88   if (new_space_lab_.IsValid()) {
89     new_space_lab_.TryMerge(&saved_lab_);
90     return true;
91   }
92   new_space_lab_ = saved_lab_;
93   lab_allocation_will_fail_ = true;
94   return false;
95 }
96 
AllocateInNewSpace(int object_size,AllocationOrigin origin,AllocationAlignment alignment)97 AllocationResult LocalAllocator::AllocateInNewSpace(
98     int object_size, AllocationOrigin origin, AllocationAlignment alignment) {
99   if (object_size > kMaxLabObjectSize) {
100     return new_space_->AllocateRawSynchronized(object_size, alignment, origin);
101   }
102   return AllocateInLAB(object_size, alignment);
103 }
104 
105 }  // namespace internal
106 }  // namespace v8
107 
108 #endif  // V8_HEAP_LOCAL_ALLOCATOR_INL_H_
109