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