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

Side by Side Diff: src/lookup.cc

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

Powered by Google App Engine
This is Rietveld 408576698