// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_LOCAL_ALLOCATOR_INL_H_
#define V8_HEAP_LOCAL_ALLOCATOR_INL_H_

#include "src/heap/local-allocator.h"

#include "src/heap/spaces-inl.h"

namespace v8 {
namespace internal {

AllocationResult LocalAllocator::Allocate(AllocationSpace space,
                                          int object_size,
                                          AllocationAlignment alignment) {
  switch (space) {
    case NEW_SPACE:
      return AllocateInNewSpace(object_size, alignment);
    case OLD_SPACE:
      return compaction_spaces_.Get(OLD_SPACE)->AllocateRaw(object_size,
                                                            alignment);
    case CODE_SPACE:
      return compaction_spaces_.Get(CODE_SPACE)
          ->AllocateRaw(object_size, alignment);
    default:
      UNREACHABLE();
  }
}

void LocalAllocator::FreeLast(AllocationSpace space, HeapObject object,
                              int object_size) {
  switch (space) {
    case NEW_SPACE:
      FreeLastInNewSpace(object, object_size);
      return;
    case OLD_SPACE:
      FreeLastInOldSpace(object, object_size);
      return;
    default:
      // Only new and old space supported.
      UNREACHABLE();
  }
}

void LocalAllocator::FreeLastInNewSpace(HeapObject object, int object_size) {
  if (!new_space_lab_.TryFreeLast(object, object_size)) {
    // We couldn't free the last object so we have to write a proper filler.
    heap_->CreateFillerObjectAt(object.address(), object_size,
                                ClearRecordedSlots::kNo);
  }
}

void LocalAllocator::FreeLastInOldSpace(HeapObject object, int object_size) {
  if (!compaction_spaces_.Get(OLD_SPACE)->TryFreeLast(object, object_size)) {
    // We couldn't free the last object so we have to write a proper filler.
    heap_->CreateFillerObjectAt(object.address(), object_size,
                                ClearRecordedSlots::kNo);
  }
}

AllocationResult LocalAllocator::AllocateInLAB(int object_size,
                                               AllocationAlignment alignment) {
  AllocationResult allocation;
  if (!new_space_lab_.IsValid() && !NewLocalAllocationBuffer()) {
    return AllocationResult::Retry(OLD_SPACE);
  }
  allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
  if (allocation.IsRetry()) {
    if (!NewLocalAllocationBuffer()) {
      return AllocationResult::Retry(OLD_SPACE);
    } else {
      allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
      CHECK(!allocation.IsRetry());
    }
  }
  return allocation;
}

bool LocalAllocator::NewLocalAllocationBuffer() {
  if (lab_allocation_will_fail_) return false;
  LocalAllocationBuffer saved_lab_ = new_space_lab_;
  AllocationResult result =
      new_space_->AllocateRawSynchronized(kLabSize, kWordAligned);
  new_space_lab_ = LocalAllocationBuffer::FromResult(heap_, result, kLabSize);
  if (new_space_lab_.IsValid()) {
    new_space_lab_.TryMerge(&saved_lab_);
    return true;
  }
  new_space_lab_ = saved_lab_;
  lab_allocation_will_fail_ = true;
  return false;
}

AllocationResult LocalAllocator::AllocateInNewSpace(
    int object_size, AllocationAlignment alignment) {
  if (object_size > kMaxLabObjectSize) {
    return new_space_->AllocateRawSynchronized(object_size, alignment);
  }
  return AllocateInLAB(object_size, alignment);
}

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_LOCAL_ALLOCATOR_INL_H_
