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 |