blob: e8b1281b5a9e8a345ce8ee903a385cfc3655237c [file] [log] [blame]
// Copyright 2015 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.
#include "src/interpreter/constant-array-builder.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
namespace v8 {
namespace internal {
namespace interpreter {
ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(Zone* zone,
size_t start_index,
size_t capacity)
: start_index_(start_index),
capacity_(capacity),
reserved_(0),
constants_(zone) {}
void ConstantArrayBuilder::ConstantArraySlice::Reserve() {
DCHECK_GT(available(), 0u);
reserved_++;
DCHECK_LE(reserved_, capacity() - constants_.size());
}
void ConstantArrayBuilder::ConstantArraySlice::Unreserve() {
DCHECK_GT(reserved_, 0u);
reserved_--;
}
size_t ConstantArrayBuilder::ConstantArraySlice::Allocate(
Handle<Object> object) {
DCHECK_GT(available(), 0u);
size_t index = constants_.size();
DCHECK_LT(index, capacity());
constants_.push_back(object);
return index + start_index();
}
Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At(
size_t index) const {
return constants_[index - start_index()];
}
STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kMaxCapacity;
STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kLowCapacity;
ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone)
: isolate_(isolate),
idx8_slice_(zone, 0, kLowCapacity),
idx16_slice_(zone, kLowCapacity, kHighCapacity),
constants_map_(isolate->heap(), zone) {
STATIC_ASSERT(kMaxCapacity == static_cast<size_t>(kMaxUInt16 + 1));
DCHECK_EQ(idx8_slice_.start_index(), 0u);
DCHECK_EQ(idx8_slice_.capacity(), kLowCapacity);
DCHECK_EQ(idx16_slice_.start_index(), kLowCapacity);
DCHECK_EQ(idx16_slice_.capacity(), kMaxCapacity - kLowCapacity);
}
size_t ConstantArrayBuilder::size() const {
if (idx16_slice_.size() > 0) {
return idx16_slice_.start_index() + idx16_slice_.size();
} else {
return idx8_slice_.size();
}
}
Handle<Object> ConstantArrayBuilder::At(size_t index) const {
if (index >= idx16_slice_.start_index()) {
return idx16_slice_.At(index);
} else if (index < idx8_slice_.size()) {
return idx8_slice_.At(index);
} else {
return isolate_->factory()->the_hole_value();
}
}
Handle<FixedArray> ConstantArrayBuilder::ToFixedArray() {
Handle<FixedArray> fixed_array = isolate_->factory()->NewFixedArray(
static_cast<int>(size()), PretenureFlag::TENURED);
for (int i = 0; i < fixed_array->length(); i++) {
fixed_array->set(i, *At(static_cast<size_t>(i)));
}
constants_map()->Clear();
return fixed_array;
}
size_t ConstantArrayBuilder::Insert(Handle<Object> object) {
index_t* entry = constants_map()->Find(object);
return (entry == nullptr) ? AllocateEntry(object) : *entry;
}
ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry(
Handle<Object> object) {
DCHECK(!object->IsOddball());
size_t index;
index_t* entry = constants_map()->Get(object);
if (idx8_slice_.available() > 0) {
index = idx8_slice_.Allocate(object);
} else {
index = idx16_slice_.Allocate(object);
}
CHECK_LT(index, kMaxCapacity);
*entry = static_cast<index_t>(index);
return *entry;
}
OperandSize ConstantArrayBuilder::CreateReservedEntry() {
if (idx8_slice_.available() > 0) {
idx8_slice_.Reserve();
return OperandSize::kByte;
} else if (idx16_slice_.available() > 0) {
idx16_slice_.Reserve();
return OperandSize::kShort;
} else {
UNREACHABLE();
return OperandSize::kNone;
}
}
size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
Handle<Object> object) {
DiscardReservedEntry(operand_size);
size_t index;
index_t* entry = constants_map()->Find(object);
if (nullptr == entry) {
index = AllocateEntry(object);
} else {
if (operand_size == OperandSize::kByte &&
*entry >= idx8_slice_.capacity()) {
// The object is already in the constant array, but has an index
// outside the range of an idx8 operand so we need to create a
// duplicate entry in the idx8 operand range to satisfy the
// commitment.
*entry = static_cast<index_t>(idx8_slice_.Allocate(object));
}
index = *entry;
}
DCHECK(operand_size == OperandSize::kShort || index < idx8_slice_.capacity());
DCHECK_LT(index, kMaxCapacity);
return index;
}
void ConstantArrayBuilder::DiscardReservedEntry(OperandSize operand_size) {
switch (operand_size) {
case OperandSize::kByte:
idx8_slice_.Unreserve();
return;
case OperandSize::kShort:
idx16_slice_.Unreserve();
return;
default:
UNREACHABLE();
}
}
} // namespace interpreter
} // namespace internal
} // namespace v8