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/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 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 JSObject::TransitionElementsKind(holder, to); | 213 JSObject::TransitionElementsKind(holder, to); |
214 } | 214 } |
215 | 215 |
216 // Copy the backing store if it is copy-on-write. | 216 // Copy the backing store if it is copy-on-write. |
217 if (IsFastSmiOrObjectElementsKind(to)) { | 217 if (IsFastSmiOrObjectElementsKind(to)) { |
218 JSObject::EnsureWritableFastElements(holder); | 218 JSObject::EnsureWritableFastElements(holder); |
219 } | 219 } |
220 return; | 220 return; |
221 } | 221 } |
222 | 222 |
| 223 if (holder->IsJSGlobalObject()) { |
| 224 Handle<GlobalDictionary> dictionary(holder->global_dictionary()); |
| 225 Handle<PropertyCell> cell( |
| 226 PropertyCell::cast(dictionary->ValueAt(dictionary_entry()))); |
| 227 DCHECK(!cell->IsTheHole(isolate_)); |
| 228 property_details_ = cell->property_details(); |
| 229 PropertyCell::PrepareForValue(dictionary, dictionary_entry(), value, |
| 230 property_details_); |
| 231 return; |
| 232 } |
223 if (!holder->HasFastProperties()) return; | 233 if (!holder->HasFastProperties()) return; |
224 | 234 |
225 Handle<Map> old_map(holder->map(), isolate_); | 235 Handle<Map> old_map(holder->map(), isolate_); |
226 Handle<Map> new_map = | 236 Handle<Map> new_map = |
227 Map::PrepareForDataProperty(old_map, descriptor_number(), value); | 237 Map::PrepareForDataProperty(old_map, descriptor_number(), value); |
228 | 238 |
229 if (old_map.is_identical_to(new_map)) { | 239 if (old_map.is_identical_to(new_map)) { |
230 // Update the property details if the representation was None. | 240 // Update the property details if the representation was None. |
231 if (representation().IsNone()) { | 241 if (representation().IsNone()) { |
232 property_details_ = | 242 property_details_ = |
(...skipping 12 matching lines...) Expand all Loading... |
245 DCHECK(state_ == DATA || state_ == ACCESSOR); | 255 DCHECK(state_ == DATA || state_ == ACCESSOR); |
246 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 256 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
247 Handle<JSObject> holder = GetHolder<JSObject>(); | 257 Handle<JSObject> holder = GetHolder<JSObject>(); |
248 if (IsElement()) { | 258 if (IsElement()) { |
249 DCHECK(!holder->HasFixedTypedArrayElements()); | 259 DCHECK(!holder->HasFixedTypedArrayElements()); |
250 DCHECK(attributes != NONE || !holder->HasFastElements()); | 260 DCHECK(attributes != NONE || !holder->HasFastElements()); |
251 Handle<FixedArrayBase> elements(holder->elements()); | 261 Handle<FixedArrayBase> elements(holder->elements()); |
252 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, | 262 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, |
253 attributes); | 263 attributes); |
254 ReloadPropertyInformation<true>(); | 264 ReloadPropertyInformation<true>(); |
| 265 } else if (holder->HasFastProperties()) { |
| 266 Handle<Map> old_map(holder->map(), isolate_); |
| 267 Handle<Map> new_map = Map::ReconfigureExistingProperty( |
| 268 old_map, descriptor_number(), i::kData, attributes); |
| 269 new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value); |
| 270 JSObject::MigrateToMap(holder, new_map); |
| 271 ReloadPropertyInformation<false>(); |
255 } else { | 272 } else { |
256 if (!holder->HasFastProperties()) { | 273 PropertyDetails details(attributes, v8::internal::DATA, 0, |
257 PropertyDetails details(attributes, v8::internal::DATA, 0, | 274 PropertyCellType::kMutable); |
258 PropertyCellType::kMutable); | 275 if (holder->IsJSGlobalObject()) { |
259 JSObject::SetNormalizedProperty(holder, name(), value, details); | 276 Handle<GlobalDictionary> dictionary(holder->global_dictionary()); |
| 277 |
| 278 Handle<PropertyCell> cell = PropertyCell::PrepareForValue( |
| 279 dictionary, dictionary_entry(), value, details); |
| 280 cell->set_value(*value); |
| 281 property_details_ = cell->property_details(); |
260 } else { | 282 } else { |
261 Handle<Map> old_map(holder->map(), isolate_); | 283 Handle<NameDictionary> dictionary(holder->property_dictionary()); |
262 Handle<Map> new_map = Map::ReconfigureExistingProperty( | 284 PropertyDetails original_details = |
263 old_map, descriptor_number(), i::kData, attributes); | 285 dictionary->DetailsAt(dictionary_entry()); |
264 new_map = | 286 int enumeration_index = original_details.dictionary_index(); |
265 Map::PrepareForDataProperty(new_map, descriptor_number(), value); | 287 DCHECK(enumeration_index > 0); |
266 JSObject::MigrateToMap(holder, new_map); | 288 details = details.set_index(enumeration_index); |
| 289 dictionary->SetEntry(dictionary_entry(), name(), value, details); |
| 290 property_details_ = details; |
267 } | 291 } |
268 ReloadPropertyInformation<false>(); | 292 state_ = DATA; |
269 } | 293 } |
270 | 294 |
271 WriteDataValue(value); | 295 WriteDataValue(value); |
272 | 296 |
273 #if VERIFY_HEAP | 297 #if VERIFY_HEAP |
274 if (FLAG_verify_heap) { | 298 if (FLAG_verify_heap) { |
275 holder->JSObjectVerify(); | 299 holder->JSObjectVerify(); |
276 } | 300 } |
277 #endif | 301 #endif |
278 } | 302 } |
(...skipping 11 matching lines...) Expand all Loading... |
290 DCHECK_NE(INTEGER_INDEXED_EXOTIC, state_); | 314 DCHECK_NE(INTEGER_INDEXED_EXOTIC, state_); |
291 DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype()); | 315 DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype()); |
292 | 316 |
293 Handle<Map> map(receiver->map(), isolate_); | 317 Handle<Map> map(receiver->map(), isolate_); |
294 | 318 |
295 // Dictionary maps can always have additional data properties. | 319 // Dictionary maps can always have additional data properties. |
296 if (map->is_dictionary_map()) { | 320 if (map->is_dictionary_map()) { |
297 state_ = TRANSITION; | 321 state_ = TRANSITION; |
298 if (map->IsJSGlobalObjectMap()) { | 322 if (map->IsJSGlobalObjectMap()) { |
299 // Install a property cell. | 323 // Install a property cell. |
300 auto cell = JSGlobalObject::EnsurePropertyCell( | 324 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver); |
301 Handle<JSGlobalObject>::cast(receiver), name()); | 325 int entry; |
| 326 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( |
| 327 global, name(), PropertyCellType::kUninitialized, &entry); |
| 328 Handle<GlobalDictionary> dictionary(global->global_dictionary(), |
| 329 isolate_); |
302 DCHECK(cell->value()->IsTheHole(isolate_)); | 330 DCHECK(cell->value()->IsTheHole(isolate_)); |
| 331 DCHECK(!value->IsTheHole(isolate_)); |
303 transition_ = cell; | 332 transition_ = cell; |
| 333 // Assign an enumeration index to the property and update |
| 334 // SetNextEnumerationIndex. |
| 335 int index = dictionary->NextEnumerationIndex(); |
| 336 dictionary->SetNextEnumerationIndex(index + 1); |
| 337 property_details_ = PropertyDetails(attributes, i::DATA, index, |
| 338 PropertyCellType::kUninitialized); |
| 339 PropertyCellType new_type = |
| 340 PropertyCell::UpdatedType(cell, value, property_details_); |
| 341 property_details_ = property_details_.set_cell_type(new_type); |
| 342 cell->set_property_details(property_details_); |
| 343 number_ = entry; |
| 344 has_property_ = true; |
304 } else { | 345 } else { |
| 346 // Don't set enumeration index (it will be set during value store). |
| 347 property_details_ = |
| 348 PropertyDetails(attributes, i::DATA, 0, PropertyCellType::kNoCell); |
305 transition_ = map; | 349 transition_ = map; |
306 } | 350 } |
307 return; | 351 return; |
308 } | 352 } |
309 | 353 |
310 Handle<Map> transition = | 354 Handle<Map> transition = |
311 Map::TransitionToDataProperty(map, name_, value, attributes, store_mode); | 355 Map::TransitionToDataProperty(map, name_, value, attributes, store_mode); |
312 state_ = TRANSITION; | 356 state_ = TRANSITION; |
313 transition_ = transition; | 357 transition_ = transition; |
314 | 358 |
315 if (!transition->is_dictionary_map()) { | 359 if (!transition->is_dictionary_map()) { |
316 property_details_ = transition->GetLastDescriptorDetails(); | 360 property_details_ = transition->GetLastDescriptorDetails(); |
317 has_property_ = true; | 361 has_property_ = true; |
318 } | 362 } |
319 } | 363 } |
320 | 364 |
321 void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) { | 365 void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) { |
322 DCHECK_EQ(TRANSITION, state_); | 366 DCHECK_EQ(TRANSITION, state_); |
323 | 367 |
324 DCHECK(receiver.is_identical_to(GetStoreTarget())); | 368 DCHECK(receiver.is_identical_to(GetStoreTarget())); |
325 | |
326 if (receiver->IsJSGlobalObject()) return; | |
327 holder_ = receiver; | 369 holder_ = receiver; |
| 370 if (receiver->IsJSGlobalObject()) { |
| 371 state_ = DATA; |
| 372 return; |
| 373 } |
328 Handle<Map> transition = transition_map(); | 374 Handle<Map> transition = transition_map(); |
329 bool simple_transition = transition->GetBackPointer() == receiver->map(); | 375 bool simple_transition = transition->GetBackPointer() == receiver->map(); |
330 JSObject::MigrateToMap(receiver, transition); | 376 JSObject::MigrateToMap(receiver, transition); |
331 | 377 |
332 if (simple_transition) { | 378 if (simple_transition) { |
333 int number = transition->LastAdded(); | 379 int number = transition->LastAdded(); |
334 number_ = static_cast<uint32_t>(number); | 380 number_ = static_cast<uint32_t>(number); |
335 property_details_ = transition->GetLastDescriptorDetails(); | 381 property_details_ = transition->GetLastDescriptorDetails(); |
336 state_ = DATA; | 382 state_ = DATA; |
| 383 } else if (receiver->map()->is_dictionary_map()) { |
| 384 Handle<NameDictionary> dictionary(receiver->property_dictionary(), |
| 385 isolate_); |
| 386 int entry; |
| 387 dictionary = NameDictionary::Add(dictionary, name(), |
| 388 isolate_->factory()->uninitialized_value(), |
| 389 property_details_, &entry); |
| 390 receiver->set_properties(*dictionary); |
| 391 // Reload details containing proper enumeration index value. |
| 392 property_details_ = dictionary->DetailsAt(entry); |
| 393 number_ = entry; |
| 394 has_property_ = true; |
| 395 state_ = DATA; |
| 396 |
337 } else { | 397 } else { |
338 ReloadPropertyInformation<false>(); | 398 ReloadPropertyInformation<false>(); |
339 } | 399 } |
340 } | 400 } |
341 | 401 |
342 | 402 |
343 void LookupIterator::Delete() { | 403 void LookupIterator::Delete() { |
344 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_); | 404 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_); |
345 if (IsElement()) { | 405 if (IsElement()) { |
346 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 406 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 DCHECK(holder_->HasFastProperties()); | 625 DCHECK(holder_->HasFastProperties()); |
566 DCHECK_EQ(v8::internal::DATA, property_details_.type()); | 626 DCHECK_EQ(v8::internal::DATA, property_details_.type()); |
567 return handle( | 627 return handle( |
568 holder_->map()->instance_descriptors()->GetFieldType(descriptor_number()), | 628 holder_->map()->instance_descriptors()->GetFieldType(descriptor_number()), |
569 isolate_); | 629 isolate_); |
570 } | 630 } |
571 | 631 |
572 | 632 |
573 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { | 633 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { |
574 DCHECK(!IsElement()); | 634 DCHECK(!IsElement()); |
575 Handle<JSObject> holder = GetHolder<JSObject>(); | 635 Handle<JSGlobalObject> holder = GetHolder<JSGlobalObject>(); |
576 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder); | 636 Object* value = holder->global_dictionary()->ValueAt(dictionary_entry()); |
577 Object* value = global->global_dictionary()->ValueAt(dictionary_entry()); | |
578 DCHECK(value->IsPropertyCell()); | 637 DCHECK(value->IsPropertyCell()); |
579 return handle(PropertyCell::cast(value)); | 638 return handle(PropertyCell::cast(value), isolate_); |
580 } | 639 } |
581 | 640 |
582 | 641 |
583 Handle<Object> LookupIterator::GetAccessors() const { | 642 Handle<Object> LookupIterator::GetAccessors() const { |
584 DCHECK_EQ(ACCESSOR, state_); | 643 DCHECK_EQ(ACCESSOR, state_); |
585 return FetchValue(); | 644 return FetchValue(); |
586 } | 645 } |
587 | 646 |
588 | 647 |
589 Handle<Object> LookupIterator::GetDataValue() const { | 648 Handle<Object> LookupIterator::GetDataValue() const { |
(...skipping 11 matching lines...) Expand all Loading... |
601 ElementsAccessor* accessor = object->GetElementsAccessor(); | 660 ElementsAccessor* accessor = object->GetElementsAccessor(); |
602 accessor->Set(object, number_, *value); | 661 accessor->Set(object, number_, *value); |
603 } else if (holder->HasFastProperties()) { | 662 } else if (holder->HasFastProperties()) { |
604 if (property_details_.type() == v8::internal::DATA) { | 663 if (property_details_.type() == v8::internal::DATA) { |
605 JSObject::cast(*holder)->WriteToField(descriptor_number(), | 664 JSObject::cast(*holder)->WriteToField(descriptor_number(), |
606 property_details_, *value); | 665 property_details_, *value); |
607 } else { | 666 } else { |
608 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); | 667 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); |
609 } | 668 } |
610 } else if (holder->IsJSGlobalObject()) { | 669 } else if (holder->IsJSGlobalObject()) { |
611 Handle<GlobalDictionary> property_dictionary = | 670 GlobalDictionary* dictionary = JSObject::cast(*holder)->global_dictionary(); |
612 handle(JSObject::cast(*holder)->global_dictionary()); | 671 Object* cell = dictionary->ValueAt(dictionary_entry()); |
613 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, | 672 DCHECK(cell->IsPropertyCell()); |
614 property_details_); | 673 PropertyCell::cast(cell)->set_value(*value); |
615 } else { | 674 } else { |
616 NameDictionary* property_dictionary = holder->property_dictionary(); | 675 NameDictionary* dictionary = holder->property_dictionary(); |
617 property_dictionary->ValueAtPut(dictionary_entry(), *value); | 676 dictionary->ValueAtPut(dictionary_entry(), *value); |
618 } | 677 } |
619 } | 678 } |
620 | 679 |
621 template <bool is_element> | 680 template <bool is_element> |
622 bool LookupIterator::SkipInterceptor(JSObject* holder) { | 681 bool LookupIterator::SkipInterceptor(JSObject* holder) { |
623 auto info = GetInterceptor<is_element>(holder); | 682 auto info = GetInterceptor<is_element>(holder); |
624 // TODO(dcarney): check for symbol/can_intercept_symbols here as well. | 683 // TODO(dcarney): check for symbol/can_intercept_symbols here as well. |
625 if (info->non_masking()) { | 684 if (info->non_masking()) { |
626 switch (interceptor_state_) { | 685 switch (interceptor_state_) { |
627 case InterceptorState::kUninitialized: | 686 case InterceptorState::kUninitialized: |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 : access_check_info->named_interceptor(); | 827 : access_check_info->named_interceptor(); |
769 if (interceptor) { | 828 if (interceptor) { |
770 return handle(InterceptorInfo::cast(interceptor), isolate_); | 829 return handle(InterceptorInfo::cast(interceptor), isolate_); |
771 } | 830 } |
772 } | 831 } |
773 return Handle<InterceptorInfo>(); | 832 return Handle<InterceptorInfo>(); |
774 } | 833 } |
775 | 834 |
776 } // namespace internal | 835 } // namespace internal |
777 } // namespace v8 | 836 } // namespace v8 |
OLD | NEW |