| 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/v8.h" | 5 #include "src/v8.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/lookup.h" | 9 #include "src/lookup.h" |
| 10 #include "src/lookup-inl.h" | 10 #include "src/lookup-inl.h" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 Handle<Map> LookupIterator::GetReceiverMap() const { | 53 Handle<Map> LookupIterator::GetReceiverMap() const { |
| 54 Handle<Object> receiver = GetReceiver(); | 54 Handle<Object> receiver = GetReceiver(); |
| 55 if (receiver->IsNumber()) return isolate_->factory()->heap_number_map(); | 55 if (receiver->IsNumber()) return isolate_->factory()->heap_number_map(); |
| 56 return handle(Handle<HeapObject>::cast(receiver)->map()); | 56 return handle(Handle<HeapObject>::cast(receiver)->map()); |
| 57 } | 57 } |
| 58 | 58 |
| 59 | 59 |
| 60 Handle<JSObject> LookupIterator::GetStoreTarget() const { |
| 61 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); |
| 62 |
| 63 if (receiver->IsJSGlobalProxy()) { |
| 64 PrototypeIterator iter(isolate(), receiver); |
| 65 if (iter.IsAtEnd()) return receiver; |
| 66 return Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 67 } |
| 68 return receiver; |
| 69 } |
| 70 |
| 71 |
| 60 bool LookupIterator::IsBootstrapping() const { | 72 bool LookupIterator::IsBootstrapping() const { |
| 61 return isolate_->bootstrapper()->IsActive(); | 73 return isolate_->bootstrapper()->IsActive(); |
| 62 } | 74 } |
| 63 | 75 |
| 64 | 76 |
| 65 bool LookupIterator::HasAccess(v8::AccessType access_type) const { | 77 bool LookupIterator::HasAccess(v8::AccessType access_type) const { |
| 66 DCHECK_EQ(ACCESS_CHECK, state_); | 78 DCHECK_EQ(ACCESS_CHECK, state_); |
| 67 DCHECK(is_guaranteed_to_have_holder()); | 79 DCHECK(is_guaranteed_to_have_holder()); |
| 68 return isolate_->MayNamedAccess(GetHolder<JSObject>(), name_, access_type); | 80 return isolate_->MayNamedAccess(GetHolder<JSObject>(), name_, access_type); |
| 69 } | 81 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 83 if (holder->IsGlobalObject() && | 95 if (holder->IsGlobalObject() && |
| 84 (property_details_.IsDeleted() || FetchValue()->IsTheHole())) { | 96 (property_details_.IsDeleted() || FetchValue()->IsTheHole())) { |
| 85 return false; | 97 return false; |
| 86 } | 98 } |
| 87 } else { | 99 } else { |
| 88 // Can't use descriptor_number() yet because has_property_ is still false. | 100 // Can't use descriptor_number() yet because has_property_ is still false. |
| 89 property_details_ = | 101 property_details_ = |
| 90 holder_map_->instance_descriptors()->GetDetails(number_); | 102 holder_map_->instance_descriptors()->GetDetails(number_); |
| 91 } | 103 } |
| 92 | 104 |
| 105 LoadPropertyKind(); |
| 106 |
| 107 has_property_ = true; |
| 108 return true; |
| 109 } |
| 110 |
| 111 |
| 112 void LookupIterator::LoadPropertyKind() { |
| 93 switch (property_details_.type()) { | 113 switch (property_details_.type()) { |
| 94 case v8::internal::FIELD: | 114 case v8::internal::FIELD: |
| 95 case v8::internal::NORMAL: | 115 case v8::internal::NORMAL: |
| 96 case v8::internal::CONSTANT: | 116 case v8::internal::CONSTANT: |
| 97 property_kind_ = DATA; | 117 property_kind_ = DATA; |
| 98 break; | 118 break; |
| 99 case v8::internal::CALLBACKS: | 119 case v8::internal::CALLBACKS: |
| 100 property_kind_ = ACCESSOR; | 120 property_kind_ = ACCESSOR; |
| 101 break; | 121 break; |
| 102 case v8::internal::HANDLER: | 122 case v8::internal::HANDLER: |
| 103 case v8::internal::INTERCEPTOR: | 123 case v8::internal::INTERCEPTOR: |
| 104 UNREACHABLE(); | 124 UNREACHABLE(); |
| 105 } | 125 } |
| 106 | |
| 107 has_property_ = true; | |
| 108 return true; | |
| 109 } | 126 } |
| 110 | 127 |
| 111 | 128 |
| 112 void LookupIterator::ReloadPropertyInformation() { | 129 void LookupIterator::ReloadPropertyInformation() { |
| 113 state_ = BEFORE_PROPERTY; | 130 state_ = BEFORE_PROPERTY; |
| 114 state_ = LookupInHolder(*holder_map_); | 131 state_ = LookupInHolder(*holder_map_); |
| 115 DCHECK(IsFound()); | 132 DCHECK(IsFound()); |
| 116 HasProperty(); | 133 HasProperty(); |
| 117 } | 134 } |
| 118 | 135 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 141 | 158 |
| 142 if (holder_map_->is_dictionary_map()) { | 159 if (holder_map_->is_dictionary_map()) { |
| 143 PropertyDetails details(attributes, NORMAL, 0); | 160 PropertyDetails details(attributes, NORMAL, 0); |
| 144 JSObject::SetNormalizedProperty(holder, name(), value, details); | 161 JSObject::SetNormalizedProperty(holder, name(), value, details); |
| 145 } | 162 } |
| 146 | 163 |
| 147 ReloadPropertyInformation(); | 164 ReloadPropertyInformation(); |
| 148 } | 165 } |
| 149 | 166 |
| 150 | 167 |
| 151 void LookupIterator::TransitionToDataProperty( | 168 void LookupIterator::PrepareTransitionToDataProperty( |
| 152 Handle<Object> value, PropertyAttributes attributes, | 169 Handle<Object> value, PropertyAttributes attributes, |
| 153 Object::StoreFromKeyed store_mode) { | 170 Object::StoreFromKeyed store_mode) { |
| 154 DCHECK(!has_property_ || !HolderIsReceiverOrHiddenPrototype()); | 171 if (state_ == TRANSITION) return; |
| 172 DCHECK(!has_property_ || property_kind_ != ACCESSOR); |
| 173 DCHECK(!(has_property_ || state_ == JSPROXY) || |
| 174 !HolderIsReceiverOrHiddenPrototype()); |
| 155 | 175 |
| 156 // Can only be called when the receiver is a JSObject. JSProxy has to be | 176 // Can only be called when the receiver is a JSObject. JSProxy has to be |
| 157 // handled via a trap. Adding properties to primitive values is not | 177 // handled via a trap. Adding properties to primitive values is not |
| 158 // observable. | 178 // observable. |
| 159 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); | 179 Handle<JSObject> receiver = GetStoreTarget(); |
| 160 | 180 |
| 161 if (receiver->IsJSGlobalProxy()) { | 181 if (!name().is_identical_to(isolate()->factory()->hidden_string()) && |
| 162 PrototypeIterator iter(isolate(), receiver); | 182 !receiver->map()->is_extensible()) { |
| 163 receiver = | 183 return; |
| 164 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
| 165 } | 184 } |
| 166 | 185 |
| 186 transition_map_ = Map::TransitionToDataProperty( |
| 187 handle(receiver->map()), name_, value, attributes, store_mode); |
| 188 state_ = TRANSITION; |
| 189 } |
| 190 |
| 191 |
| 192 void LookupIterator::ApplyTransitionToDataProperty() { |
| 193 DCHECK_EQ(TRANSITION, state_); |
| 194 |
| 195 Handle<JSObject> receiver = GetStoreTarget(); |
| 167 maybe_holder_ = receiver; | 196 maybe_holder_ = receiver; |
| 168 holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()), name_, | 197 holder_map_ = transition_map_; |
| 169 value, attributes, store_mode); | |
| 170 JSObject::MigrateToMap(receiver, holder_map_); | 198 JSObject::MigrateToMap(receiver, holder_map_); |
| 171 | |
| 172 ReloadPropertyInformation(); | 199 ReloadPropertyInformation(); |
| 173 } | 200 } |
| 174 | 201 |
| 175 | 202 |
| 176 void LookupIterator::TransitionToAccessorProperty( | 203 void LookupIterator::TransitionToAccessorProperty( |
| 177 AccessorComponent component, Handle<Object> accessor, | 204 AccessorComponent component, Handle<Object> accessor, |
| 178 PropertyAttributes attributes) { | 205 PropertyAttributes attributes) { |
| 179 DCHECK(!accessor->IsNull()); | 206 DCHECK(!accessor->IsNull()); |
| 180 // Can only be called when the receiver is a JSObject. JSProxy has to be | 207 // Can only be called when the receiver is a JSObject. JSProxy has to be |
| 181 // handled via a trap. Adding properties to primitive values is not | 208 // handled via a trap. Adding properties to primitive values is not |
| 182 // observable. | 209 // observable. |
| 183 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); | 210 Handle<JSObject> receiver = GetStoreTarget(); |
| 184 | |
| 185 if (receiver->IsJSGlobalProxy()) { | |
| 186 PrototypeIterator iter(isolate(), receiver); | |
| 187 receiver = | |
| 188 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
| 189 } | |
| 190 | |
| 191 maybe_holder_ = receiver; | 211 maybe_holder_ = receiver; |
| 192 holder_map_ = Map::TransitionToAccessorProperty( | 212 holder_map_ = Map::TransitionToAccessorProperty( |
| 193 handle(receiver->map()), name_, component, accessor, attributes); | 213 handle(receiver->map()), name_, component, accessor, attributes); |
| 194 JSObject::MigrateToMap(receiver, holder_map_); | 214 JSObject::MigrateToMap(receiver, holder_map_); |
| 195 | 215 |
| 196 ReloadPropertyInformation(); | 216 ReloadPropertyInformation(); |
| 197 | 217 |
| 198 if (!holder_map_->is_dictionary_map()) return; | 218 if (!holder_map_->is_dictionary_map()) return; |
| 199 | 219 |
| 200 // We have to deoptimize since accesses to data properties may have been | 220 // We have to deoptimize since accesses to data properties may have been |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 DCHECK(has_property_); | 317 DCHECK(has_property_); |
| 298 DCHECK_EQ(DESCRIPTOR, property_encoding_); | 318 DCHECK_EQ(DESCRIPTOR, property_encoding_); |
| 299 DCHECK_EQ(v8::internal::FIELD, property_details_.type()); | 319 DCHECK_EQ(v8::internal::FIELD, property_details_.type()); |
| 300 int index = | 320 int index = |
| 301 holder_map()->instance_descriptors()->GetFieldIndex(descriptor_number()); | 321 holder_map()->instance_descriptors()->GetFieldIndex(descriptor_number()); |
| 302 bool is_double = representation().IsDouble(); | 322 bool is_double = representation().IsDouble(); |
| 303 return FieldIndex::ForPropertyIndex(*holder_map(), index, is_double); | 323 return FieldIndex::ForPropertyIndex(*holder_map(), index, is_double); |
| 304 } | 324 } |
| 305 | 325 |
| 306 | 326 |
| 327 Handle<HeapType> LookupIterator::GetFieldType() const { |
| 328 DCHECK(has_property_); |
| 329 DCHECK_EQ(DESCRIPTOR, property_encoding_); |
| 330 DCHECK_EQ(v8::internal::FIELD, property_details_.type()); |
| 331 return handle( |
| 332 holder_map()->instance_descriptors()->GetFieldType(descriptor_number()), |
| 333 isolate_); |
| 334 } |
| 335 |
| 336 |
| 307 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { | 337 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { |
| 308 Handle<JSObject> holder = GetHolder<JSObject>(); | 338 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 309 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | 339 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 310 Object* value = global->property_dictionary()->ValueAt(dictionary_entry()); | 340 Object* value = global->property_dictionary()->ValueAt(dictionary_entry()); |
| 311 return Handle<PropertyCell>(PropertyCell::cast(value)); | 341 return Handle<PropertyCell>(PropertyCell::cast(value)); |
| 312 } | 342 } |
| 313 | 343 |
| 314 | 344 |
| 315 Handle<Object> LookupIterator::GetAccessors() const { | 345 Handle<Object> LookupIterator::GetAccessors() const { |
| 316 DCHECK(has_property_); | 346 DCHECK(has_property_); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 346 DCHECK_EQ(v8::internal::CONSTANT, property_details_.type()); | 376 DCHECK_EQ(v8::internal::CONSTANT, property_details_.type()); |
| 347 } | 377 } |
| 348 } | 378 } |
| 349 | 379 |
| 350 | 380 |
| 351 void LookupIterator::InternalizeName() { | 381 void LookupIterator::InternalizeName() { |
| 352 if (name_->IsUniqueName()) return; | 382 if (name_->IsUniqueName()) return; |
| 353 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); | 383 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); |
| 354 } | 384 } |
| 355 } } // namespace v8::internal | 385 } } // namespace v8::internal |
| OLD | NEW |