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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 state_ = BEFORE_PROPERTY; | 102 state_ = BEFORE_PROPERTY; |
103 interceptor_state_ = InterceptorState::kUninitialized; | 103 interceptor_state_ = InterceptorState::kUninitialized; |
104 state_ = LookupInHolder(*holder_map_, *holder_); | 104 state_ = LookupInHolder(*holder_map_, *holder_); |
105 DCHECK(IsFound() || holder_map_->is_dictionary_map()); | 105 DCHECK(IsFound() || holder_map_->is_dictionary_map()); |
106 } | 106 } |
107 | 107 |
108 | 108 |
109 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { | 109 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { |
110 DCHECK(state_ == DATA || state_ == ACCESSOR); | 110 DCHECK(state_ == DATA || state_ == ACCESSOR); |
111 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 111 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
112 if (holder_map_->is_dictionary_map()) return; | 112 |
113 holder_map_ = | 113 Handle<JSObject> holder = GetHolder<JSObject>(); |
114 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); | 114 |
115 JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_); | 115 if (IsElement()) { |
| 116 ElementsKind old_kind = holder_map_->elements_kind(); |
| 117 holder_map_ = Map::PrepareForDataElement(holder_map_, value); |
| 118 ElementsKind new_kind = holder_map_->elements_kind(); |
| 119 if (new_kind != old_kind) { |
| 120 // TODO(verwaest): Handle element migration in MigrateToMap. |
| 121 JSObject::UpdateAllocationSite(holder, new_kind); |
| 122 if (IsFastDoubleElementsKind(old_kind) != |
| 123 IsFastDoubleElementsKind(new_kind)) { |
| 124 Handle<FixedArrayBase> old_elements(holder->elements()); |
| 125 int capacity = old_elements->length(); |
| 126 Handle<FixedArrayBase> new_elements; |
| 127 if (IsFastDoubleElementsKind(new_kind)) { |
| 128 new_elements = factory()->NewFixedDoubleArray(capacity); |
| 129 } else { |
| 130 new_elements = factory()->NewFixedArray(capacity); |
| 131 } |
| 132 |
| 133 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_kind); |
| 134 accessor->CopyElements(holder, new_elements, old_kind); |
| 135 |
| 136 JSObject::ValidateElements(holder); |
| 137 JSObject::SetMapAndElements(holder, holder_map_, new_elements); |
| 138 |
| 139 if (FLAG_trace_elements_transitions) { |
| 140 JSObject::PrintElementsTransition( |
| 141 stdout, holder, old_kind, old_elements, new_kind, new_elements); |
| 142 } |
| 143 // SetMapAndElements above migrated the object. No reloading of property |
| 144 // infomation is necessary for elements. |
| 145 return; |
| 146 } else if (FLAG_trace_elements_transitions) { |
| 147 Handle<FixedArrayBase> elements(holder->elements()); |
| 148 JSObject::PrintElementsTransition(stdout, holder, old_kind, elements, |
| 149 new_kind, elements); |
| 150 } |
| 151 } |
| 152 |
| 153 // Copy the backing store if it is copy-on-write. |
| 154 if (IsFastSmiOrObjectElementsKind(new_kind)) { |
| 155 JSObject::EnsureWritableFastElements(holder); |
| 156 } |
| 157 |
| 158 } else { |
| 159 if (holder_map_->is_dictionary_map()) return; |
| 160 holder_map_ = |
| 161 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); |
| 162 } |
| 163 |
| 164 JSObject::MigrateToMap(holder, holder_map_); |
116 ReloadPropertyInformation(); | 165 ReloadPropertyInformation(); |
117 } | 166 } |
118 | 167 |
119 | 168 |
120 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, | 169 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, |
121 PropertyAttributes attributes) { | 170 PropertyAttributes attributes) { |
122 DCHECK(state_ == DATA || state_ == ACCESSOR); | 171 DCHECK(state_ == DATA || state_ == ACCESSOR); |
123 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 172 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
124 Handle<JSObject> holder = GetHolder<JSObject>(); | 173 Handle<JSObject> holder = GetHolder<JSObject>(); |
125 if (holder_map_->is_dictionary_map()) { | 174 if (IsElement()) { |
| 175 // TODO(verwaest): Clean up. |
| 176 if (attributes == NONE && !holder->HasDictionaryElements() && |
| 177 !holder->HasDictionaryArgumentsElements()) { |
| 178 ElementsAccessor* accessor = holder->GetElementsAccessor(); |
| 179 accessor->Set(holder, index(), value); |
| 180 } else { |
| 181 DCHECK(holder->HasFastElements() || holder->HasDictionaryElements() || |
| 182 holder->HasSloppyArgumentsElements()); |
| 183 Handle<SeededNumberDictionary> d = JSObject::NormalizeElements(holder); |
| 184 // TODO(verwaest): Move this into NormalizeElements. |
| 185 d->set_requires_slow_elements(); |
| 186 if (holder->HasDictionaryElements()) { |
| 187 JSObject::SetDictionaryElement(holder, index(), value, attributes); |
| 188 } else { |
| 189 JSObject::SetSloppyArgumentsElement(holder, index(), value, attributes); |
| 190 } |
| 191 } |
| 192 } else if (holder_map_->is_dictionary_map()) { |
126 PropertyDetails details(attributes, v8::internal::DATA, 0, | 193 PropertyDetails details(attributes, v8::internal::DATA, 0, |
127 PropertyCellType::kMutable); | 194 PropertyCellType::kMutable); |
128 JSObject::SetNormalizedProperty(holder, name(), value, details); | 195 JSObject::SetNormalizedProperty(holder, name(), value, details); |
129 } else { | 196 } else { |
130 holder_map_ = Map::ReconfigureExistingProperty( | 197 holder_map_ = Map::ReconfigureExistingProperty( |
131 holder_map_, descriptor_number(), i::kData, attributes); | 198 holder_map_, descriptor_number(), i::kData, attributes); |
132 holder_map_ = | 199 holder_map_ = |
133 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); | 200 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); |
134 JSObject::MigrateToMap(holder, holder_map_); | 201 JSObject::MigrateToMap(holder, holder_map_); |
135 } | 202 } |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 } | 412 } |
346 | 413 |
347 | 414 |
348 Handle<Object> LookupIterator::GetDataValue() const { | 415 Handle<Object> LookupIterator::GetDataValue() const { |
349 DCHECK_EQ(DATA, state_); | 416 DCHECK_EQ(DATA, state_); |
350 Handle<Object> value = FetchValue(); | 417 Handle<Object> value = FetchValue(); |
351 return value; | 418 return value; |
352 } | 419 } |
353 | 420 |
354 | 421 |
355 void LookupIterator::WriteDataValue(Handle<Object> value) { | 422 Handle<Object> LookupIterator::WriteDataValue(Handle<Object> value) { |
356 DCHECK_EQ(DATA, state_); | 423 DCHECK_EQ(DATA, state_); |
357 DCHECK(!IsElement()); | |
358 Handle<JSObject> holder = GetHolder<JSObject>(); | 424 Handle<JSObject> holder = GetHolder<JSObject>(); |
359 if (holder->IsGlobalObject()) { | 425 if (IsElement()) { |
| 426 ElementsAccessor* accessor = holder->GetElementsAccessor(); |
| 427 return accessor->Set(holder, index_, value); |
| 428 } else if (holder->IsGlobalObject()) { |
360 Handle<GlobalDictionary> property_dictionary = | 429 Handle<GlobalDictionary> property_dictionary = |
361 handle(holder->global_dictionary()); | 430 handle(holder->global_dictionary()); |
362 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, | 431 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, |
363 property_details_); | 432 property_details_); |
364 } else if (holder_map_->is_dictionary_map()) { | 433 } else if (holder_map_->is_dictionary_map()) { |
365 Handle<NameDictionary> property_dictionary = | 434 Handle<NameDictionary> property_dictionary = |
366 handle(holder->property_dictionary()); | 435 handle(holder->property_dictionary()); |
367 property_dictionary->ValueAtPut(dictionary_entry(), *value); | 436 property_dictionary->ValueAtPut(dictionary_entry(), *value); |
368 } else if (property_details_.type() == v8::internal::DATA) { | 437 } else if (property_details_.type() == v8::internal::DATA) { |
369 holder->WriteToField(descriptor_number(), *value); | 438 holder->WriteToField(descriptor_number(), *value); |
370 } else { | 439 } else { |
371 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); | 440 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); |
372 } | 441 } |
| 442 return value; |
373 } | 443 } |
374 | 444 |
375 | 445 |
376 bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { | 446 bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { |
377 DCHECK(exotic_index_state_ != ExoticIndexState::kNotExotic); | 447 DCHECK(exotic_index_state_ != ExoticIndexState::kNotExotic); |
378 // Currently typed arrays are the only such objects. | 448 // Currently typed arrays are the only such objects. |
379 if (!holder->IsJSTypedArray()) return false; | 449 if (!holder->IsJSTypedArray()) return false; |
380 if (exotic_index_state_ == ExoticIndexState::kExotic) return true; | 450 if (exotic_index_state_ == ExoticIndexState::kExotic) return true; |
381 if (!InternalHolderIsReceiverOrHiddenPrototype()) { | 451 if (!InternalHolderIsReceiverOrHiddenPrototype()) { |
382 exotic_index_state_ = ExoticIndexState::kNotExotic; | 452 exotic_index_state_ = ExoticIndexState::kNotExotic; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 case InterceptorState::kSkipNonMasking: | 504 case InterceptorState::kSkipNonMasking: |
435 return true; | 505 return true; |
436 case InterceptorState::kProcessNonMasking: | 506 case InterceptorState::kProcessNonMasking: |
437 return false; | 507 return false; |
438 } | 508 } |
439 } | 509 } |
440 return interceptor_state_ == InterceptorState::kProcessNonMasking; | 510 return interceptor_state_ == InterceptorState::kProcessNonMasking; |
441 } | 511 } |
442 } // namespace internal | 512 } // namespace internal |
443 } // namespace v8 | 513 } // namespace v8 |
OLD | NEW |