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/lookup.h" | 9 #include "src/lookup.h" |
9 #include "src/lookup-inl.h" | 10 #include "src/lookup-inl.h" |
10 | 11 |
11 namespace v8 { | 12 namespace v8 { |
12 namespace internal { | 13 namespace internal { |
13 | 14 |
14 | 15 |
15 void LookupIterator::Next() { | 16 void LookupIterator::Next() { |
16 DisallowHeapAllocation no_gc; | 17 DisallowHeapAllocation no_gc; |
17 has_property_ = false; | 18 has_property_ = false; |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 case v8::internal::NONEXISTENT: | 103 case v8::internal::NONEXISTENT: |
103 case v8::internal::INTERCEPTOR: | 104 case v8::internal::INTERCEPTOR: |
104 UNREACHABLE(); | 105 UNREACHABLE(); |
105 } | 106 } |
106 | 107 |
107 has_property_ = true; | 108 has_property_ = true; |
108 return true; | 109 return true; |
109 } | 110 } |
110 | 111 |
111 | 112 |
| 113 void LookupIterator::ReloadPropertyInformation() { |
| 114 state_ = BEFORE_PROPERTY; |
| 115 state_ = LookupInHolder(*holder_map_); |
| 116 DCHECK(IsFound()); |
| 117 HasProperty(); |
| 118 } |
| 119 |
| 120 |
112 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { | 121 void LookupIterator::PrepareForDataProperty(Handle<Object> value) { |
113 DCHECK(has_property_); | 122 DCHECK(has_property_); |
114 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 123 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
115 if (property_encoding_ == DICTIONARY) return; | 124 if (property_encoding_ == DICTIONARY) return; |
116 holder_map_ = | 125 holder_map_ = |
117 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); | 126 Map::PrepareForDataProperty(holder_map_, descriptor_number(), value); |
118 JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_); | 127 JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_); |
119 // Reload property information. | 128 ReloadPropertyInformation(); |
120 if (holder_map_->is_dictionary_map()) { | |
121 property_encoding_ = DICTIONARY; | |
122 } else { | |
123 property_encoding_ = DESCRIPTOR; | |
124 } | |
125 CHECK(HasProperty()); | |
126 } | 129 } |
127 | 130 |
128 | 131 |
129 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, | 132 void LookupIterator::ReconfigureDataProperty(Handle<Object> value, |
130 PropertyAttributes attributes) { | 133 PropertyAttributes attributes) { |
131 DCHECK(has_property_); | 134 DCHECK(has_property_); |
132 DCHECK(HolderIsReceiverOrHiddenPrototype()); | 135 DCHECK(HolderIsReceiverOrHiddenPrototype()); |
133 Handle<JSObject> holder = GetHolder<JSObject>(); | 136 Handle<JSObject> holder = GetHolder<JSObject>(); |
134 if (property_encoding_ != DICTIONARY) { | 137 if (property_encoding_ != DICTIONARY) { |
135 holder_map_ = Map::ReconfigureDataProperty(holder_map_, descriptor_number(), | 138 holder_map_ = Map::ReconfigureDataProperty(holder_map_, descriptor_number(), |
136 attributes); | 139 attributes); |
137 JSObject::MigrateToMap(holder, holder_map_); | 140 JSObject::MigrateToMap(holder, holder_map_); |
138 } | 141 } |
139 | 142 |
140 // Reload property information and update the descriptor if in dictionary | |
141 // mode. | |
142 if (holder_map_->is_dictionary_map()) { | 143 if (holder_map_->is_dictionary_map()) { |
143 property_encoding_ = DICTIONARY; | |
144 PropertyDetails details(attributes, NORMAL, 0); | 144 PropertyDetails details(attributes, NORMAL, 0); |
145 JSObject::SetNormalizedProperty(holder, name(), value, details); | 145 JSObject::SetNormalizedProperty(holder, name(), value, details); |
146 } else { | |
147 property_encoding_ = DESCRIPTOR; | |
148 } | 146 } |
149 | 147 |
150 CHECK(HasProperty()); | 148 ReloadPropertyInformation(); |
151 } | 149 } |
152 | 150 |
153 | 151 |
154 void LookupIterator::TransitionToDataProperty( | 152 void LookupIterator::TransitionToDataProperty( |
155 Handle<Object> value, PropertyAttributes attributes, | 153 Handle<Object> value, PropertyAttributes attributes, |
156 Object::StoreFromKeyed store_mode) { | 154 Object::StoreFromKeyed store_mode) { |
157 DCHECK(!has_property_ || !HolderIsReceiverOrHiddenPrototype()); | 155 DCHECK(!has_property_ || !HolderIsReceiverOrHiddenPrototype()); |
158 | 156 |
159 // Can only be called when the receiver is a JSObject. JSProxy has to be | 157 // Can only be called when the receiver is a JSObject. JSProxy has to be |
160 // handled via a trap. Adding properties to primitive values is not | 158 // handled via a trap. Adding properties to primitive values is not |
161 // observable. | 159 // observable. |
162 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); | 160 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); |
163 | 161 |
164 if (receiver->IsJSGlobalProxy()) { | 162 if (receiver->IsJSGlobalProxy()) { |
165 PrototypeIterator iter(isolate(), receiver); | 163 PrototypeIterator iter(isolate(), receiver); |
166 receiver = | 164 receiver = |
167 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); | 165 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); |
168 } | 166 } |
169 | 167 |
170 maybe_holder_ = receiver; | 168 maybe_holder_ = receiver; |
171 holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()), name_, | 169 holder_map_ = Map::TransitionToDataProperty(handle(receiver->map()), name_, |
172 value, attributes, store_mode); | 170 value, attributes, store_mode); |
173 JSObject::MigrateToMap(receiver, holder_map_); | 171 JSObject::MigrateToMap(receiver, holder_map_); |
174 | 172 |
175 // Reload the information. | 173 ReloadPropertyInformation(); |
176 state_ = NOT_FOUND; | |
177 configuration_ = CHECK_PROPERTY; | |
178 state_ = LookupInHolder(*holder_map_); | |
179 DCHECK(IsFound()); | |
180 HasProperty(); | |
181 } | 174 } |
182 | 175 |
183 | 176 |
| 177 void LookupIterator::TransitionToAccessorProperty( |
| 178 AccessorComponent component, Handle<Object> accessor, |
| 179 PropertyAttributes attributes) { |
| 180 DCHECK(!accessor->IsNull()); |
| 181 // Can only be called when the receiver is a JSObject. JSProxy has to be |
| 182 // handled via a trap. Adding properties to primitive values is not |
| 183 // observable. |
| 184 Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver()); |
| 185 |
| 186 if (receiver->IsJSGlobalProxy()) { |
| 187 PrototypeIterator iter(isolate(), receiver); |
| 188 receiver = |
| 189 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 190 } |
| 191 |
| 192 maybe_holder_ = receiver; |
| 193 holder_map_ = Map::TransitionToAccessorProperty( |
| 194 handle(receiver->map()), name_, component, accessor, attributes); |
| 195 JSObject::MigrateToMap(receiver, holder_map_); |
| 196 |
| 197 ReloadPropertyInformation(); |
| 198 |
| 199 if (!holder_map_->is_dictionary_map()) return; |
| 200 |
| 201 // We have to deoptimize since accesses to data properties may have been |
| 202 // inlined without a corresponding map-check. |
| 203 if (holder_map_->IsGlobalObjectMap()) { |
| 204 Deoptimizer::DeoptimizeGlobalObject(*receiver); |
| 205 } |
| 206 |
| 207 // Install the accessor into the dictionary-mode object. |
| 208 PropertyDetails details(attributes, CALLBACKS, 0); |
| 209 Handle<AccessorPair> pair; |
| 210 if (IsFound() && HasProperty() && property_kind() == ACCESSOR && |
| 211 GetAccessors()->IsAccessorPair()) { |
| 212 pair = Handle<AccessorPair>::cast(GetAccessors()); |
| 213 // If the component and attributes are identical, nothing has to be done. |
| 214 if (pair->get(component) == *accessor) { |
| 215 if (property_details().attributes() == attributes) return; |
| 216 } else { |
| 217 pair = AccessorPair::Copy(pair); |
| 218 pair->set(component, *accessor); |
| 219 } |
| 220 } else { |
| 221 pair = isolate()->factory()->NewAccessorPair(); |
| 222 pair->set(component, *accessor); |
| 223 } |
| 224 JSObject::SetNormalizedProperty(receiver, name_, pair, details); |
| 225 |
| 226 JSObject::ReoptimizeIfPrototype(receiver); |
| 227 holder_map_ = handle(receiver->map()); |
| 228 ReloadPropertyInformation(); |
| 229 } |
| 230 |
| 231 |
184 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { | 232 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { |
185 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); | 233 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); |
186 // Optimization that only works if configuration_ is not mutable. | 234 // Optimization that only works if configuration_ is not mutable. |
187 if (!check_derived()) return true; | 235 if (!check_derived()) return true; |
188 DisallowHeapAllocation no_gc; | 236 DisallowHeapAllocation no_gc; |
189 Handle<Object> receiver = GetReceiver(); | 237 Handle<Object> receiver = GetReceiver(); |
190 if (!receiver->IsJSReceiver()) return false; | 238 if (!receiver->IsJSReceiver()) return false; |
191 Object* current = *receiver; | 239 Object* current = *receiver; |
192 JSReceiver* holder = *maybe_holder_.ToHandleChecked(); | 240 JSReceiver* holder = *maybe_holder_.ToHandleChecked(); |
193 // JSProxy do not occur as hidden prototypes. | 241 // JSProxy do not occur as hidden prototypes. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 DCHECK_EQ(v8::internal::CONSTANT, property_details_.type()); | 347 DCHECK_EQ(v8::internal::CONSTANT, property_details_.type()); |
300 } | 348 } |
301 } | 349 } |
302 | 350 |
303 | 351 |
304 void LookupIterator::InternalizeName() { | 352 void LookupIterator::InternalizeName() { |
305 if (name_->IsUniqueName()) return; | 353 if (name_->IsUniqueName()) return; |
306 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); | 354 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); |
307 } | 355 } |
308 } } // namespace v8::internal | 356 } } // namespace v8::internal |
OLD | NEW |