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 |