Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kMaxCapacity; | |
| 15 STATIC_CONST_MEMBER_DEFINITION const size_t ConstantArrayBuilder::kLowCapacity; | |
| 16 | |
| 17 | |
| 18 ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone) | |
| 19 : isolate_(isolate), | |
| 20 constants_map_(isolate->heap(), zone), | |
| 21 constants_(zone), | |
| 22 allocated_low_(0), | |
| 23 reserved_low_(0), | |
| 24 reserved_high_(0) {} | |
| 25 | |
| 26 | |
| 27 Handle<FixedArray> ConstantArrayBuilder::ToFixedArray( | |
| 28 Factory* factory, PretenureFlag pretenure) const { | |
| 29 Handle<FixedArray> fixed_array = | |
| 30 factory->NewFixedArray(static_cast<int>(constants_.size()), pretenure); | |
| 31 for (int i = 0; i < fixed_array->length(); i++) { | |
| 32 fixed_array->set(i, *constants_.at(i)); | |
| 33 } | |
| 34 return fixed_array; | |
| 35 } | |
| 36 | |
| 37 | |
| 38 size_t ConstantArrayBuilder::Insert(Handle<Object> object) { | |
| 39 index_t* entry = constants_map_.Find(object); | |
| 40 return (entry == nullptr) ? AllocateEntry(object) : *entry; | |
| 41 } | |
| 42 | |
| 43 | |
| 44 void ConstantArrayBuilder::EnsureCapacity(size_t minimum_pool_size) { | |
| 45 DCHECK_GE(minimum_pool_size, allocated_low_); | |
| 46 if (constants_.size() < minimum_pool_size) { | |
| 47 constants_.insert(constants_.end(), minimum_pool_size - constants_.size(), | |
| 48 isolate()->factory()->the_hole_value()); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 | |
| 53 ConstantArrayBuilder::index_t ConstantArrayBuilder::AllocateEntry( | |
| 54 Handle<Object> object) { | |
| 55 DCHECK(!object->IsOddball()); | |
| 56 DCHECK_LE(allocated_and_reserved_low(), kLowCapacity); | |
| 57 index_t* entry = constants_map_.Get(object); | |
| 58 if (allocated_and_reserved_low() < kLowCapacity) { | |
| 59 EnsureCapacity(allocated_low_ + 1); | |
|
mythria
2015/12/24 15:53:44
I might have missed something, but would the follo
oth
2015/12/27 08:42:34
Consider the case where a reservation has been mad
| |
| 60 DCHECK(constants_[allocated_low_].is_identical_to( | |
| 61 isolate()->factory()->the_hole_value())); | |
| 62 constants_[allocated_low_] = object; | |
| 63 *entry = allocated_low_++; | |
| 64 } else { | |
| 65 if (allocated_and_reserved_low() == kLowCapacity) { | |
| 66 EnsureCapacity(kLowCapacity); | |
| 67 } | |
| 68 constants_.push_back(object); | |
| 69 DCHECK_LE(constants_.size() - 1, std::numeric_limits<index_t>::max()); | |
| 70 *entry = static_cast<index_t>(constants_.size() - 1); | |
| 71 DCHECK_GT(constants_.size(), kLowCapacity); | |
| 72 DCHECK_LE(constants_.size(), kMaxCapacity); | |
| 73 } | |
| 74 DCHECK_LE(allocated_and_reserved_low(), kLowCapacity); | |
| 75 DCHECK_LE(reserved_high_ + constants_.size(), kMaxCapacity); | |
| 76 DCHECK(constants_[*entry]->SameValue(*object)); | |
| 77 return *entry; | |
| 78 } | |
| 79 | |
| 80 | |
| 81 ConstantArrayBuilder::ReservationToken | |
| 82 ConstantArrayBuilder::CreateReservedEntry() { | |
| 83 if (allocated_and_reserved_low() < kLowCapacity) { | |
| 84 reserved_low_++; | |
| 85 return ReservationToken::kIdx8; | |
| 86 } else { | |
| 87 reserved_high_++; | |
| 88 DCHECK_LE(reserved_high_ + constants_.size(), kMaxCapacity); | |
| 89 return ReservationToken::kIdx16; | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 | |
| 94 size_t ConstantArrayBuilder::CommitReservedEntry(ReservationToken token, | |
| 95 Handle<Object> object) { | |
| 96 DCHECK(token == ReservationToken::kIdx16 || reserved_low_ > 0); | |
| 97 DiscardReservedEntry(token); | |
| 98 size_t index; | |
| 99 index_t* entry = constants_map_.Find(object); | |
| 100 if (nullptr == entry) { | |
| 101 index = AllocateEntry(object); | |
| 102 } else { | |
| 103 if (token == ReservationToken::kIdx8 && *entry >= kLowCapacity) { | |
| 104 // The object is already in the constant array, but has an index | |
| 105 // outside the low range so we need to create a duplicate entry | |
| 106 // in the low range to satisfy the commitment. | |
|
mythria
2015/12/24 15:53:44
Do we need constants_[allocated_low_] = object; he
oth
2015/12/27 08:42:34
Yes.
| |
| 107 *entry = allocated_low_++; | |
| 108 DCHECK_LE(allocated_and_reserved_low(), kLowCapacity); | |
| 109 } | |
| 110 index = *entry; | |
| 111 } | |
| 112 DCHECK(token == ReservationToken::kIdx16 || index < kLowCapacity); | |
| 113 return index; | |
| 114 } | |
| 115 | |
| 116 | |
| 117 void ConstantArrayBuilder::DiscardReservedEntry(ReservationToken token) { | |
| 118 if (token == ReservationToken::kIdx8) { | |
| 119 DCHECK_GT(reserved_low_, 0); | |
| 120 reserved_low_--; | |
| 121 if (reserved_low_ != 0 && constants_.size() == kLowCapacity) { | |
| 122 constants_.resize(allocated_low_); | |
| 123 } | |
| 124 } else { | |
| 125 DCHECK(token == ReservationToken::kIdx16); | |
| 126 DCHECK_GT(reserved_high_, 0); | |
| 127 reserved_high_--; | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 | |
| 132 // static | |
| 133 size_t ConstantArrayBuilder::SizeOfReservedArrayIndex(ReservationToken token) { | |
| 134 switch (token) { | |
| 135 case ReservationToken::kIdx8: | |
| 136 return 1; | |
| 137 case ReservationToken::kIdx16: | |
| 138 return 2; | |
| 139 } | |
| 140 UNREACHABLE(); | |
| 141 return 0; | |
| 142 } | |
| 143 | |
| 144 } // namespace interpreter | |
| 145 } // namespace internal | |
| 146 } // namespace v8 | |
| OLD | NEW |