OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/runtime/runtime-utils.h" | 8 #include "src/runtime/runtime-utils.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 * length overflows 32-bit non-negative integer. | 97 * length overflows 32-bit non-negative integer. |
98 */ | 98 */ |
99 class ArrayConcatVisitor { | 99 class ArrayConcatVisitor { |
100 public: | 100 public: |
101 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage, | 101 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage, |
102 bool fast_elements) | 102 bool fast_elements) |
103 : isolate_(isolate), | 103 : isolate_(isolate), |
104 storage_(Handle<FixedArray>::cast( | 104 storage_(Handle<FixedArray>::cast( |
105 isolate->global_handles()->Create(*storage))), | 105 isolate->global_handles()->Create(*storage))), |
106 index_offset_(0u), | 106 index_offset_(0u), |
107 fast_elements_(fast_elements), | 107 bit_field_(FastElementsField::encode(fast_elements) | |
108 exceeds_array_limit_(false) {} | 108 ExceedsLimitField::encode(false)) {} |
109 | 109 |
110 ~ArrayConcatVisitor() { clear_storage(); } | 110 ~ArrayConcatVisitor() { clear_storage(); } |
111 | 111 |
112 void visit(uint32_t i, Handle<Object> elm) { | 112 void visit(uint32_t i, Handle<Object> elm) { |
113 if (i > JSObject::kMaxElementCount - index_offset_) { | 113 if (i > JSObject::kMaxElementCount - index_offset_) { |
114 exceeds_array_limit_ = true; | 114 set_exceeds_array_limit(true); |
115 return; | 115 return; |
116 } | 116 } |
117 uint32_t index = index_offset_ + i; | 117 uint32_t index = index_offset_ + i; |
118 | 118 |
119 if (fast_elements_) { | 119 if (fast_elements()) { |
120 if (index < static_cast<uint32_t>(storage_->length())) { | 120 if (index < static_cast<uint32_t>(storage_->length())) { |
121 storage_->set(index, *elm); | 121 storage_->set(index, *elm); |
122 return; | 122 return; |
123 } | 123 } |
124 // Our initial estimate of length was foiled, possibly by | 124 // Our initial estimate of length was foiled, possibly by |
125 // getters on the arrays increasing the length of later arrays | 125 // getters on the arrays increasing the length of later arrays |
126 // during iteration. | 126 // during iteration. |
127 // This shouldn't happen in anything but pathological cases. | 127 // This shouldn't happen in anything but pathological cases. |
128 SetDictionaryMode(); | 128 SetDictionaryMode(); |
129 // Fall-through to dictionary mode. | 129 // Fall-through to dictionary mode. |
130 } | 130 } |
131 DCHECK(!fast_elements_); | 131 DCHECK(!fast_elements()); |
132 Handle<SeededNumberDictionary> dict( | 132 Handle<SeededNumberDictionary> dict( |
133 SeededNumberDictionary::cast(*storage_)); | 133 SeededNumberDictionary::cast(*storage_)); |
134 Handle<SeededNumberDictionary> result = | 134 Handle<SeededNumberDictionary> result = |
135 SeededNumberDictionary::AtNumberPut(dict, index, elm); | 135 SeededNumberDictionary::AtNumberPut(dict, index, elm); |
136 if (!result.is_identical_to(dict)) { | 136 if (!result.is_identical_to(dict)) { |
137 // Dictionary needed to grow. | 137 // Dictionary needed to grow. |
138 clear_storage(); | 138 clear_storage(); |
139 set_storage(*result); | 139 set_storage(*result); |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 void increase_index_offset(uint32_t delta) { | 143 void increase_index_offset(uint32_t delta) { |
144 if (JSObject::kMaxElementCount - index_offset_ < delta) { | 144 if (JSObject::kMaxElementCount - index_offset_ < delta) { |
145 index_offset_ = JSObject::kMaxElementCount; | 145 index_offset_ = JSObject::kMaxElementCount; |
146 } else { | 146 } else { |
147 index_offset_ += delta; | 147 index_offset_ += delta; |
148 } | 148 } |
149 // If the initial length estimate was off (see special case in visit()), | 149 // If the initial length estimate was off (see special case in visit()), |
150 // but the array blowing the limit didn't contain elements beyond the | 150 // but the array blowing the limit didn't contain elements beyond the |
151 // provided-for index range, go to dictionary mode now. | 151 // provided-for index range, go to dictionary mode now. |
152 if (fast_elements_ && | 152 if (fast_elements() && |
153 index_offset_ > | 153 index_offset_ > |
154 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { | 154 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { |
155 SetDictionaryMode(); | 155 SetDictionaryMode(); |
156 } | 156 } |
157 } | 157 } |
158 | 158 |
159 bool exceeds_array_limit() { return exceeds_array_limit_; } | 159 bool exceeds_array_limit() const { |
| 160 return ExceedsLimitField::decode(bit_field_); |
| 161 } |
160 | 162 |
161 Handle<JSArray> ToArray() { | 163 Handle<JSArray> ToArray() { |
162 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); | 164 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); |
163 Handle<Object> length = | 165 Handle<Object> length = |
164 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); | 166 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); |
165 Handle<Map> map = JSObject::GetElementsTransitionMap( | 167 Handle<Map> map = JSObject::GetElementsTransitionMap( |
166 array, fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); | 168 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); |
167 array->set_map(*map); | 169 array->set_map(*map); |
168 array->set_length(*length); | 170 array->set_length(*length); |
169 array->set_elements(*storage_); | 171 array->set_elements(*storage_); |
170 return array; | 172 return array; |
171 } | 173 } |
172 | 174 |
173 private: | 175 private: |
174 // Convert storage to dictionary mode. | 176 // Convert storage to dictionary mode. |
175 void SetDictionaryMode() { | 177 void SetDictionaryMode() { |
176 DCHECK(fast_elements_); | 178 DCHECK(fast_elements()); |
177 Handle<FixedArray> current_storage(*storage_); | 179 Handle<FixedArray> current_storage(*storage_); |
178 Handle<SeededNumberDictionary> slow_storage( | 180 Handle<SeededNumberDictionary> slow_storage( |
179 SeededNumberDictionary::New(isolate_, current_storage->length())); | 181 SeededNumberDictionary::New(isolate_, current_storage->length())); |
180 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); | 182 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); |
181 for (uint32_t i = 0; i < current_length; i++) { | 183 for (uint32_t i = 0; i < current_length; i++) { |
182 HandleScope loop_scope(isolate_); | 184 HandleScope loop_scope(isolate_); |
183 Handle<Object> element(current_storage->get(i), isolate_); | 185 Handle<Object> element(current_storage->get(i), isolate_); |
184 if (!element->IsTheHole()) { | 186 if (!element->IsTheHole()) { |
185 Handle<SeededNumberDictionary> new_storage = | 187 Handle<SeededNumberDictionary> new_storage = |
186 SeededNumberDictionary::AtNumberPut(slow_storage, i, element); | 188 SeededNumberDictionary::AtNumberPut(slow_storage, i, element); |
187 if (!new_storage.is_identical_to(slow_storage)) { | 189 if (!new_storage.is_identical_to(slow_storage)) { |
188 slow_storage = loop_scope.CloseAndEscape(new_storage); | 190 slow_storage = loop_scope.CloseAndEscape(new_storage); |
189 } | 191 } |
190 } | 192 } |
191 } | 193 } |
192 clear_storage(); | 194 clear_storage(); |
193 set_storage(*slow_storage); | 195 set_storage(*slow_storage); |
194 fast_elements_ = false; | 196 set_fast_elements(false); |
195 } | 197 } |
196 | 198 |
197 inline void clear_storage() { | 199 inline void clear_storage() { |
198 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); | 200 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); |
199 } | 201 } |
200 | 202 |
201 inline void set_storage(FixedArray* storage) { | 203 inline void set_storage(FixedArray* storage) { |
202 storage_ = | 204 storage_ = |
203 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage)); | 205 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage)); |
204 } | 206 } |
205 | 207 |
| 208 class FastElementsField : public BitField<bool, 0, 1> {}; |
| 209 class ExceedsLimitField : public BitField<bool, 1, 1> {}; |
| 210 |
| 211 bool fast_elements() const { return FastElementsField::decode(bit_field_); } |
| 212 void set_fast_elements(bool fast) { |
| 213 bit_field_ = FastElementsField::update(bit_field_, fast); |
| 214 } |
| 215 void set_exceeds_array_limit(bool exceeds) { |
| 216 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds); |
| 217 } |
| 218 |
206 Isolate* isolate_; | 219 Isolate* isolate_; |
207 Handle<FixedArray> storage_; // Always a global handle. | 220 Handle<FixedArray> storage_; // Always a global handle. |
208 // Index after last seen index. Always less than or equal to | 221 // Index after last seen index. Always less than or equal to |
209 // JSObject::kMaxElementCount. | 222 // JSObject::kMaxElementCount. |
210 uint32_t index_offset_; | 223 uint32_t index_offset_; |
211 bool fast_elements_ : 1; | 224 uint32_t bit_field_; |
212 bool exceeds_array_limit_ : 1; | |
213 }; | 225 }; |
214 | 226 |
215 | 227 |
216 static uint32_t EstimateElementCount(Handle<JSArray> array) { | 228 static uint32_t EstimateElementCount(Handle<JSArray> array) { |
217 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 229 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
218 int element_count = 0; | 230 int element_count = 0; |
219 switch (array->GetElementsKind()) { | 231 switch (array->GetElementsKind()) { |
220 case FAST_SMI_ELEMENTS: | 232 case FAST_SMI_ELEMENTS: |
221 case FAST_HOLEY_SMI_ELEMENTS: | 233 case FAST_HOLEY_SMI_ELEMENTS: |
222 case FAST_ELEMENTS: | 234 case FAST_ELEMENTS: |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 } | 1187 } |
1176 | 1188 |
1177 | 1189 |
1178 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { | 1190 RUNTIME_FUNCTION(RuntimeReference_FastOneByteArrayJoin) { |
1179 SealHandleScope shs(isolate); | 1191 SealHandleScope shs(isolate); |
1180 DCHECK(args.length() == 2); | 1192 DCHECK(args.length() == 2); |
1181 return isolate->heap()->undefined_value(); | 1193 return isolate->heap()->undefined_value(); |
1182 } | 1194 } |
1183 } | 1195 } |
1184 } // namespace v8::internal | 1196 } // namespace v8::internal |
OLD | NEW |