Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: src/lookup.cc

Issue 1753273002: Specialize helper methods in the LookupIterator by is_element. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase fix Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/lookup.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/lookup.h" 5 #include "src/lookup.h"
6 6
7 #include "src/bootstrapper.h" 7 #include "src/bootstrapper.h"
8 #include "src/deoptimizer.h" 8 #include "src/deoptimizer.h"
9 #include "src/elements.h" 9 #include "src/elements.h"
10 #include "src/field-type.h" 10 #include "src/field-type.h"
(...skipping 27 matching lines...) Expand all
38 LookupIterator it(isolate, receiver, index, configuration); 38 LookupIterator it(isolate, receiver, index, configuration);
39 // Here we try to avoid having to rebuild the string later 39 // Here we try to avoid having to rebuild the string later
40 // by storing it on the indexed LookupIterator. 40 // by storing it on the indexed LookupIterator.
41 it.name_ = name; 41 it.name_ = name;
42 return it; 42 return it;
43 } 43 }
44 44
45 return LookupIterator(receiver, name, configuration); 45 return LookupIterator(receiver, name, configuration);
46 } 46 }
47 47
48 template <bool is_element>
48 void LookupIterator::Start() { 49 void LookupIterator::Start() {
49 DisallowHeapAllocation no_gc; 50 DisallowHeapAllocation no_gc;
50 51
51 has_property_ = false; 52 has_property_ = false;
52 state_ = NOT_FOUND; 53 state_ = NOT_FOUND;
53 number_ = DescriptorArray::kNotFound; 54 number_ = DescriptorArray::kNotFound;
54 holder_ = initial_holder_; 55 holder_ = initial_holder_;
55 56
56 JSReceiver* holder = *holder_; 57 JSReceiver* holder = *holder_;
57 Map* map = holder->map(); 58 Map* map = holder->map();
58 59
59 state_ = LookupInHolder(map, holder); 60 state_ = LookupInHolder<is_element>(map, holder);
60 if (IsFound()) return; 61 if (IsFound()) return;
61 62
62 NextInternal(map, holder); 63 NextInternal<is_element>(map, holder);
63 } 64 }
64 65
66 template void LookupIterator::Start<true>();
67 template void LookupIterator::Start<false>();
68
65 void LookupIterator::Next() { 69 void LookupIterator::Next() {
66 DCHECK_NE(JSPROXY, state_); 70 DCHECK_NE(JSPROXY, state_);
67 DCHECK_NE(TRANSITION, state_); 71 DCHECK_NE(TRANSITION, state_);
68 DisallowHeapAllocation no_gc; 72 DisallowHeapAllocation no_gc;
69 has_property_ = false; 73 has_property_ = false;
70 74
71 JSReceiver* holder = *holder_; 75 JSReceiver* holder = *holder_;
72 Map* map = holder->map(); 76 Map* map = holder->map();
73 77
74 if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) { 78 if (map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
75 state_ = LookupInSpecialHolder(map, holder); 79 state_ = IsElement() ? LookupInSpecialHolder<true>(map, holder)
80 : LookupInSpecialHolder<false>(map, holder);
76 if (IsFound()) return; 81 if (IsFound()) return;
77 } 82 }
78 83
79 NextInternal(map, holder); 84 IsElement() ? NextInternal<true>(map, holder)
85 : NextInternal<false>(map, holder);
80 } 86 }
81 87
88 template <bool is_element>
82 void LookupIterator::NextInternal(Map* map, JSReceiver* holder) { 89 void LookupIterator::NextInternal(Map* map, JSReceiver* holder) {
83 do { 90 do {
84 JSReceiver* maybe_holder = NextHolder(map); 91 JSReceiver* maybe_holder = NextHolder(map);
85 if (maybe_holder == nullptr) { 92 if (maybe_holder == nullptr) {
86 if (interceptor_state_ == InterceptorState::kSkipNonMasking) { 93 if (interceptor_state_ == InterceptorState::kSkipNonMasking) {
87 RestartLookupForNonMaskingInterceptors(); 94 RestartLookupForNonMaskingInterceptors<is_element>();
88 return; 95 return;
89 } 96 }
90 if (holder != *holder_) holder_ = handle(holder, isolate_); 97 if (holder != *holder_) holder_ = handle(holder, isolate_);
91 return; 98 return;
92 } 99 }
93 holder = maybe_holder; 100 holder = maybe_holder;
94 map = holder->map(); 101 map = holder->map();
95 state_ = LookupInHolder(map, holder); 102 state_ = LookupInHolder<is_element>(map, holder);
96 } while (!IsFound()); 103 } while (!IsFound());
97 104
98 holder_ = handle(holder, isolate_); 105 holder_ = handle(holder, isolate_);
99 } 106 }
100 107
108 template <bool is_element>
101 void LookupIterator::RestartInternal(InterceptorState interceptor_state) { 109 void LookupIterator::RestartInternal(InterceptorState interceptor_state) {
102 interceptor_state_ = interceptor_state; 110 interceptor_state_ = interceptor_state;
103 property_details_ = PropertyDetails::Empty(); 111 property_details_ = PropertyDetails::Empty();
104 Start(); 112 Start<is_element>();
105 } 113 }
106 114
115 template void LookupIterator::RestartInternal<true>(InterceptorState);
116 template void LookupIterator::RestartInternal<false>(InterceptorState);
107 117
108 // static 118 // static
109 Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver( 119 Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver(
110 Isolate* isolate, Handle<Object> receiver, uint32_t index) { 120 Isolate* isolate, Handle<Object> receiver, uint32_t index) {
111 // Strings are the only objects with properties (only elements) directly on 121 // Strings are the only objects with properties (only elements) directly on
112 // the wrapper. Hence we can skip generating the wrapper for all other cases. 122 // the wrapper. Hence we can skip generating the wrapper for all other cases.
113 if (index != kMaxUInt32 && receiver->IsString() && 123 if (index != kMaxUInt32 && receiver->IsString() &&
114 index < static_cast<uint32_t>(String::cast(*receiver)->length())) { 124 index < static_cast<uint32_t>(String::cast(*receiver)->length())) {
115 // TODO(verwaest): Speed this up. Perhaps use a cached wrapper on the native 125 // TODO(verwaest): Speed this up. Perhaps use a cached wrapper on the native
116 // context, ensuring that we don't leak it into JS? 126 // context, ensuring that we don't leak it into JS?
(...skipping 15 matching lines...) Expand all
132 if (receiver_->IsNumber()) return factory()->heap_number_map(); 142 if (receiver_->IsNumber()) return factory()->heap_number_map();
133 return handle(Handle<HeapObject>::cast(receiver_)->map(), isolate_); 143 return handle(Handle<HeapObject>::cast(receiver_)->map(), isolate_);
134 } 144 }
135 145
136 bool LookupIterator::HasAccess() const { 146 bool LookupIterator::HasAccess() const {
137 DCHECK_EQ(ACCESS_CHECK, state_); 147 DCHECK_EQ(ACCESS_CHECK, state_);
138 return isolate_->MayAccess(handle(isolate_->context()), 148 return isolate_->MayAccess(handle(isolate_->context()),
139 GetHolder<JSObject>()); 149 GetHolder<JSObject>());
140 } 150 }
141 151
142 152 template <bool is_element>
143 void LookupIterator::ReloadPropertyInformation() { 153 void LookupIterator::ReloadPropertyInformation() {
144 state_ = BEFORE_PROPERTY; 154 state_ = BEFORE_PROPERTY;
145 interceptor_state_ = InterceptorState::kUninitialized; 155 interceptor_state_ = InterceptorState::kUninitialized;
146 state_ = LookupInHolder(holder_->map(), *holder_); 156 state_ = LookupInHolder<is_element>(holder_->map(), *holder_);
147 DCHECK(IsFound() || !holder_->HasFastProperties()); 157 DCHECK(IsFound() || !holder_->HasFastProperties());
148 } 158 }
149 159
150 bool LookupIterator::HolderIsInContextIndex(uint32_t index) const { 160 bool LookupIterator::HolderIsInContextIndex(uint32_t index) const {
151 DisallowHeapAllocation no_gc; 161 DisallowHeapAllocation no_gc;
152 162
153 Object* context = heap()->native_contexts_list(); 163 Object* context = heap()->native_contexts_list();
154 while (!context->IsUndefined()) { 164 while (!context->IsUndefined()) {
155 Context* current_context = Context::cast(context); 165 Context* current_context = Context::cast(context);
156 if (current_context->get(index) == *holder_) { 166 if (current_context->get(index) == *holder_) {
157 return true; 167 return true;
158 } 168 }
159 context = current_context->get(Context::NEXT_CONTEXT_LINK); 169 context = current_context->get(Context::NEXT_CONTEXT_LINK);
160 } 170 }
161 return false; 171 return false;
162 } 172 }
163 173
164 void LookupIterator::UpdateProtector() { 174 void LookupIterator::UpdateProtector() {
165 if (!FLAG_harmony_species) return; 175 if (!FLAG_harmony_species) return;
166 176
167 if (IsElement()) return; 177 if (IsElement()) return;
168 if (isolate_->bootstrapper()->IsActive()) return; 178 if (isolate_->bootstrapper()->IsActive()) return;
169 if (!isolate_->IsArraySpeciesLookupChainIntact()) return; 179 if (!isolate_->IsArraySpeciesLookupChainIntact()) return;
170 180
171 if (*name_ == *isolate_->factory()->constructor_string()) { 181 if (*name_ == heap()->constructor_string()) {
172 // Setting the constructor property could change an instance's @@species 182 // Setting the constructor property could change an instance's @@species
173 if (holder_->IsJSArray()) { 183 if (holder_->IsJSArray()) {
174 isolate_->CountUsage( 184 isolate_->CountUsage(
175 v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified); 185 v8::Isolate::UseCounterFeature::kArrayInstanceConstructorModified);
176 isolate_->InvalidateArraySpeciesProtector(); 186 isolate_->InvalidateArraySpeciesProtector();
177 } else if (holder_->map()->is_prototype_map()) { 187 } else if (holder_->map()->is_prototype_map()) {
178 // Setting the constructor of Array.prototype of any realm also needs 188 // Setting the constructor of Array.prototype of any realm also needs
179 // to invalidate the species protector 189 // to invalidate the species protector
180 if (HolderIsInContextIndex(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) { 190 if (HolderIsInContextIndex(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)) {
181 isolate_->CountUsage(v8::Isolate::UseCounterFeature:: 191 isolate_->CountUsage(v8::Isolate::UseCounterFeature::
182 kArrayPrototypeConstructorModified); 192 kArrayPrototypeConstructorModified);
183 isolate_->InvalidateArraySpeciesProtector(); 193 isolate_->InvalidateArraySpeciesProtector();
184 } 194 }
185 } 195 }
186 } else if (*name_ == *isolate_->factory()->species_symbol()) { 196 } else if (*name_ == heap()->species_symbol()) {
187 // Setting the Symbol.species property of any Array constructor invalidates 197 // Setting the Symbol.species property of any Array constructor invalidates
188 // the species protector 198 // the species protector
189 if (HolderIsInContextIndex(Context::ARRAY_FUNCTION_INDEX)) { 199 if (HolderIsInContextIndex(Context::ARRAY_FUNCTION_INDEX)) {
190 isolate_->CountUsage( 200 isolate_->CountUsage(
191 v8::Isolate::UseCounterFeature::kArraySpeciesModified); 201 v8::Isolate::UseCounterFeature::kArraySpeciesModified);
192 isolate_->InvalidateArraySpeciesProtector(); 202 isolate_->InvalidateArraySpeciesProtector();
193 } 203 }
194 } 204 }
195 } 205 }
196 206
(...skipping 29 matching lines...) Expand all
226 if (old_map.is_identical_to(new_map)) { 236 if (old_map.is_identical_to(new_map)) {
227 // Update the property details if the representation was None. 237 // Update the property details if the representation was None.
228 if (representation().IsNone()) { 238 if (representation().IsNone()) {
229 property_details_ = 239 property_details_ =
230 new_map->instance_descriptors()->GetDetails(descriptor_number()); 240 new_map->instance_descriptors()->GetDetails(descriptor_number());
231 } 241 }
232 return; 242 return;
233 } 243 }
234 244
235 JSObject::MigrateToMap(holder, new_map); 245 JSObject::MigrateToMap(holder, new_map);
236 ReloadPropertyInformation(); 246 ReloadPropertyInformation<false>();
237 } 247 }
238 248
239 249
240 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, 250 void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
241 PropertyAttributes attributes) { 251 PropertyAttributes attributes) {
242 DCHECK(state_ == DATA || state_ == ACCESSOR); 252 DCHECK(state_ == DATA || state_ == ACCESSOR);
243 DCHECK(HolderIsReceiverOrHiddenPrototype()); 253 DCHECK(HolderIsReceiverOrHiddenPrototype());
244 Handle<JSObject> holder = GetHolder<JSObject>(); 254 Handle<JSObject> holder = GetHolder<JSObject>();
245 if (IsElement()) { 255 if (IsElement()) {
246 DCHECK(!holder->HasFixedTypedArrayElements()); 256 DCHECK(!holder->HasFixedTypedArrayElements());
247 DCHECK(attributes != NONE || !holder->HasFastElements()); 257 DCHECK(attributes != NONE || !holder->HasFastElements());
248 Handle<FixedArrayBase> elements(holder->elements()); 258 Handle<FixedArrayBase> elements(holder->elements());
249 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, 259 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value,
250 attributes); 260 attributes);
251 } else if (!holder->HasFastProperties()) { 261 ReloadPropertyInformation<true>();
252 PropertyDetails details(attributes, v8::internal::DATA, 0,
253 PropertyCellType::kMutable);
254 JSObject::SetNormalizedProperty(holder, name(), value, details);
255 } else { 262 } else {
256 Handle<Map> old_map(holder->map(), isolate_); 263 if (!holder->HasFastProperties()) {
257 Handle<Map> new_map = Map::ReconfigureExistingProperty( 264 PropertyDetails details(attributes, v8::internal::DATA, 0,
258 old_map, descriptor_number(), i::kData, attributes); 265 PropertyCellType::kMutable);
259 new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value); 266 JSObject::SetNormalizedProperty(holder, name(), value, details);
260 JSObject::MigrateToMap(holder, new_map); 267 } else {
268 Handle<Map> old_map(holder->map(), isolate_);
269 Handle<Map> new_map = Map::ReconfigureExistingProperty(
270 old_map, descriptor_number(), i::kData, attributes);
271 new_map =
272 Map::PrepareForDataProperty(new_map, descriptor_number(), value);
273 JSObject::MigrateToMap(holder, new_map);
274 }
275 ReloadPropertyInformation<false>();
261 } 276 }
262 277
263 ReloadPropertyInformation();
264 WriteDataValue(value); 278 WriteDataValue(value);
265 279
266 #if VERIFY_HEAP 280 #if VERIFY_HEAP
267 if (FLAG_verify_heap) { 281 if (FLAG_verify_heap) {
268 holder->JSObjectVerify(); 282 holder->JSObjectVerify();
269 } 283 }
270 #endif 284 #endif
271 } 285 }
272 286
273 // Can only be called when the receiver is a JSObject. JSProxy has to be handled 287 // Can only be called when the receiver is a JSObject. JSProxy has to be handled
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 Handle<Map> transition = transition_map(); 335 Handle<Map> transition = transition_map();
322 bool simple_transition = transition->GetBackPointer() == receiver->map(); 336 bool simple_transition = transition->GetBackPointer() == receiver->map();
323 JSObject::MigrateToMap(receiver, transition); 337 JSObject::MigrateToMap(receiver, transition);
324 338
325 if (simple_transition) { 339 if (simple_transition) {
326 int number = transition->LastAdded(); 340 int number = transition->LastAdded();
327 number_ = static_cast<uint32_t>(number); 341 number_ = static_cast<uint32_t>(number);
328 property_details_ = transition->GetLastDescriptorDetails(); 342 property_details_ = transition->GetLastDescriptorDetails();
329 state_ = DATA; 343 state_ = DATA;
330 } else { 344 } else {
331 ReloadPropertyInformation(); 345 ReloadPropertyInformation<false>();
332 } 346 }
333 } 347 }
334 348
335 349
336 void LookupIterator::Delete() { 350 void LookupIterator::Delete() {
337 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_); 351 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_);
338 if (IsElement()) { 352 if (IsElement()) {
339 Handle<JSObject> object = Handle<JSObject>::cast(holder); 353 Handle<JSObject> object = Handle<JSObject>::cast(holder);
340 ElementsAccessor* accessor = object->GetElementsAccessor(); 354 ElementsAccessor* accessor = object->GetElementsAccessor();
341 accessor->Delete(object, number_); 355 accessor->Delete(object, number_);
342 } else { 356 } else {
343 PropertyNormalizationMode mode = holder->map()->is_prototype_map() 357 PropertyNormalizationMode mode = holder->map()->is_prototype_map()
344 ? KEEP_INOBJECT_PROPERTIES 358 ? KEEP_INOBJECT_PROPERTIES
345 : CLEAR_INOBJECT_PROPERTIES; 359 : CLEAR_INOBJECT_PROPERTIES;
346 360
347 if (holder->HasFastProperties()) { 361 if (holder->HasFastProperties()) {
348 JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0, 362 JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0,
349 "DeletingProperty"); 363 "DeletingProperty");
350 ReloadPropertyInformation(); 364 ReloadPropertyInformation<false>();
351 } 365 }
352 // TODO(verwaest): Get rid of the name_ argument. 366 // TODO(verwaest): Get rid of the name_ argument.
353 JSReceiver::DeleteNormalizedProperty(holder, name_, number_); 367 JSReceiver::DeleteNormalizedProperty(holder, name_, number_);
354 if (holder->IsJSObject()) { 368 if (holder->IsJSObject()) {
355 JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder)); 369 JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder));
356 } 370 }
357 } 371 }
358 state_ = NOT_FOUND; 372 state_ = NOT_FOUND;
359 } 373 }
360 374
361 375
362 void LookupIterator::TransitionToAccessorProperty( 376 void LookupIterator::TransitionToAccessorProperty(
363 AccessorComponent component, Handle<Object> accessor, 377 AccessorComponent component, Handle<Object> accessor,
364 PropertyAttributes attributes) { 378 PropertyAttributes attributes) {
365 DCHECK(!accessor->IsNull()); 379 DCHECK(!accessor->IsNull());
366 // Can only be called when the receiver is a JSObject. JSProxy has to be 380 // Can only be called when the receiver is a JSObject. JSProxy has to be
367 // handled via a trap. Adding properties to primitive values is not 381 // handled via a trap. Adding properties to primitive values is not
368 // observable. 382 // observable.
369 Handle<JSObject> receiver = GetStoreTarget(); 383 Handle<JSObject> receiver = GetStoreTarget();
370 384
371 if (!IsElement() && !receiver->map()->is_dictionary_map()) { 385 if (!IsElement() && !receiver->map()->is_dictionary_map()) {
372 holder_ = receiver; 386 holder_ = receiver;
373 Handle<Map> old_map(receiver->map(), isolate_); 387 Handle<Map> old_map(receiver->map(), isolate_);
374 Handle<Map> new_map = Map::TransitionToAccessorProperty( 388 Handle<Map> new_map = Map::TransitionToAccessorProperty(
375 old_map, name_, component, accessor, attributes); 389 old_map, name_, component, accessor, attributes);
376 JSObject::MigrateToMap(receiver, new_map); 390 JSObject::MigrateToMap(receiver, new_map);
377 391
378 ReloadPropertyInformation(); 392 ReloadPropertyInformation<false>();
379 393
380 if (!new_map->is_dictionary_map()) return; 394 if (!new_map->is_dictionary_map()) return;
381 } 395 }
382 396
383 Handle<AccessorPair> pair; 397 Handle<AccessorPair> pair;
384 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) { 398 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) {
385 pair = Handle<AccessorPair>::cast(GetAccessors()); 399 pair = Handle<AccessorPair>::cast(GetAccessors());
386 // If the component and attributes are identical, nothing has to be done. 400 // If the component and attributes are identical, nothing has to be done.
387 if (pair->get(component) == *accessor) { 401 if (pair->get(component) == *accessor) {
388 if (property_details().attributes() == attributes) return; 402 if (property_details().attributes() == attributes) return;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 if (receiver->HasSlowArgumentsElements()) { 442 if (receiver->HasSlowArgumentsElements()) {
429 FixedArray* parameter_map = FixedArray::cast(receiver->elements()); 443 FixedArray* parameter_map = FixedArray::cast(receiver->elements());
430 uint32_t length = parameter_map->length() - 2; 444 uint32_t length = parameter_map->length() - 2;
431 if (number_ < length) { 445 if (number_ < length) {
432 parameter_map->set(number_ + 2, heap()->the_hole_value()); 446 parameter_map->set(number_ + 2, heap()->the_hole_value());
433 } 447 }
434 FixedArray::cast(receiver->elements())->set(1, *dictionary); 448 FixedArray::cast(receiver->elements())->set(1, *dictionary);
435 } else { 449 } else {
436 receiver->set_elements(*dictionary); 450 receiver->set_elements(*dictionary);
437 } 451 }
452
453 ReloadPropertyInformation<true>();
438 } else { 454 } else {
439 PropertyNormalizationMode mode = receiver->map()->is_prototype_map() 455 PropertyNormalizationMode mode = receiver->map()->is_prototype_map()
440 ? KEEP_INOBJECT_PROPERTIES 456 ? KEEP_INOBJECT_PROPERTIES
441 : CLEAR_INOBJECT_PROPERTIES; 457 : CLEAR_INOBJECT_PROPERTIES;
442 // Normalize object to make this operation simple. 458 // Normalize object to make this operation simple.
443 JSObject::NormalizeProperties(receiver, mode, 0, 459 JSObject::NormalizeProperties(receiver, mode, 0,
444 "TransitionToAccessorPair"); 460 "TransitionToAccessorPair");
445 461
446 JSObject::SetNormalizedProperty(receiver, name_, pair, details); 462 JSObject::SetNormalizedProperty(receiver, name_, pair, details);
447 JSObject::ReoptimizeIfPrototype(receiver); 463 JSObject::ReoptimizeIfPrototype(receiver);
464
465 ReloadPropertyInformation<false>();
448 } 466 }
449
450 ReloadPropertyInformation();
451 } 467 }
452 468
453 469
454 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { 470 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const {
455 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); 471 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY);
456 // Optimization that only works if configuration_ is not mutable. 472 // Optimization that only works if configuration_ is not mutable.
457 if (!check_prototype_chain()) return true; 473 if (!check_prototype_chain()) return true;
458 DisallowHeapAllocation no_gc; 474 DisallowHeapAllocation no_gc;
459 if (!receiver_->IsJSReceiver()) return false; 475 if (!receiver_->IsJSReceiver()) return false;
460 JSReceiver* current = JSReceiver::cast(*receiver_); 476 JSReceiver* current = JSReceiver::cast(*receiver_);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 handle(JSObject::cast(*holder)->global_dictionary()); 596 handle(JSObject::cast(*holder)->global_dictionary());
581 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, 597 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value,
582 property_details_); 598 property_details_);
583 } else { 599 } else {
584 NameDictionary* property_dictionary = holder->property_dictionary(); 600 NameDictionary* property_dictionary = holder->property_dictionary();
585 property_dictionary->ValueAtPut(dictionary_entry(), *value); 601 property_dictionary->ValueAtPut(dictionary_entry(), *value);
586 } 602 }
587 } 603 }
588 604
589 605
590 bool LookupIterator::HasInterceptor(Map* map) const {
591 if (IsElement()) return map->has_indexed_interceptor();
592 return map->has_named_interceptor();
593 }
594
595
596 bool LookupIterator::SkipInterceptor(JSObject* holder) { 606 bool LookupIterator::SkipInterceptor(JSObject* holder) {
597 auto info = GetInterceptor(holder); 607 auto info = GetInterceptor(holder);
598 // TODO(dcarney): check for symbol/can_intercept_symbols here as well. 608 // TODO(dcarney): check for symbol/can_intercept_symbols here as well.
599 if (info->non_masking()) { 609 if (info->non_masking()) {
600 switch (interceptor_state_) { 610 switch (interceptor_state_) {
601 case InterceptorState::kUninitialized: 611 case InterceptorState::kUninitialized:
602 interceptor_state_ = InterceptorState::kSkipNonMasking; 612 interceptor_state_ = InterceptorState::kSkipNonMasking;
603 // Fall through. 613 // Fall through.
604 case InterceptorState::kSkipNonMasking: 614 case InterceptorState::kSkipNonMasking:
605 return true; 615 return true;
(...skipping 26 matching lines...) Expand all
632 if (!holder->IsJSTypedArray() || !name_->IsString()) return NOT_FOUND; 642 if (!holder->IsJSTypedArray() || !name_->IsString()) return NOT_FOUND;
633 643
634 Handle<String> name_string = Handle<String>::cast(name_); 644 Handle<String> name_string = Handle<String>::cast(name_);
635 if (name_string->length() == 0) return NOT_FOUND; 645 if (name_string->length() == 0) return NOT_FOUND;
636 646
637 return IsSpecialIndex(isolate_->unicode_cache(), *name_string) 647 return IsSpecialIndex(isolate_->unicode_cache(), *name_string)
638 ? INTEGER_INDEXED_EXOTIC 648 ? INTEGER_INDEXED_EXOTIC
639 : NOT_FOUND; 649 : NOT_FOUND;
640 } 650 }
641 651
652 namespace {
653
654 template <bool is_element>
655 bool HasInterceptor(Map* map) {
656 return is_element ? map->has_indexed_interceptor()
657 : map->has_named_interceptor();
658 }
659
660 } // namespace
661
662 template <bool is_element>
642 LookupIterator::State LookupIterator::LookupInSpecialHolder( 663 LookupIterator::State LookupIterator::LookupInSpecialHolder(
643 Map* const map, JSReceiver* const holder) { 664 Map* const map, JSReceiver* const holder) {
644 STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY); 665 STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
645 switch (state_) { 666 switch (state_) {
646 case NOT_FOUND: 667 case NOT_FOUND:
647 if (map->IsJSProxyMap()) { 668 if (map->IsJSProxyMap()) {
648 if (IsElement() || !name_->IsPrivate()) return JSPROXY; 669 if (is_element || !name_->IsPrivate()) return JSPROXY;
649 } 670 }
650 if (map->is_access_check_needed()) { 671 if (map->is_access_check_needed()) {
651 if (IsElement() || !name_->IsPrivate()) return ACCESS_CHECK; 672 if (is_element || !name_->IsPrivate()) return ACCESS_CHECK;
652 } 673 }
653 // Fall through. 674 // Fall through.
654 case ACCESS_CHECK: 675 case ACCESS_CHECK:
655 if (check_interceptor() && HasInterceptor(map) && 676 if (check_interceptor() && HasInterceptor<is_element>(map) &&
656 !SkipInterceptor(JSObject::cast(holder))) { 677 !SkipInterceptor(JSObject::cast(holder))) {
657 if (IsElement() || !name_->IsPrivate()) return INTERCEPTOR; 678 if (is_element || !name_->IsPrivate()) return INTERCEPTOR;
658 } 679 }
659 // Fall through. 680 // Fall through.
660 case INTERCEPTOR: 681 case INTERCEPTOR:
661 if (!IsElement() && map->IsJSGlobalObjectMap()) { 682 if (!is_element && map->IsJSGlobalObjectMap()) {
662 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); 683 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary();
663 int number = dict->FindEntry(name_); 684 int number = dict->FindEntry(name_);
664 if (number == GlobalDictionary::kNotFound) return NOT_FOUND; 685 if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
665 number_ = static_cast<uint32_t>(number); 686 number_ = static_cast<uint32_t>(number);
666 DCHECK(dict->ValueAt(number_)->IsPropertyCell()); 687 DCHECK(dict->ValueAt(number_)->IsPropertyCell());
667 PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); 688 PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_));
668 if (cell->value()->IsTheHole()) return NOT_FOUND; 689 if (cell->value()->IsTheHole()) return NOT_FOUND;
669 property_details_ = cell->property_details(); 690 property_details_ = cell->property_details();
670 has_property_ = true; 691 has_property_ = true;
671 switch (property_details_.kind()) { 692 switch (property_details_.kind()) {
672 case v8::internal::kData: 693 case v8::internal::kData:
673 return DATA; 694 return DATA;
674 case v8::internal::kAccessor: 695 case v8::internal::kAccessor:
675 return ACCESSOR; 696 return ACCESSOR;
676 } 697 }
677 } 698 }
678 return LookupInRegularHolder(map, holder); 699 return LookupInRegularHolder<is_element>(map, holder);
679 case ACCESSOR: 700 case ACCESSOR:
680 case DATA: 701 case DATA:
681 return NOT_FOUND; 702 return NOT_FOUND;
682 case INTEGER_INDEXED_EXOTIC: 703 case INTEGER_INDEXED_EXOTIC:
683 case JSPROXY: 704 case JSPROXY:
684 case TRANSITION: 705 case TRANSITION:
685 UNREACHABLE(); 706 UNREACHABLE();
686 } 707 }
687 UNREACHABLE(); 708 UNREACHABLE();
688 return NOT_FOUND; 709 return NOT_FOUND;
689 } 710 }
690 711
712 template <bool is_element>
691 LookupIterator::State LookupIterator::LookupInRegularHolder( 713 LookupIterator::State LookupIterator::LookupInRegularHolder(
692 Map* const map, JSReceiver* const holder) { 714 Map* const map, JSReceiver* const holder) {
693 DisallowHeapAllocation no_gc; 715 DisallowHeapAllocation no_gc;
694 if (interceptor_state_ == InterceptorState::kProcessNonMasking) { 716 if (interceptor_state_ == InterceptorState::kProcessNonMasking) {
695 return NOT_FOUND; 717 return NOT_FOUND;
696 } 718 }
697 719
698 if (IsElement()) { 720 if (is_element) {
699 JSObject* js_object = JSObject::cast(holder); 721 JSObject* js_object = JSObject::cast(holder);
700 ElementsAccessor* accessor = js_object->GetElementsAccessor(); 722 ElementsAccessor* accessor = js_object->GetElementsAccessor();
701 FixedArrayBase* backing_store = js_object->elements(); 723 FixedArrayBase* backing_store = js_object->elements();
702 number_ = accessor->GetEntryForIndex(js_object, backing_store, index_); 724 number_ = accessor->GetEntryForIndex(js_object, backing_store, index_);
703 if (number_ == kMaxUInt32) { 725 if (number_ == kMaxUInt32) {
704 return holder->IsJSTypedArray() ? INTEGER_INDEXED_EXOTIC : NOT_FOUND; 726 return holder->IsJSTypedArray() ? INTEGER_INDEXED_EXOTIC : NOT_FOUND;
705 } 727 }
706 property_details_ = accessor->GetDetails(js_object, number_); 728 property_details_ = accessor->GetDetails(js_object, number_);
707 } else if (!map->is_dictionary_map()) { 729 } else if (!map->is_dictionary_map()) {
708 DescriptorArray* descriptors = map->instance_descriptors(); 730 DescriptorArray* descriptors = map->instance_descriptors();
(...skipping 15 matching lines...) Expand all
724 case v8::internal::kAccessor: 746 case v8::internal::kAccessor:
725 return ACCESSOR; 747 return ACCESSOR;
726 } 748 }
727 749
728 UNREACHABLE(); 750 UNREACHABLE();
729 return state_; 751 return state_;
730 } 752 }
731 753
732 } // namespace internal 754 } // namespace internal
733 } // namespace v8 755 } // namespace v8
OLDNEW
« no previous file with comments | « src/lookup.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698