Home | History | Annotate | Download | only in heap
      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