| Index: src/interpreter/constant-array-builder.cc
|
| diff --git a/src/interpreter/constant-array-builder.cc b/src/interpreter/constant-array-builder.cc
|
| index e8b1281b5a9e8a345ce8ee903a385cfc3655237c..e20d392ea8db67cc3ce79ed09c65b3cd1d763291 100644
|
| --- a/src/interpreter/constant-array-builder.cc
|
| +++ b/src/interpreter/constant-array-builder.cc
|
| @@ -11,28 +11,25 @@ namespace v8 {
|
| namespace internal {
|
| namespace interpreter {
|
|
|
| -ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(Zone* zone,
|
| - size_t start_index,
|
| - size_t capacity)
|
| +ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(
|
| + Zone* zone, size_t start_index, size_t capacity, OperandSize operand_size)
|
| : start_index_(start_index),
|
| capacity_(capacity),
|
| reserved_(0),
|
| + operand_size_(operand_size),
|
| 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);
|
| @@ -42,44 +39,53 @@ size_t ConstantArrayBuilder::ConstantArraySlice::Allocate(
|
| return index + start_index();
|
| }
|
|
|
| -
|
| Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At(
|
| size_t index) const {
|
| + DCHECK_GE(index, start_index());
|
| + DCHECK_LT(index, start_index() + size());
|
| return constants_[index - start_index()];
|
| }
|
|
|
| -
|
| -STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kMaxCapacity;
|
| -STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kLowCapacity;
|
| -
|
| +STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::k8BitCapacity;
|
| +STATIC_CONST_MEMBER_DEFINITION const size_t
|
| + ConstantArrayBuilder::k16BitCapacity;
|
| +STATIC_CONST_MEMBER_DEFINITION const size_t
|
| + ConstantArrayBuilder::k32BitCapacity;
|
|
|
| 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);
|
| + : isolate_(isolate), constants_map_(isolate->heap(), zone) {
|
| + idx_slice_[0] =
|
| + new (zone) ConstantArraySlice(zone, 0, k8BitCapacity, OperandSize::kByte);
|
| + idx_slice_[1] = new (zone) ConstantArraySlice(
|
| + zone, k8BitCapacity, k16BitCapacity, OperandSize::kShort);
|
| }
|
|
|
| -
|
| size_t ConstantArrayBuilder::size() const {
|
| - if (idx16_slice_.size() > 0) {
|
| - return idx16_slice_.start_index() + idx16_slice_.size();
|
| - } else {
|
| - return idx8_slice_.size();
|
| + size_t i = arraysize(idx_slice_);
|
| + while (i > 0) {
|
| + ConstantArraySlice* slice = idx_slice_[--i];
|
| + if (slice->size() > 0) {
|
| + return slice->start_index() + slice->size();
|
| + }
|
| }
|
| + return idx_slice_[0]->size();
|
| }
|
|
|
| +const ConstantArrayBuilder::ConstantArraySlice*
|
| +ConstantArrayBuilder::IndexToSlice(size_t index) const {
|
| + for (const ConstantArraySlice* slice : idx_slice_) {
|
| + if (index <= slice->max_index()) {
|
| + return slice;
|
| + }
|
| + }
|
| + UNREACHABLE();
|
| + return nullptr;
|
| +}
|
|
|
| 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);
|
| + const ConstantArraySlice* slice = IndexToSlice(index);
|
| + if (index < slice->start_index() + slice->size()) {
|
| + return slice->At(index);
|
| } else {
|
| return isolate_->factory()->the_hole_value();
|
| }
|
| @@ -88,49 +94,78 @@ Handle<Object> ConstantArrayBuilder::At(size_t index) const {
|
| 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)));
|
| + int array_index = 0;
|
| + for (const ConstantArraySlice* slice : idx_slice_) {
|
| + if (array_index == fixed_array->length()) {
|
| + break;
|
| + }
|
| + // Copy objects from slice into array.
|
| + for (size_t i = 0; i < slice->size(); ++i) {
|
| + fixed_array->set(array_index++, *slice->At(slice->start_index() + i));
|
| + }
|
| + // Insert holes where reservations led to unused slots.
|
| + size_t padding =
|
| + std::min(static_cast<size_t>(fixed_array->length() - array_index),
|
| + slice->capacity() - slice->size());
|
| + for (size_t i = slice->start_index() + slice->size();
|
| + i < slice->start_index() + padding; ++i) {
|
| + fixed_array->set(array_index++, *isolate_->factory()->the_hole_value());
|
| + }
|
| }
|
| + DCHECK_EQ(array_index, fixed_array->length());
|
| 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);
|
| + for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
| + if (idx_slice_[i]->available() > 0) {
|
| + size_t index = idx_slice_[i]->Allocate(object);
|
| + *entry = static_cast<index_t>(index);
|
| + return *entry;
|
| + break;
|
| + }
|
| }
|
| - CHECK_LT(index, kMaxCapacity);
|
| - *entry = static_cast<index_t>(index);
|
| - return *entry;
|
| + UNREACHABLE();
|
| + return kMaxUInt32;
|
| }
|
|
|
| -
|
| 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;
|
| + for (size_t i = 0; i < arraysize(idx_slice_); ++i) {
|
| + if (idx_slice_[i]->available() > 0) {
|
| + idx_slice_[i]->Reserve();
|
| + return idx_slice_[i]->operand_size();
|
| + }
|
| }
|
| + UNREACHABLE();
|
| + return OperandSize::kNone;
|
| }
|
|
|
| +ConstantArrayBuilder::ConstantArraySlice*
|
| +ConstantArrayBuilder::OperandSizeToSlice(OperandSize operand_size) const {
|
| + ConstantArraySlice* slice = nullptr;
|
| + switch (operand_size) {
|
| + case OperandSize::kNone:
|
| + UNREACHABLE();
|
| + break;
|
| + case OperandSize::kByte:
|
| + slice = idx_slice_[0];
|
| + break;
|
| + case OperandSize::kShort:
|
| + slice = idx_slice_[1];
|
| + break;
|
| + }
|
| + DCHECK(slice->operand_size() == operand_size);
|
| + return slice;
|
| +}
|
|
|
| size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
|
| Handle<Object> object) {
|
| @@ -140,33 +175,20 @@ size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size,
|
| 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));
|
| + ConstantArraySlice* slice = OperandSizeToSlice(operand_size);
|
| + if (*entry > slice->max_index()) {
|
| + // The object is already in the constant array, but may have an
|
| + // index too big for the reserved operand_size. So, duplicate
|
| + // entry with the smaller operand size.
|
| + *entry = static_cast<index_t>(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();
|
| - }
|
| + OperandSizeToSlice(operand_size)->Unreserve();
|
| }
|
|
|
| } // namespace interpreter
|
|
|