| 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 |