OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 <ostream> | 5 #include <ostream> |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/property-access-info.h" | 9 #include "src/compiler/property-access-info.h" |
10 #include "src/field-index-inl.h" | 10 #include "src/field-index-inl.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 case PropertyAccessMode::kLoad: | 21 case PropertyAccessMode::kLoad: |
22 return os << "Load"; | 22 return os << "Load"; |
23 case PropertyAccessMode::kStore: | 23 case PropertyAccessMode::kStore: |
24 return os << "Store"; | 24 return os << "Store"; |
25 } | 25 } |
26 UNREACHABLE(); | 26 UNREACHABLE(); |
27 return os; | 27 return os; |
28 } | 28 } |
29 | 29 |
30 | 30 |
| 31 // static |
| 32 PropertyAccessInfo PropertyAccessInfo::NotFound(Type* receiver_type, |
| 33 MaybeHandle<JSObject> holder) { |
| 34 return PropertyAccessInfo(holder, receiver_type); |
| 35 } |
| 36 |
| 37 |
| 38 // static |
| 39 PropertyAccessInfo PropertyAccessInfo::DataConstant( |
| 40 Type* receiver_type, Handle<Object> constant, |
| 41 MaybeHandle<JSObject> holder) { |
| 42 return PropertyAccessInfo(holder, constant, receiver_type); |
| 43 } |
| 44 |
| 45 |
| 46 // static |
| 47 PropertyAccessInfo PropertyAccessInfo::DataField( |
| 48 Type* receiver_type, FieldIndex field_index, Type* field_type, |
| 49 MaybeHandle<JSObject> holder, MaybeHandle<Map> transition_map) { |
| 50 return PropertyAccessInfo(holder, transition_map, field_index, field_type, |
| 51 receiver_type); |
| 52 } |
| 53 |
| 54 |
31 PropertyAccessInfo::PropertyAccessInfo() | 55 PropertyAccessInfo::PropertyAccessInfo() |
32 : kind_(kInvalid), receiver_type_(Type::None()), field_type_(Type::Any()) {} | 56 : kind_(kInvalid), receiver_type_(Type::None()), field_type_(Type::Any()) {} |
33 | 57 |
34 | 58 |
35 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 59 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
| 60 Type* receiver_type) |
| 61 : kind_(kNotFound), |
| 62 receiver_type_(receiver_type), |
| 63 holder_(holder), |
| 64 field_type_(Type::Any()) {} |
| 65 |
| 66 |
| 67 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
36 Handle<Object> constant, | 68 Handle<Object> constant, |
37 Type* receiver_type) | 69 Type* receiver_type) |
38 : kind_(kDataConstant), | 70 : kind_(kDataConstant), |
39 receiver_type_(receiver_type), | 71 receiver_type_(receiver_type), |
40 constant_(constant), | 72 constant_(constant), |
41 holder_(holder), | 73 holder_(holder), |
42 field_type_(Type::Any()) {} | 74 field_type_(Type::Any()) {} |
43 | 75 |
44 | 76 |
45 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, | 77 PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 // Compute the receiver type. | 120 // Compute the receiver type. |
89 Handle<Map> receiver_map = map; | 121 Handle<Map> receiver_map = map; |
90 | 122 |
91 // We support fast inline cases for certain JSObject getters. | 123 // We support fast inline cases for certain JSObject getters. |
92 if (access_mode == PropertyAccessMode::kLoad && | 124 if (access_mode == PropertyAccessMode::kLoad && |
93 LookupSpecialFieldAccessor(map, name, access_info)) { | 125 LookupSpecialFieldAccessor(map, name, access_info)) { |
94 return true; | 126 return true; |
95 } | 127 } |
96 | 128 |
97 MaybeHandle<JSObject> holder; | 129 MaybeHandle<JSObject> holder; |
98 while (true) { | 130 do { |
99 // Lookup the named property on the {map}. | 131 // Lookup the named property on the {map}. |
100 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); | 132 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); |
101 int const number = descriptors->SearchWithCache(*name, *map); | 133 int const number = descriptors->SearchWithCache(*name, *map); |
102 if (number != DescriptorArray::kNotFound) { | 134 if (number != DescriptorArray::kNotFound) { |
103 PropertyDetails const details = descriptors->GetDetails(number); | 135 PropertyDetails const details = descriptors->GetDetails(number); |
104 if (access_mode == PropertyAccessMode::kStore) { | 136 if (access_mode == PropertyAccessMode::kStore) { |
105 // Don't bother optimizing stores to read-only properties. | 137 // Don't bother optimizing stores to read-only properties. |
106 if (details.IsReadOnly()) { | 138 if (details.IsReadOnly()) { |
107 return false; | 139 return false; |
108 } | 140 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 .ToHandle(&constructor)) { | 212 .ToHandle(&constructor)) { |
181 map = handle(constructor->initial_map(), isolate()); | 213 map = handle(constructor->initial_map(), isolate()); |
182 DCHECK(map->prototype()->IsJSObject()); | 214 DCHECK(map->prototype()->IsJSObject()); |
183 } else if (map->prototype()->IsNull()) { | 215 } else if (map->prototype()->IsNull()) { |
184 // Store to property not found on the receiver or any prototype, we need | 216 // Store to property not found on the receiver or any prototype, we need |
185 // to transition to a new data property. | 217 // to transition to a new data property. |
186 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) | 218 // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) |
187 if (access_mode == PropertyAccessMode::kStore) { | 219 if (access_mode == PropertyAccessMode::kStore) { |
188 return LookupTransition(receiver_map, name, holder, access_info); | 220 return LookupTransition(receiver_map, name, holder, access_info); |
189 } | 221 } |
190 // TODO(bmeurer): Handle the not found case if the prototype is null. | 222 // The property was not found, return undefined or throw depending |
191 return false; | 223 // on the language mode of the load operation. |
| 224 // Implemented according to ES6 section 9.1.8 [[Get]] (P, Receiver) |
| 225 *access_info = PropertyAccessInfo::NotFound( |
| 226 Type::Class(receiver_map, zone()), holder); |
| 227 return true; |
192 } else { | 228 } else { |
193 return false; | 229 return false; |
194 } | 230 } |
195 } | 231 } |
196 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate()); | 232 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate()); |
197 if (map_prototype->map()->is_deprecated()) { | 233 if (map_prototype->map()->is_deprecated()) { |
198 // Try to migrate the prototype object so we don't embed the deprecated | 234 // Try to migrate the prototype object so we don't embed the deprecated |
199 // map into the optimized code. | 235 // map into the optimized code. |
200 JSObject::TryMigrateInstance(map_prototype); | 236 JSObject::TryMigrateInstance(map_prototype); |
201 } | 237 } |
202 map = handle(map_prototype->map(), isolate()); | 238 map = handle(map_prototype->map(), isolate()); |
203 holder = map_prototype; | 239 holder = map_prototype; |
204 | 240 } while (CanInlinePropertyAccess(map)); |
205 // Check if it is safe to inline property access for the {map}. | |
206 if (!CanInlinePropertyAccess(map)) return false; | |
207 } | |
208 return false; | 241 return false; |
209 } | 242 } |
210 | 243 |
211 | 244 |
| 245 bool PropertyAccessInfoFactory::ComputePropertyAccessInfos( |
| 246 MapHandleList const& maps, Handle<Name> name, |
| 247 PropertyAccessMode access_mode, |
| 248 ZoneVector<PropertyAccessInfo>* access_infos) { |
| 249 for (Handle<Map> map : maps) { |
| 250 if (Map::TryUpdate(map).ToHandle(&map)) { |
| 251 PropertyAccessInfo access_info; |
| 252 if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) { |
| 253 return false; |
| 254 } |
| 255 access_infos->push_back(access_info); |
| 256 } |
| 257 } |
| 258 return true; |
| 259 } |
| 260 |
| 261 |
212 bool PropertyAccessInfoFactory::LookupSpecialFieldAccessor( | 262 bool PropertyAccessInfoFactory::LookupSpecialFieldAccessor( |
213 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { | 263 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
214 // Check for special JSObject field accessors. | 264 // Check for special JSObject field accessors. |
215 int offset; | 265 int offset; |
216 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { | 266 if (Accessors::IsJSObjectFieldAccessor(map, name, &offset)) { |
217 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); | 267 FieldIndex field_index = FieldIndex::ForInObjectOffset(offset); |
218 Type* field_type = Type::Tagged(); | 268 Type* field_type = Type::Tagged(); |
219 if (map->IsStringMap()) { | 269 if (map->IsStringMap()) { |
220 DCHECK(Name::Equals(factory()->length_string(), name)); | 270 DCHECK(Name::Equals(factory()->length_string(), name)); |
221 // The String::length property is always a smi in the range | 271 // The String::length property is always a smi in the range |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 dependencies()->AssumeMapNotDeprecated(transition_map); | 342 dependencies()->AssumeMapNotDeprecated(transition_map); |
293 *access_info = | 343 *access_info = |
294 PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index, | 344 PropertyAccessInfo::DataField(Type::Class(map, zone()), field_index, |
295 field_type, holder, transition_map); | 345 field_type, holder, transition_map); |
296 return true; | 346 return true; |
297 } | 347 } |
298 return false; | 348 return false; |
299 } | 349 } |
300 | 350 |
301 | 351 |
302 bool PropertyAccessInfoFactory::ComputePropertyAccessInfos( | |
303 MapHandleList const& maps, Handle<Name> name, | |
304 PropertyAccessMode access_mode, | |
305 ZoneVector<PropertyAccessInfo>* access_infos) { | |
306 for (Handle<Map> map : maps) { | |
307 if (Map::TryUpdate(map).ToHandle(&map)) { | |
308 PropertyAccessInfo access_info; | |
309 if (!ComputePropertyAccessInfo(map, name, access_mode, &access_info)) { | |
310 return false; | |
311 } | |
312 access_infos->push_back(access_info); | |
313 } | |
314 } | |
315 return true; | |
316 } | |
317 | |
318 | |
319 Factory* PropertyAccessInfoFactory::factory() const { | 352 Factory* PropertyAccessInfoFactory::factory() const { |
320 return isolate()->factory(); | 353 return isolate()->factory(); |
321 } | 354 } |
322 | 355 |
323 } // namespace compiler | 356 } // namespace compiler |
324 } // namespace internal | 357 } // namespace internal |
325 } // namespace v8 | 358 } // namespace v8 |
OLD | NEW |