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 |