| 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 |