| Index: src/interpreter/constant-array-builder.cc
|
| diff --git a/src/interpreter/constant-array-builder.cc b/src/interpreter/constant-array-builder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2586e1ff4d5c443ce53db6782266d2a15f620cd9
|
| --- /dev/null
|
| +++ b/src/interpreter/constant-array-builder.cc
|
| @@ -0,0 +1,174 @@
|
| +// 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(Factory* factory) const {
|
| + Handle<FixedArray> fixed_array =
|
| + 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)));
|
| + }
|
| + 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
|
|
|