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 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 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 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 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 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 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 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