| 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/lookup.h" | 8 #include "src/lookup.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 number_ = holder->property_dictionary()->FindEntry(name_); | 113 number_ = holder->property_dictionary()->FindEntry(name_); |
| 114 if (number_ == NameDictionary::kNotFound) return false; | 114 if (number_ == NameDictionary::kNotFound) return false; |
| 115 | 115 |
| 116 property_details_ = holder->property_dictionary()->DetailsAt(number_); | 116 property_details_ = holder->property_dictionary()->DetailsAt(number_); |
| 117 // Holes in dictionary cells are absent values. | 117 // Holes in dictionary cells are absent values. |
| 118 if (holder->IsGlobalObject() && | 118 if (holder->IsGlobalObject() && |
| 119 (property_details_.IsDeleted() || FetchValue()->IsTheHole())) { | 119 (property_details_.IsDeleted() || FetchValue()->IsTheHole())) { |
| 120 return false; | 120 return false; |
| 121 } | 121 } |
| 122 } else { | 122 } else { |
| 123 property_details_ = holder_map_->instance_descriptors()->GetDetails( | 123 // Can't use descriptor_number() yet because has_property_ is still false. |
| 124 number_); | 124 property_details_ = |
| 125 holder_map_->instance_descriptors()->GetDetails(number_); |
| 125 } | 126 } |
| 126 | 127 |
| 127 switch (property_details_.type()) { | 128 switch (property_details_.type()) { |
| 128 case v8::internal::FIELD: | 129 case v8::internal::FIELD: |
| 129 case v8::internal::NORMAL: | 130 case v8::internal::NORMAL: |
| 130 case v8::internal::CONSTANT: | 131 case v8::internal::CONSTANT: |
| 131 property_kind_ = DATA; | 132 property_kind_ = DATA; |
| 132 break; | 133 break; |
| 133 case v8::internal::CALLBACKS: | 134 case v8::internal::CALLBACKS: |
| 134 property_kind_ = ACCESSOR; | 135 property_kind_ = ACCESSOR; |
| 135 break; | 136 break; |
| 136 case v8::internal::HANDLER: | 137 case v8::internal::HANDLER: |
| 137 case v8::internal::NONEXISTENT: | 138 case v8::internal::NONEXISTENT: |
| 138 case v8::internal::INTERCEPTOR: | 139 case v8::internal::INTERCEPTOR: |
| 139 UNREACHABLE(); | 140 UNREACHABLE(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 has_property_ = true; | 143 has_property_ = true; |
| 143 return true; | 144 return true; |
| 144 } | 145 } |
| 145 | 146 |
| 146 | 147 |
| 147 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { | 148 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { |
| 148 ASSERT(has_property_); | 149 ASSERT(has_property_); |
| 149 ASSERT(HolderIsReceiver()); | 150 ASSERT(HolderIsReceiverOrHiddenPrototype()); |
| 150 if (property_encoding_ == DICTIONARY) return; | 151 if (property_encoding_ == DICTIONARY) return; |
| 151 holder_map_ = Map::PrepareForDataProperty(holder_map_, number_, value); | 152 holder_map_ = |
| 153 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); |
| 152 JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_); | 154 JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_); |
| 153 // Reload property information. | 155 // Reload property information. |
| 154 if (holder_map_->is_dictionary_map()) { | 156 if (holder_map_->is_dictionary_map()) { |
| 155 property_encoding_ = DICTIONARY; | 157 property_encoding_ = DICTIONARY; |
| 156 } else { | 158 } else { |
| 157 property_encoding_ = DESCRIPTOR; | 159 property_encoding_ = DESCRIPTOR; |
| 158 } | 160 } |
| 159 CHECK(HasProperty()); | 161 CHECK(HasProperty()); |
| 160 } | 162 } |
| 161 | 163 |
| 162 | 164 |
| 163 void LookupIterator::TransitionToDataProperty( | 165 void LookupIterator::TransitionToDataProperty( |
| 164 Handle<Object> value, PropertyAttributes attributes, | 166 Handle<Object> value, PropertyAttributes attributes, |
| 165 Object::StoreFromKeyed store_mode) { | 167 Object::StoreFromKeyed store_mode) { |
| 166 ASSERT(!has_property_ || !HolderIsReceiver()); | 168 ASSERT(!has_property_ || !HolderIsReceiverOrHiddenPrototype()); |
| 167 | 169 |
| 168 // Can only be called when the receiver is a JSObject. JSProxy has to be | 170 // Can only be called when the receiver is a JSObject. JSProxy has to be |
| 169 // handled via a trap. Adding properties to primitive values is not | 171 // handled via a trap. Adding properties to primitive values is not |
| 170 // observable. | 172 // observable. |
| 171 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); | 173 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); |
| 172 | 174 |
| 173 // Properties have to be added to context extension objects through | 175 // Properties have to be added to context extension objects through |
| 174 // SetOwnPropertyIgnoreAttributes. | 176 // SetOwnPropertyIgnoreAttributes. |
| 175 ASSERT(!receiver->IsJSContextExtensionObject()); | 177 ASSERT(!receiver->IsJSContextExtensionObject()); |
| 176 | 178 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 187 | 189 |
| 188 // Reload the information. | 190 // Reload the information. |
| 189 state_ = NOT_FOUND; | 191 state_ = NOT_FOUND; |
| 190 configuration_ = CHECK_OWN_REAL; | 192 configuration_ = CHECK_OWN_REAL; |
| 191 state_ = LookupInHolder(); | 193 state_ = LookupInHolder(); |
| 192 ASSERT(IsFound()); | 194 ASSERT(IsFound()); |
| 193 HasProperty(); | 195 HasProperty(); |
| 194 } | 196 } |
| 195 | 197 |
| 196 | 198 |
| 197 bool LookupIterator::HolderIsReceiver() const { | 199 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { |
| 198 ASSERT(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); | 200 ASSERT(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); |
| 199 DisallowHeapAllocation no_gc; | 201 DisallowHeapAllocation no_gc; |
| 200 Handle<Object> receiver = GetReceiver(); | 202 Handle<Object> receiver = GetReceiver(); |
| 201 if (!receiver->IsJSReceiver()) return false; | 203 if (!receiver->IsJSReceiver()) return false; |
| 202 Object* current = *receiver; | 204 Object* current = *receiver; |
| 203 JSReceiver* holder = *maybe_holder_.ToHandleChecked(); | 205 JSReceiver* holder = *maybe_holder_.ToHandleChecked(); |
| 204 // JSProxy do not occur as hidden prototypes. | 206 // JSProxy do not occur as hidden prototypes. |
| 205 if (current->IsJSProxy()) { | 207 if (current->IsJSProxy()) { |
| 206 return JSReceiver::cast(current) == holder; | 208 return JSReceiver::cast(current) == holder; |
| 207 } | 209 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 221 Handle<JSObject> holder = GetHolder<JSObject>(); | 223 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 222 switch (property_encoding_) { | 224 switch (property_encoding_) { |
| 223 case DICTIONARY: | 225 case DICTIONARY: |
| 224 result = holder->property_dictionary()->ValueAt(number_); | 226 result = holder->property_dictionary()->ValueAt(number_); |
| 225 if (holder->IsGlobalObject()) { | 227 if (holder->IsGlobalObject()) { |
| 226 result = PropertyCell::cast(result)->value(); | 228 result = PropertyCell::cast(result)->value(); |
| 227 } | 229 } |
| 228 break; | 230 break; |
| 229 case DESCRIPTOR: | 231 case DESCRIPTOR: |
| 230 if (property_details_.type() == v8::internal::FIELD) { | 232 if (property_details_.type() == v8::internal::FIELD) { |
| 231 FieldIndex field_index = FieldIndex::ForDescriptor( | 233 FieldIndex field_index = |
| 232 *holder_map_, number_); | 234 FieldIndex::ForDescriptor(*holder_map_, number_); |
| 233 return JSObject::FastPropertyAt( | 235 return JSObject::FastPropertyAt( |
| 234 holder, property_details_.representation(), field_index); | 236 holder, property_details_.representation(), field_index); |
| 235 } | 237 } |
| 236 result = holder_map_->instance_descriptors()->GetValue(number_); | 238 result = holder_map_->instance_descriptors()->GetValue(number_); |
| 237 } | 239 } |
| 238 return handle(result, isolate_); | 240 return handle(result, isolate_); |
| 239 } | 241 } |
| 240 | 242 |
| 241 | 243 |
| 244 FieldIndex LookupIterator::GetFieldIndex() const { |
| 245 ASSERT_EQ(PROPERTY, state_); |
| 246 int index = |
| 247 holder_map()->instance_descriptors()->GetFieldIndex(descriptor_number()); |
| 248 bool is_double = representation().IsDouble(); |
| 249 return FieldIndex::ForPropertyIndex(*holder_map(), index, is_double); |
| 250 } |
| 251 |
| 252 |
| 253 Handle<PropertyCell> LookupIterator::GetPropertyCell() const { |
| 254 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 255 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
| 256 Object* value = global->property_dictionary()->ValueAt(dictionary_entry()); |
| 257 return Handle<PropertyCell>(PropertyCell::cast(value)); |
| 258 } |
| 259 |
| 260 |
| 242 Handle<Object> LookupIterator::GetAccessors() const { | 261 Handle<Object> LookupIterator::GetAccessors() const { |
| 243 ASSERT(has_property_); | 262 ASSERT(has_property_); |
| 244 ASSERT_EQ(ACCESSOR, property_kind_); | 263 ASSERT_EQ(ACCESSOR, property_kind_); |
| 245 return FetchValue(); | 264 return FetchValue(); |
| 246 } | 265 } |
| 247 | 266 |
| 248 | 267 |
| 249 Handle<Object> LookupIterator::GetDataValue() const { | 268 Handle<Object> LookupIterator::GetDataValue() const { |
| 250 ASSERT(has_property_); | 269 ASSERT(has_property_); |
| 251 ASSERT_EQ(DATA, property_kind_); | 270 ASSERT_EQ(DATA, property_kind_); |
| 252 Handle<Object> value = FetchValue(); | 271 Handle<Object> value = FetchValue(); |
| 253 return value; | 272 return value; |
| 254 } | 273 } |
| 255 | 274 |
| 256 | 275 |
| 257 void LookupIterator::WriteDataValue(Handle<Object> value) { | 276 void LookupIterator::WriteDataValue(Handle<Object> value) { |
| 258 ASSERT(is_guaranteed_to_have_holder()); | 277 ASSERT(is_guaranteed_to_have_holder()); |
| 259 ASSERT(has_property_); | 278 ASSERT(has_property_); |
| 260 Handle<JSObject> holder = GetHolder<JSObject>(); | 279 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 261 if (property_encoding_ == DICTIONARY) { | 280 if (property_encoding_ == DICTIONARY) { |
| 262 NameDictionary* property_dictionary = holder->property_dictionary(); | 281 NameDictionary* property_dictionary = holder->property_dictionary(); |
| 263 if (holder->IsGlobalObject()) { | 282 if (holder->IsGlobalObject()) { |
| 264 Handle<PropertyCell> cell( | 283 Handle<PropertyCell> cell( |
| 265 PropertyCell::cast(property_dictionary->ValueAt(number_))); | 284 PropertyCell::cast(property_dictionary->ValueAt(dictionary_entry()))); |
| 266 PropertyCell::SetValueInferType(cell, value); | 285 PropertyCell::SetValueInferType(cell, value); |
| 267 } else { | 286 } else { |
| 268 property_dictionary->ValueAtPut(number_, *value); | 287 property_dictionary->ValueAtPut(dictionary_entry(), *value); |
| 269 } | 288 } |
| 270 } else if (property_details_.type() == v8::internal::FIELD) { | 289 } else if (property_details_.type() == v8::internal::FIELD) { |
| 271 holder->WriteToField(number_, *value); | 290 holder->WriteToField(descriptor_number(), *value); |
| 272 } else { | 291 } else { |
| 273 ASSERT_EQ(v8::internal::CONSTANT, property_details_.type()); | 292 ASSERT_EQ(v8::internal::CONSTANT, property_details_.type()); |
| 274 } | 293 } |
| 275 } | 294 } |
| 276 | 295 |
| 277 | 296 |
| 278 void LookupIterator::InternalizeName() { | 297 void LookupIterator::InternalizeName() { |
| 279 if (name_->IsUniqueName()) return; | 298 if (name_->IsUniqueName()) return; |
| 280 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); | 299 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); |
| 281 } | 300 } |
| 282 } } // namespace v8::internal | 301 } } // namespace v8::internal |
| OLD | NEW |