1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/interpreter/constant-array-builder.h" 6 7 #include "src/isolate.h" 8 #include "src/objects-inl.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace interpreter { 13 14 ConstantArrayBuilder::ConstantArraySlice::ConstantArraySlice(Zone* zone, 15 size_t start_index, 16 size_t capacity) 17 : start_index_(start_index), 18 capacity_(capacity), 19 reserved_(0), 20 constants_(zone) {} 21 22 23 void ConstantArrayBuilder::ConstantArraySlice::Reserve() { 24 DCHECK_GT(available(), 0u); 25 reserved_++; 26 DCHECK_LE(reserved_, capacity() - constants_.size()); 27 } 28 29 30 void ConstantArrayBuilder::ConstantArraySlice::Unreserve() { 31 DCHECK_GT(reserved_, 0u); 32 reserved_--; 33 } 34 35 36 size_t ConstantArrayBuilder::ConstantArraySlice::Allocate( 37 Handle<Object> object) { 38 DCHECK_GT(available(), 0u); 39 size_t index = constants_.size(); 40 DCHECK_LT(index, capacity()); 41 constants_.push_back(object); 42 return index + start_index(); 43 } 44 45 46 Handle<Object> ConstantArrayBuilder::ConstantArraySlice::At( 47 size_t index) const { 48 return constants_[index - start_index()]; 49 } 50 51 52 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kMaxCapacity; 53 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kLowCapacity; 54 55 56 ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone) 57 : isolate_(isolate), 58 idx8_slice_(zone, 0, kLowCapacity), 59 idx16_slice_(zone, kLowCapacity, kHighCapacity), 60 constants_map_(isolate->heap(), zone) { 61 STATIC_ASSERT(kMaxCapacity == static_cast<size_t>(kMaxUInt16 + 1)); 62 DCHECK_EQ(idx8_slice_.start_index(), 0u); 63 DCHECK_EQ(idx8_slice_.capacity(), kLowCapacity); 64 DCHECK_EQ(idx16_slice_.start_index(), kLowCapacity); 65 DCHECK_EQ(idx16_slice_.capacity(), kMaxCapacity - kLowCapacity); 66 } 67 68 69 size_t ConstantArrayBuilder::size() const { 70 if (idx16_slice_.size() > 0) { 71 return idx16_slice_.start_index() + idx16_slice_.size(); 72 } else { 73 return idx8_slice_.size(); 74 } 75 } 76 77 78 Handle<Object> ConstantArrayBuilder::At(size_t index) const { 79 if (index >= idx16_slice_.start_index()) { 80 return idx16_slice_.At(index); 81 } else if (index < idx8_slice_.size()) { 82 return idx8_slice_.At(index); 83 } else { 84 return isolate_->factory()->the_hole_value(); 85 } 86 } 87 88 89 Handle<FixedArray> ConstantArrayBuilder::ToFixedArray(Factory* factory) const { 90 Handle<FixedArray> fixed_array = 91 factory->NewFixedArray(static_cast<int>(size()), PretenureFlag::TENURED); 92 for (int i = 0; i < fixed_array->length(); i++) { 93 fixed_array->set(i, *At(static_cast<size_t>(i))); 94 } 95 return fixed_array; 96 } 97 98 99 size_t ConstantArrayBuilder::Insert(Handle<Object> object) { 100 index_t* entry = constants_map_.Find(object); 101 return (entry == nullptr) ? AllocateEntry(object) : *entry; 102 } 103 104 105 ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry( 106 Handle<Object> object) { 107 DCHECK(!object->IsOddball()); 108 size_t index; 109 index_t* entry = constants_map_.Get(object); 110 if (idx8_slice_.available() > 0) { 111 index = idx8_slice_.Allocate(object); 112 } else { 113 index = idx16_slice_.Allocate(object); 114 } 115 CHECK_LT(index, kMaxCapacity); 116 *entry = static_cast<index_t>(index); 117 return *entry; 118 } 119 120 121 OperandSize ConstantArrayBuilder::CreateReservedEntry() { 122 if (idx8_slice_.available() > 0) { 123 idx8_slice_.Reserve(); 124 return OperandSize::kByte; 125 } else if (idx16_slice_.available() > 0) { 126 idx16_slice_.Reserve(); 127 return OperandSize::kShort; 128 } else { 129 UNREACHABLE(); 130 return OperandSize::kNone; 131 } 132 } 133 134 135 size_t ConstantArrayBuilder::CommitReservedEntry(OperandSize operand_size, 136 Handle<Object> object) { 137 DiscardReservedEntry(operand_size); 138 size_t index; 139 index_t* entry = constants_map_.Find(object); 140 if (nullptr == entry) { 141 index = AllocateEntry(object); 142 } else { 143 if (operand_size == OperandSize::kByte && 144 *entry >= idx8_slice_.capacity()) { 145 // The object is already in the constant array, but has an index 146 // outside the range of an idx8 operand so we need to create a 147 // duplicate entry in the idx8 operand range to satisfy the 148 // commitment. 149 *entry = static_cast<index_t>(idx8_slice_.Allocate(object)); 150 } 151 index = *entry; 152 } 153 DCHECK(operand_size == OperandSize::kShort || index < idx8_slice_.capacity()); 154 DCHECK_LT(index, kMaxCapacity); 155 return index; 156 } 157 158 159 void ConstantArrayBuilder::DiscardReservedEntry(OperandSize operand_size) { 160 switch (operand_size) { 161 case OperandSize::kByte: 162 idx8_slice_.Unreserve(); 163 return; 164 case OperandSize::kShort: 165 idx16_slice_.Unreserve(); 166 return; 167 default: 168 UNREACHABLE(); 169 } 170 } 171 172 } // namespace interpreter 173 } // namespace internal 174 } // namespace v8 175