| 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 } | 46 } |
| 47 | 47 |
| 48 | 48 |
| 49 void LookupIterator::Next() { | 49 void LookupIterator::Next() { |
| 50 DCHECK_NE(JSPROXY, state_); | 50 DCHECK_NE(JSPROXY, state_); |
| 51 DCHECK_NE(TRANSITION, state_); | 51 DCHECK_NE(TRANSITION, state_); |
| 52 DisallowHeapAllocation no_gc; | 52 DisallowHeapAllocation no_gc; |
| 53 has_property_ = false; | 53 has_property_ = false; |
| 54 | 54 |
| 55 JSReceiver* holder = *holder_; | 55 JSReceiver* holder = *holder_; |
| 56 Map* map = *holder_map_; | 56 Map* map = holder->map(); |
| 57 | 57 |
| 58 // Perform lookup on current holder. | 58 // Perform lookup on current holder. |
| 59 state_ = LookupInHolder(map, holder); | 59 state_ = LookupInHolder(map, holder); |
| 60 if (IsFound()) return; | 60 if (IsFound()) return; |
| 61 | 61 |
| 62 // Continue lookup if lookup on current holder failed. | 62 // Continue lookup if lookup on current holder failed. |
| 63 do { | 63 do { |
| 64 JSReceiver* maybe_holder = NextHolder(map); | 64 JSReceiver* maybe_holder = NextHolder(map); |
| 65 if (maybe_holder == nullptr) { | 65 if (maybe_holder == nullptr) { |
| 66 if (interceptor_state_ == InterceptorState::kSkipNonMasking) { | 66 if (interceptor_state_ == InterceptorState::kSkipNonMasking) { |
| 67 RestartLookupForNonMaskingInterceptors(); | 67 RestartLookupForNonMaskingInterceptors(); |
| 68 return; | 68 return; |
| 69 } | 69 } |
| 70 break; | 70 break; |
| 71 } | 71 } |
| 72 holder = maybe_holder; | 72 holder = maybe_holder; |
| 73 map = holder->map(); | 73 map = holder->map(); |
| 74 state_ = LookupInHolder(map, holder); | 74 state_ = LookupInHolder(map, holder); |
| 75 } while (!IsFound()); | 75 } while (!IsFound()); |
| 76 | 76 |
| 77 if (holder != *holder_) { | 77 if (holder != *holder_) holder_ = handle(holder, isolate_); |
| 78 holder_ = handle(holder, isolate_); | |
| 79 holder_map_ = handle(map, isolate_); | |
| 80 } | |
| 81 } | 78 } |
| 82 | 79 |
| 83 | 80 |
| 84 void LookupIterator::RestartInternal(InterceptorState interceptor_state) { | 81 void LookupIterator::RestartInternal(InterceptorState interceptor_state) { |
| 85 state_ = NOT_FOUND; | 82 state_ = NOT_FOUND; |
| 86 interceptor_state_ = interceptor_state; | 83 interceptor_state_ = interceptor_state; |
| 87 property_details_ = PropertyDetails::Empty(); | 84 property_details_ = PropertyDetails::Empty(); |
| 88 holder_ = initial_holder_; | 85 holder_ = initial_holder_; |
| 89 holder_map_ = handle(holder_->map(), isolate_); | |
| 90 number_ = DescriptorArray::kNotFound; | 86 number_ = DescriptorArray::kNotFound; |
| 91 Next(); | 87 Next(); |
| 92 } | 88 } |
| 93 | 89 |
| 94 | 90 |
| 95 // static | 91 // static |
| 96 Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver( | 92 Handle<JSReceiver> LookupIterator::GetRootForNonJSReceiver( |
| 97 Isolate* isolate, Handle<Object> receiver, uint32_t index) { | 93 Isolate* isolate, Handle<Object> receiver, uint32_t index) { |
| 98 // Strings are the only objects with properties (only elements) directly on | 94 // Strings are the only objects with properties (only elements) directly on |
| 99 // 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. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 bool LookupIterator::HasAccess() const { | 131 bool LookupIterator::HasAccess() const { |
| 136 DCHECK_EQ(ACCESS_CHECK, state_); | 132 DCHECK_EQ(ACCESS_CHECK, state_); |
| 137 return isolate_->MayAccess(handle(isolate_->context()), | 133 return isolate_->MayAccess(handle(isolate_->context()), |
| 138 GetHolder<JSObject>()); | 134 GetHolder<JSObject>()); |
| 139 } | 135 } |
| 140 | 136 |
| 141 | 137 |
| 142 void LookupIterator::ReloadPropertyInformation() { | 138 void LookupIterator::ReloadPropertyInformation() { |
| 143 state_ = BEFORE_PROPERTY; | 139 state_ = BEFORE_PROPERTY; |
| 144 interceptor_state_ = InterceptorState::kUninitialized; | 140 interceptor_state_ = InterceptorState::kUninitialized; |
| 145 state_ = LookupInHolder(*holder_map_, *holder_); | 141 state_ = LookupInHolder(holder_->map(), *holder_); |
| 146 DCHECK(IsFound() || holder_map_->is_dictionary_map()); | 142 DCHECK(IsFound() || !holder_->HasFastProperties()); |
| 147 } | 143 } |
| 148 | 144 |
| 149 | 145 |
| 150 void LookupIterator::ReloadHolderMap() { | |
| 151 DCHECK_EQ(DATA, state_); | |
| 152 DCHECK(IsElement()); | |
| 153 DCHECK(JSObject::cast(*holder_)->HasFixedTypedArrayElements()); | |
| 154 if (*holder_map_ != holder_->map()) { | |
| 155 holder_map_ = handle(holder_->map(), isolate_); | |
| 156 } | |
| 157 } | |
| 158 | |
| 159 | |
| 160 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { | 146 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { |
| 161 DCHECK(state_ == DATA || state_ == ACCESSOR); | 147 DCHECK(state_ == DATA || state_ == ACCESSOR); |
| 162 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 148 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
| 163 | 149 |
| 164 Handle<JSObject> holder = GetHolder<JSObject>(); | 150 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 165 | 151 |
| 166 if (IsElement()) { | 152 if (IsElement()) { |
| 167 ElementsKind kind = holder_map_->elements_kind(); | 153 ElementsKind kind = holder->GetElementsKind(); |
| 168 ElementsKind to = value->OptimalElementsKind(); | 154 ElementsKind to = value->OptimalElementsKind(); |
| 169 if (IsHoleyElementsKind(kind)) to = GetHoleyElementsKind(to); | 155 if (IsHoleyElementsKind(kind)) to = GetHoleyElementsKind(to); |
| 170 to = GetMoreGeneralElementsKind(kind, to); | 156 to = GetMoreGeneralElementsKind(kind, to); |
| 171 | 157 |
| 172 if (kind != to) { | 158 if (kind != to) { |
| 173 JSObject::TransitionElementsKind(holder, to); | 159 JSObject::TransitionElementsKind(holder, to); |
| 174 holder_map_ = handle(holder->map(), isolate_); | |
| 175 } | 160 } |
| 176 | 161 |
| 177 // Copy the backing store if it is copy-on-write. | 162 // Copy the backing store if it is copy-on-write. |
| 178 if (IsFastSmiOrObjectElementsKind(to)) { | 163 if (IsFastSmiOrObjectElementsKind(to)) { |
| 179 JSObject::EnsureWritableFastElements(holder); | 164 JSObject::EnsureWritableFastElements(holder); |
| 180 } | 165 } |
| 181 | |
| 182 if (kind == to) return; | |
| 183 | |
| 184 } else if (holder_map_->is_dictionary_map()) { | |
| 185 return; | 166 return; |
| 186 } else { | |
| 187 holder_map_ = | |
| 188 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); | |
| 189 | |
| 190 if (holder->map() == *holder_map_) { | |
| 191 // Update the property details if the representation was None. | |
| 192 if (representation().IsNone()) { | |
| 193 property_details_ = holder_map_->instance_descriptors()->GetDetails( | |
| 194 descriptor_number()); | |
| 195 } | |
| 196 return; | |
| 197 } | |
| 198 } | 167 } |
| 199 | 168 |
| 200 JSObject::MigrateToMap(holder, holder_map_); | 169 if (!holder->HasFastProperties()) return; |
| 170 |
| 171 Handle<Map> old_map(holder->map(), isolate_); |
| 172 Handle<Map> new_map = |
| 173 Map::PrepareForDataProperty(old_map, descriptor_number(), value); |
| 174 |
| 175 if (old_map.is_identical_to(new_map)) { |
| 176 // Update the property details if the representation was None. |
| 177 if (representation().IsNone()) { |
| 178 property_details_ = |
| 179 new_map->instance_descriptors()->GetDetails(descriptor_number()); |
| 180 } |
| 181 return; |
| 182 } |
| 183 |
| 184 JSObject::MigrateToMap(holder, new_map); |
| 201 ReloadPropertyInformation(); | 185 ReloadPropertyInformation(); |
| 202 } | 186 } |
| 203 | 187 |
| 204 | 188 |
| 205 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, | 189 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, |
| 206 PropertyAttributes attributes) { | 190 PropertyAttributes attributes) { |
| 207 DCHECK(state_ == DATA || state_ == ACCESSOR); | 191 DCHECK(state_ == DATA || state_ == ACCESSOR); |
| 208 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 192 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
| 209 Handle<JSObject> holder = GetHolder<JSObject>(); | 193 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 210 if (IsElement()) { | 194 if (IsElement()) { |
| 211 DCHECK(!holder->HasFixedTypedArrayElements()); | 195 DCHECK(!holder->HasFixedTypedArrayElements()); |
| 212 DCHECK(attributes != NONE || !holder->HasFastElements()); | 196 DCHECK(attributes != NONE || !holder->HasFastElements()); |
| 213 Handle<FixedArrayBase> elements(holder->elements()); | 197 Handle<FixedArrayBase> elements(holder->elements()); |
| 214 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, | 198 holder->GetElementsAccessor()->Reconfigure(holder, elements, number_, value, |
| 215 attributes); | 199 attributes); |
| 216 } else if (holder_map_->is_dictionary_map()) { | 200 } else if (!holder->HasFastProperties()) { |
| 217 PropertyDetails details(attributes, v8::internal::DATA, 0, | 201 PropertyDetails details(attributes, v8::internal::DATA, 0, |
| 218 PropertyCellType::kMutable); | 202 PropertyCellType::kMutable); |
| 219 JSObject::SetNormalizedProperty(holder, name(), value, details); | 203 JSObject::SetNormalizedProperty(holder, name(), value, details); |
| 220 } else { | 204 } else { |
| 221 holder_map_ = Map::ReconfigureExistingProperty( | 205 Handle<Map> old_map(holder->map(), isolate_); |
| 222 holder_map_, descriptor_number(), i::kData, attributes); | 206 Handle<Map> new_map = Map::ReconfigureExistingProperty( |
| 223 holder_map_ = | 207 old_map, descriptor_number(), i::kData, attributes); |
| 224 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); | 208 new_map = Map::PrepareForDataProperty(new_map, descriptor_number(), value); |
| 225 JSObject::MigrateToMap(holder, holder_map_); | 209 JSObject::MigrateToMap(holder, new_map); |
| 226 } | 210 } |
| 227 | 211 |
| 228 ReloadPropertyInformation(); | 212 ReloadPropertyInformation(); |
| 229 WriteDataValue(value); | 213 WriteDataValue(value); |
| 230 | 214 |
| 231 #if VERIFY_HEAP | 215 #if VERIFY_HEAP |
| 232 if (FLAG_verify_heap) { | 216 if (FLAG_verify_heap) { |
| 233 holder->JSObjectVerify(); | 217 holder->JSObjectVerify(); |
| 234 } | 218 } |
| 235 #endif | 219 #endif |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 | 263 |
| 280 void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) { | 264 void LookupIterator::ApplyTransitionToDataProperty(Handle<JSObject> receiver) { |
| 281 DCHECK_EQ(TRANSITION, state_); | 265 DCHECK_EQ(TRANSITION, state_); |
| 282 | 266 |
| 283 DCHECK(receiver.is_identical_to(GetStoreTarget())); | 267 DCHECK(receiver.is_identical_to(GetStoreTarget())); |
| 284 | 268 |
| 285 if (receiver->IsJSGlobalObject()) return; | 269 if (receiver->IsJSGlobalObject()) return; |
| 286 holder_ = receiver; | 270 holder_ = receiver; |
| 287 Handle<Map> transition = transition_map(); | 271 Handle<Map> transition = transition_map(); |
| 288 bool simple_transition = transition->GetBackPointer() == receiver->map(); | 272 bool simple_transition = transition->GetBackPointer() == receiver->map(); |
| 289 holder_map_ = transition; | 273 JSObject::MigrateToMap(receiver, transition); |
| 290 JSObject::MigrateToMap(receiver, holder_map_); | |
| 291 | 274 |
| 292 if (simple_transition) { | 275 if (simple_transition) { |
| 293 int number = transition->LastAdded(); | 276 int number = transition->LastAdded(); |
| 294 number_ = static_cast<uint32_t>(number); | 277 number_ = static_cast<uint32_t>(number); |
| 295 property_details_ = transition->GetLastDescriptorDetails(); | 278 property_details_ = transition->GetLastDescriptorDetails(); |
| 296 state_ = DATA; | 279 state_ = DATA; |
| 297 } else { | 280 } else { |
| 298 ReloadPropertyInformation(); | 281 ReloadPropertyInformation(); |
| 299 } | 282 } |
| 300 } | 283 } |
| 301 | 284 |
| 302 | 285 |
| 303 void LookupIterator::Delete() { | 286 void LookupIterator::Delete() { |
| 304 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_); | 287 Handle<JSReceiver> holder = Handle<JSReceiver>::cast(holder_); |
| 305 if (IsElement()) { | 288 if (IsElement()) { |
| 306 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 289 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 307 ElementsAccessor* accessor = object->GetElementsAccessor(); | 290 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 308 accessor->Delete(object, number_); | 291 accessor->Delete(object, number_); |
| 309 } else { | 292 } else { |
| 310 PropertyNormalizationMode mode = holder->map()->is_prototype_map() | 293 PropertyNormalizationMode mode = holder->map()->is_prototype_map() |
| 311 ? KEEP_INOBJECT_PROPERTIES | 294 ? KEEP_INOBJECT_PROPERTIES |
| 312 : CLEAR_INOBJECT_PROPERTIES; | 295 : CLEAR_INOBJECT_PROPERTIES; |
| 313 | 296 |
| 314 if (holder->HasFastProperties()) { | 297 if (holder->HasFastProperties()) { |
| 315 JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0, | 298 JSObject::NormalizeProperties(Handle<JSObject>::cast(holder), mode, 0, |
| 316 "DeletingProperty"); | 299 "DeletingProperty"); |
| 317 holder_map_ = handle(holder->map(), isolate_); | |
| 318 ReloadPropertyInformation(); | 300 ReloadPropertyInformation(); |
| 319 } | 301 } |
| 320 // TODO(verwaest): Get rid of the name_ argument. | 302 // TODO(verwaest): Get rid of the name_ argument. |
| 321 JSReceiver::DeleteNormalizedProperty(holder, name_, number_); | 303 JSReceiver::DeleteNormalizedProperty(holder, name_, number_); |
| 322 if (holder->IsJSObject()) { | 304 if (holder->IsJSObject()) { |
| 323 JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder)); | 305 JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder)); |
| 324 } | 306 } |
| 325 } | 307 } |
| 326 state_ = NOT_FOUND; | 308 state_ = NOT_FOUND; |
| 327 } | 309 } |
| 328 | 310 |
| 329 | 311 |
| 330 void LookupIterator::TransitionToAccessorProperty( | 312 void LookupIterator::TransitionToAccessorProperty( |
| 331 AccessorComponent component, Handle<Object> accessor, | 313 AccessorComponent component, Handle<Object> accessor, |
| 332 PropertyAttributes attributes) { | 314 PropertyAttributes attributes) { |
| 333 DCHECK(!accessor->IsNull()); | 315 DCHECK(!accessor->IsNull()); |
| 334 // Can only be called when the receiver is a JSObject. JSProxy has to be | 316 // Can only be called when the receiver is a JSObject. JSProxy has to be |
| 335 // handled via a trap. Adding properties to primitive values is not | 317 // handled via a trap. Adding properties to primitive values is not |
| 336 // observable. | 318 // observable. |
| 337 Handle<JSObject> receiver = GetStoreTarget(); | 319 Handle<JSObject> receiver = GetStoreTarget(); |
| 338 | 320 |
| 339 if (!IsElement() && !receiver->map()->is_dictionary_map()) { | 321 if (!IsElement() && !receiver->map()->is_dictionary_map()) { |
| 340 holder_ = receiver; | 322 holder_ = receiver; |
| 341 holder_map_ = Map::TransitionToAccessorProperty( | 323 Handle<Map> old_map(receiver->map(), isolate_); |
| 342 handle(receiver->map(), isolate_), name_, component, accessor, | 324 Handle<Map> new_map = Map::TransitionToAccessorProperty( |
| 343 attributes); | 325 old_map, name_, component, accessor, attributes); |
| 344 JSObject::MigrateToMap(receiver, holder_map_); | 326 JSObject::MigrateToMap(receiver, new_map); |
| 345 | 327 |
| 346 ReloadPropertyInformation(); | 328 ReloadPropertyInformation(); |
| 347 | 329 |
| 348 if (!holder_map_->is_dictionary_map()) return; | 330 if (!new_map->is_dictionary_map()) return; |
| 349 } | 331 } |
| 350 | 332 |
| 351 Handle<AccessorPair> pair; | 333 Handle<AccessorPair> pair; |
| 352 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) { | 334 if (state() == ACCESSOR && GetAccessors()->IsAccessorPair()) { |
| 353 pair = Handle<AccessorPair>::cast(GetAccessors()); | 335 pair = Handle<AccessorPair>::cast(GetAccessors()); |
| 354 // If the component and attributes are identical, nothing has to be done. | 336 // If the component and attributes are identical, nothing has to be done. |
| 355 if (pair->get(component) == *accessor) { | 337 if (pair->get(component) == *accessor) { |
| 356 if (property_details().attributes() == attributes) return; | 338 if (property_details().attributes() == attributes) return; |
| 357 } else { | 339 } else { |
| 358 pair = AccessorPair::Copy(pair); | 340 pair = AccessorPair::Copy(pair); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 ? KEEP_INOBJECT_PROPERTIES | 390 ? KEEP_INOBJECT_PROPERTIES |
| 409 : CLEAR_INOBJECT_PROPERTIES; | 391 : CLEAR_INOBJECT_PROPERTIES; |
| 410 // Normalize object to make this operation simple. | 392 // Normalize object to make this operation simple. |
| 411 JSObject::NormalizeProperties(receiver, mode, 0, | 393 JSObject::NormalizeProperties(receiver, mode, 0, |
| 412 "TransitionToAccessorPair"); | 394 "TransitionToAccessorPair"); |
| 413 | 395 |
| 414 JSObject::SetNormalizedProperty(receiver, name_, pair, details); | 396 JSObject::SetNormalizedProperty(receiver, name_, pair, details); |
| 415 JSObject::ReoptimizeIfPrototype(receiver); | 397 JSObject::ReoptimizeIfPrototype(receiver); |
| 416 } | 398 } |
| 417 | 399 |
| 418 holder_map_ = handle(receiver->map(), isolate_); | |
| 419 ReloadPropertyInformation(); | 400 ReloadPropertyInformation(); |
| 420 } | 401 } |
| 421 | 402 |
| 422 | 403 |
| 423 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { | 404 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { |
| 424 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); | 405 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); |
| 425 // Optimization that only works if configuration_ is not mutable. | 406 // Optimization that only works if configuration_ is not mutable. |
| 426 if (!check_prototype_chain()) return true; | 407 if (!check_prototype_chain()) return true; |
| 427 DisallowHeapAllocation no_gc; | 408 DisallowHeapAllocation no_gc; |
| 428 if (!receiver_->IsJSReceiver()) return false; | 409 if (!receiver_->IsJSReceiver()) return false; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 442 return false; | 423 return false; |
| 443 } | 424 } |
| 444 | 425 |
| 445 | 426 |
| 446 Handle<Object> LookupIterator::FetchValue() const { | 427 Handle<Object> LookupIterator::FetchValue() const { |
| 447 Object* result = NULL; | 428 Object* result = NULL; |
| 448 if (IsElement()) { | 429 if (IsElement()) { |
| 449 Handle<JSObject> holder = GetHolder<JSObject>(); | 430 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 450 ElementsAccessor* accessor = holder->GetElementsAccessor(); | 431 ElementsAccessor* accessor = holder->GetElementsAccessor(); |
| 451 return accessor->Get(holder, number_); | 432 return accessor->Get(holder, number_); |
| 452 } else if (holder_map_->IsJSGlobalObjectMap()) { | 433 } else if (holder_->IsJSGlobalObject()) { |
| 453 Handle<JSObject> holder = GetHolder<JSObject>(); | 434 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 454 result = holder->global_dictionary()->ValueAt(number_); | 435 result = holder->global_dictionary()->ValueAt(number_); |
| 455 DCHECK(result->IsPropertyCell()); | 436 DCHECK(result->IsPropertyCell()); |
| 456 result = PropertyCell::cast(result)->value(); | 437 result = PropertyCell::cast(result)->value(); |
| 457 } else if (holder_map_->is_dictionary_map()) { | 438 } else if (!holder_->HasFastProperties()) { |
| 458 result = holder_->property_dictionary()->ValueAt(number_); | 439 result = holder_->property_dictionary()->ValueAt(number_); |
| 459 } else if (property_details_.type() == v8::internal::DATA) { | 440 } else if (property_details_.type() == v8::internal::DATA) { |
| 460 Handle<JSObject> holder = GetHolder<JSObject>(); | 441 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 461 FieldIndex field_index = FieldIndex::ForDescriptor(*holder_map_, number_); | 442 FieldIndex field_index = FieldIndex::ForDescriptor(holder->map(), number_); |
| 462 return JSObject::FastPropertyAt(holder, property_details_.representation(), | 443 return JSObject::FastPropertyAt(holder, property_details_.representation(), |
| 463 field_index); | 444 field_index); |
| 464 } else { | 445 } else { |
| 465 result = holder_map_->instance_descriptors()->GetValue(number_); | 446 result = holder_->map()->instance_descriptors()->GetValue(number_); |
| 466 } | 447 } |
| 467 return handle(result, isolate_); | 448 return handle(result, isolate_); |
| 468 } | 449 } |
| 469 | 450 |
| 470 | 451 |
| 471 int LookupIterator::GetAccessorIndex() const { | 452 int LookupIterator::GetAccessorIndex() const { |
| 472 DCHECK(has_property_); | 453 DCHECK(has_property_); |
| 473 DCHECK(!holder_map_->is_dictionary_map()); | 454 DCHECK(holder_->HasFastProperties()); |
| 474 DCHECK_EQ(v8::internal::ACCESSOR_CONSTANT, property_details_.type()); | 455 DCHECK_EQ(v8::internal::ACCESSOR_CONSTANT, property_details_.type()); |
| 475 return descriptor_number(); | 456 return descriptor_number(); |
| 476 } | 457 } |
| 477 | 458 |
| 478 | 459 |
| 479 int LookupIterator::GetConstantIndex() const { | 460 int LookupIterator::GetConstantIndex() const { |
| 480 DCHECK(has_property_); | 461 DCHECK(has_property_); |
| 481 DCHECK(!holder_map_->is_dictionary_map()); | 462 DCHECK(holder_->HasFastProperties()); |
| 482 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); | 463 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); |
| 483 DCHECK(!IsElement()); | 464 DCHECK(!IsElement()); |
| 484 return descriptor_number(); | 465 return descriptor_number(); |
| 485 } | 466 } |
| 486 | 467 |
| 487 | 468 |
| 488 FieldIndex LookupIterator::GetFieldIndex() const { | 469 FieldIndex LookupIterator::GetFieldIndex() const { |
| 489 DCHECK(has_property_); | 470 DCHECK(has_property_); |
| 490 DCHECK(!holder_map_->is_dictionary_map()); | 471 DCHECK(holder_->HasFastProperties()); |
| 491 DCHECK_EQ(v8::internal::DATA, property_details_.type()); | 472 DCHECK_EQ(v8::internal::DATA, property_details_.type()); |
| 492 DCHECK(!IsElement()); | 473 DCHECK(!IsElement()); |
| 474 Map* holder_map = holder_->map(); |
| 493 int index = | 475 int index = |
| 494 holder_map_->instance_descriptors()->GetFieldIndex(descriptor_number()); | 476 holder_map->instance_descriptors()->GetFieldIndex(descriptor_number()); |
| 495 bool is_double = representation().IsDouble(); | 477 bool is_double = representation().IsDouble(); |
| 496 return FieldIndex::ForPropertyIndex(*holder_map_, index, is_double); | 478 return FieldIndex::ForPropertyIndex(holder_map, index, is_double); |
| 497 } | 479 } |
| 498 | 480 |
| 499 Handle<FieldType> LookupIterator::GetFieldType() const { | 481 Handle<FieldType> LookupIterator::GetFieldType() const { |
| 500 DCHECK(has_property_); | 482 DCHECK(has_property_); |
| 501 DCHECK(!holder_map_->is_dictionary_map()); | 483 DCHECK(holder_->HasFastProperties()); |
| 502 DCHECK_EQ(v8::internal::DATA, property_details_.type()); | 484 DCHECK_EQ(v8::internal::DATA, property_details_.type()); |
| 503 return handle( | 485 return handle( |
| 504 holder_map_->instance_descriptors()->GetFieldType(descriptor_number()), | 486 holder_->map()->instance_descriptors()->GetFieldType(descriptor_number()), |
| 505 isolate_); | 487 isolate_); |
| 506 } | 488 } |
| 507 | 489 |
| 508 | 490 |
| 509 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { | 491 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { |
| 510 DCHECK(!IsElement()); | 492 DCHECK(!IsElement()); |
| 511 Handle<JSObject> holder = GetHolder<JSObject>(); | 493 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 512 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder); | 494 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder); |
| 513 Object* value = global->global_dictionary()->ValueAt(dictionary_entry()); | 495 Object* value = global->global_dictionary()->ValueAt(dictionary_entry()); |
| 514 DCHECK(value->IsPropertyCell()); | 496 DCHECK(value->IsPropertyCell()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 534 Handle<JSReceiver> holder = GetHolder<JSReceiver>(); | 516 Handle<JSReceiver> holder = GetHolder<JSReceiver>(); |
| 535 if (IsElement()) { | 517 if (IsElement()) { |
| 536 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 518 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 537 ElementsAccessor* accessor = object->GetElementsAccessor(); | 519 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 538 accessor->Set(object, number_, *value); | 520 accessor->Set(object, number_, *value); |
| 539 } else if (holder->IsJSGlobalObject()) { | 521 } else if (holder->IsJSGlobalObject()) { |
| 540 Handle<GlobalDictionary> property_dictionary = | 522 Handle<GlobalDictionary> property_dictionary = |
| 541 handle(JSObject::cast(*holder)->global_dictionary()); | 523 handle(JSObject::cast(*holder)->global_dictionary()); |
| 542 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, | 524 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, |
| 543 property_details_); | 525 property_details_); |
| 544 } else if (holder_map_->is_dictionary_map()) { | 526 } else if (!holder->HasFastProperties()) { |
| 545 NameDictionary* property_dictionary = holder->property_dictionary(); | 527 NameDictionary* property_dictionary = holder->property_dictionary(); |
| 546 property_dictionary->ValueAtPut(dictionary_entry(), *value); | 528 property_dictionary->ValueAtPut(dictionary_entry(), *value); |
| 547 } else if (property_details_.type() == v8::internal::DATA) { | 529 } else if (property_details_.type() == v8::internal::DATA) { |
| 548 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); | 530 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); |
| 549 } else { | 531 } else { |
| 550 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); | 532 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); |
| 551 } | 533 } |
| 552 } | 534 } |
| 553 | 535 |
| 554 | 536 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 // Fall through. | 682 // Fall through. |
| 701 default: | 683 default: |
| 702 return NOT_FOUND; | 684 return NOT_FOUND; |
| 703 } | 685 } |
| 704 UNREACHABLE(); | 686 UNREACHABLE(); |
| 705 return state_; | 687 return state_; |
| 706 } | 688 } |
| 707 | 689 |
| 708 } // namespace internal | 690 } // namespace internal |
| 709 } // namespace v8 | 691 } // namespace v8 |
| OLD | NEW |