Chromium Code Reviews| 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..a1f6925ecb7f48903b5f1a598e897e857b9fa375 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,51 @@ 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(); |
| } |
| +ConstantArrayBuilder::ConstantArraySlice* ConstantArrayBuilder::IndexToSlice( |
|
rmcilroy
2016/02/25 13:26:06
This seems a bit overkill to me. I'd prefer just t
oth
2016/02/25 15:40:15
Compensated in ToFixedArray to avoid 2-3x penalty
|
| + size_t index) const { |
| + DCHECK_LE(index, kMaxUInt32); |
| + static const int kLog2Table[] = {0, 1, 2, 2}; |
| + int clz = base::bits::CountLeadingZeros32(static_cast<uint32_t>(index | 1)); |
| + int byte_index = (31 - clz) >> 3; |
| + return idx_slice_[kLog2Table[byte_index]]; |
| +} |
| 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); |
| + ConstantArraySlice* slice = IndexToSlice(index); |
| + if (index < slice->start_index() + slice->size()) { |
| + return slice->At(index); |
| } else { |
| return isolate_->factory()->the_hole_value(); |
| } |
| @@ -95,43 +99,39 @@ Handle<FixedArray> ConstantArrayBuilder::ToFixedArray() { |
| 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; |
|
rmcilroy
2016/02/25 13:26:06
nit - move this into the for loop now
oth
2016/02/25 15:40:15
Done.
|
| 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) { |
| + 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; |
| } |
| - |
| size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size, |
| Handle<Object> object) { |
| DiscardReservedEntry(operand_size); |
| @@ -140,33 +140,30 @@ 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)); |
| + // The object is already in the constant array, but may have an |
|
rmcilroy
2016/02/25 13:26:06
Could you pull the check for entry in a larger ope
oth
2016/02/25 15:40:15
Done.
|
| + // index too big for the reserved operand_size. So, duplicate |
| + // entry with the smaller operand size. |
| + for (size_t i = arraysize(idx_slice_); i > 0; --i) { |
| + ConstantArraySlice* slice = idx_slice_[i - 1]; |
| + if (operand_size == slice->operand_size() && |
| + *entry > slice->max_index()) { |
| + *entry = static_cast<index_t>(slice->Allocate(object)); |
| + break; |
| + } |
| } |
| 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(); |
| + for (size_t i = 0; i < arraysize(idx_slice_); ++i) { |
| + if (operand_size == idx_slice_[i]->operand_size()) { |
|
rmcilroy
2016/02/25 13:26:06
Could you make idx_slice_ indexable by operand_siz
oth
2016/02/25 15:40:15
There is existing code already assumes the enum va
|
| + idx_slice_[i]->Unreserve(); |
| return; |
| - case OperandSize::kShort: |
| - idx16_slice_.Unreserve(); |
| - return; |
| - default: |
| - UNREACHABLE(); |
| + } |
| } |
| + UNREACHABLE(); |
| } |
| } // namespace interpreter |