LCOV - code coverage report
Current view: top level - src - lookup.h (source / functions) Hit Total Coverage
Test: app.info Lines: 81 83 97.6 %
Date: 2017-10-20 Functions: 25 26 96.2 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_LOOKUP_H_
       6             : #define V8_LOOKUP_H_
       7             : 
       8             : #include "src/factory.h"
       9             : #include "src/globals.h"
      10             : #include "src/isolate.h"
      11             : #include "src/objects.h"
      12             : #include "src/objects/descriptor-array.h"
      13             : #include "src/objects/map.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
      19             :  public:
      20             :   enum Configuration {
      21             :     // Configuration bits.
      22             :     kInterceptor = 1 << 0,
      23             :     kPrototypeChain = 1 << 1,
      24             : 
      25             :     // Convenience combinations of bits.
      26             :     OWN_SKIP_INTERCEPTOR = 0,
      27             :     OWN = kInterceptor,
      28             :     PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
      29             :     PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
      30             :     DEFAULT = PROTOTYPE_CHAIN
      31             :   };
      32             : 
      33             :   enum State {
      34             :     ACCESS_CHECK,
      35             :     INTEGER_INDEXED_EXOTIC,
      36             :     INTERCEPTOR,
      37             :     JSPROXY,
      38             :     NOT_FOUND,
      39             :     ACCESSOR,
      40             :     DATA,
      41             :     TRANSITION,
      42             :     // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
      43             :     // PROPERTY lookup.
      44             :     BEFORE_PROPERTY = INTERCEPTOR
      45             :   };
      46             : 
      47   108171261 :   LookupIterator(Handle<Object> receiver, Handle<Name> name,
      48             :                  Configuration configuration = DEFAULT)
      49   108171261 :       : LookupIterator(name->GetIsolate(), receiver, name, configuration) {}
      50             : 
      51   108171726 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      52             :                  Configuration configuration = DEFAULT)
      53             :       : LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
      54   108171726 :                        configuration) {}
      55             : 
      56    71413519 :   LookupIterator(Handle<Object> receiver, Handle<Name> name,
      57             :                  Handle<JSReceiver> holder,
      58             :                  Configuration configuration = DEFAULT)
      59             :       : LookupIterator(name->GetIsolate(), receiver, name, holder,
      60    71413519 :                        configuration) {}
      61             : 
      62   179585242 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      63             :                  Handle<JSReceiver> holder,
      64             :                  Configuration configuration = DEFAULT)
      65             :       : configuration_(ComputeConfiguration(configuration, name)),
      66             :         interceptor_state_(InterceptorState::kUninitialized),
      67             :         property_details_(PropertyDetails::Empty()),
      68             :         isolate_(isolate),
      69             :         name_(isolate_->factory()->InternalizeName(name)),
      70             :         receiver_(receiver),
      71             :         initial_holder_(holder),
      72             :         // kMaxUInt32 isn't a valid index.
      73             :         index_(kMaxUInt32),
      74   538755729 :         number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
      75             : #ifdef DEBUG
      76             :     uint32_t index;  // Assert that the name is not an array index.
      77             :     DCHECK(!name->AsArrayIndex(&index));
      78             : #endif  // DEBUG
      79   179585245 :     Start<false>();
      80   179585250 :   }
      81             : 
      82    26874515 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
      83             :                  Configuration configuration = DEFAULT)
      84             :       : LookupIterator(isolate, receiver, index,
      85    53749030 :                        GetRoot(isolate, receiver, index), configuration) {}
      86             : 
      87         255 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
      88             :                  Handle<JSReceiver> holder,
      89             :                  Configuration configuration = DEFAULT)
      90             :       : configuration_(configuration),
      91             :         interceptor_state_(InterceptorState::kUninitialized),
      92             :         property_details_(PropertyDetails::Empty()),
      93             :         isolate_(isolate),
      94             :         receiver_(receiver),
      95             :         initial_holder_(holder),
      96             :         index_(index),
      97   382903269 :         number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
      98             :     // kMaxUInt32 isn't a valid index.
      99             :     DCHECK_NE(kMaxUInt32, index_);
     100   127634423 :     Start<true>();
     101         255 :   }
     102             : 
     103    46453862 :   static LookupIterator PropertyOrElement(
     104             :       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
     105             :       Configuration configuration = DEFAULT) {
     106             :     uint32_t index;
     107    46453862 :     if (name->AsArrayIndex(&index)) {
     108             :       LookupIterator it =
     109       76164 :           LookupIterator(isolate, receiver, index, configuration);
     110       76164 :       it.name_ = name;
     111       76164 :       return it;
     112             :     }
     113    46377698 :     return LookupIterator(receiver, name, configuration);
     114             :   }
     115             : 
     116    11940671 :   static LookupIterator PropertyOrElement(
     117             :       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
     118             :       Handle<JSReceiver> holder, Configuration configuration = DEFAULT) {
     119             :     uint32_t index;
     120    11940671 :     if (name->AsArrayIndex(&index)) {
     121             :       LookupIterator it =
     122       13086 :           LookupIterator(isolate, receiver, index, holder, configuration);
     123       13086 :       it.name_ = name;
     124       13086 :       return it;
     125             :     }
     126    11927585 :     return LookupIterator(receiver, name, holder, configuration);
     127             :   }
     128             : 
     129             :   static LookupIterator PropertyOrElement(
     130             :       Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
     131             :       bool* success, Handle<JSReceiver> holder,
     132             :       Configuration configuration = DEFAULT);
     133             : 
     134             :   static LookupIterator PropertyOrElement(
     135             :       Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
     136             :       bool* success, Configuration configuration = DEFAULT);
     137             : 
     138             :   static LookupIterator ForTransitionHandler(Isolate* isolate,
     139             :                                              Handle<Object> receiver,
     140             :                                              Handle<Name> name,
     141             :                                              Handle<Object> value,
     142             :                                              MaybeHandle<Object> handler,
     143             :                                              Handle<Map> transition_map);
     144             : 
     145     4703052 :   void Restart() {
     146             :     InterceptorState state = InterceptorState::kUninitialized;
     147     4703052 :     IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
     148     4703052 :   }
     149             : 
     150             :   Isolate* isolate() const { return isolate_; }
     151      501282 :   State state() const { return state_; }
     152             : 
     153         132 :   Handle<Name> name() const {
     154             :     DCHECK(!IsElement());
     155         132 :     return name_;
     156             :   }
     157     1663821 :   Handle<Name> GetName() {
     158     1542374 :     if (name_.is_null()) {
     159             :       DCHECK(IsElement());
     160      242894 :       name_ = factory()->Uint32ToString(index_);
     161             :     }
     162     1542374 :     return name_;
     163             :   }
     164             :   uint32_t index() const { return index_; }
     165             : 
     166             :   bool IsElement() const { return index_ != kMaxUInt32; }
     167             : 
     168      281475 :   bool IsFound() const { return state_ != NOT_FOUND; }
     169             :   void Next();
     170             :   void NotFound() {
     171      464385 :     has_property_ = false;
     172      464385 :     state_ = NOT_FOUND;
     173             :   }
     174             : 
     175             :   Heap* heap() const { return isolate_->heap(); }
     176             :   Factory* factory() const { return isolate_->factory(); }
     177             :   Handle<Object> GetReceiver() const { return receiver_; }
     178             : 
     179    44112010 :   Handle<JSObject> GetStoreTarget() const {
     180             :     DCHECK(receiver_->IsJSObject());
     181    44112010 :     if (receiver_->IsJSGlobalProxy()) {
     182             :       Map* map = JSGlobalProxy::cast(*receiver_)->map();
     183       72164 :       if (map->has_hidden_prototype()) {
     184      144328 :         return handle(JSGlobalObject::cast(map->prototype()), isolate_);
     185             :       }
     186             :     }
     187             :     return Handle<JSObject>::cast(receiver_);
     188             :   }
     189             : 
     190     1403636 :   bool is_dictionary_holder() const { return !holder_->HasFastProperties(); }
     191             :   Handle<Map> transition_map() const {
     192             :     DCHECK_EQ(TRANSITION, state_);
     193             :     return Handle<Map>::cast(transition_);
     194             :   }
     195             :   Handle<PropertyCell> transition_cell() const {
     196             :     DCHECK_EQ(TRANSITION, state_);
     197             :     return Handle<PropertyCell>::cast(transition_);
     198             :   }
     199             :   template <class T>
     200      200610 :   Handle<T> GetHolder() const {
     201             :     DCHECK(IsFound());
     202      200610 :     return Handle<T>::cast(holder_);
     203             :   }
     204             : 
     205             :   bool HolderIsReceiver() const;
     206             :   bool HolderIsReceiverOrHiddenPrototype() const;
     207             : 
     208             :   bool check_prototype_chain() const {
     209   272502717 :     return (configuration_ & kPrototypeChain) != 0;
     210             :   }
     211             : 
     212             :   /* ACCESS_CHECK */
     213             :   bool HasAccess() const;
     214             : 
     215             :   /* PROPERTY */
     216    42920970 :   bool ExtendingNonExtensible(Handle<JSObject> receiver) {
     217             :     DCHECK(receiver.is_identical_to(GetStoreTarget()));
     218    42920970 :     return !receiver->map()->is_extensible() &&
     219         914 :            (IsElement() || !name_->IsPrivate());
     220             :   }
     221             :   void PrepareForDataProperty(Handle<Object> value);
     222             :   bool PrepareTransitionToDataProperty(Handle<JSObject> receiver,
     223             :                                        Handle<Object> value,
     224             :                                        PropertyAttributes attributes,
     225             :                                        Object::StoreFromKeyed store_mode);
     226      600533 :   bool IsCacheableTransition() {
     227             :     DCHECK_EQ(TRANSITION, state_);
     228      598743 :     return transition_->IsPropertyCell() ||
     229       13956 :            (transition_map()->is_dictionary_map() &&
     230     1213348 :             !GetStoreTarget()->HasFastProperties()) ||
     231     1185436 :            transition_map()->GetBackPointer()->IsMap();
     232             :   }
     233             :   void ApplyTransitionToDataProperty(Handle<JSObject> receiver);
     234             :   void ReconfigureDataProperty(Handle<Object> value,
     235             :                                PropertyAttributes attributes);
     236             :   void Delete();
     237             :   void TransitionToAccessorProperty(Handle<Object> getter,
     238             :                                     Handle<Object> setter,
     239             :                                     PropertyAttributes attributes);
     240             :   void TransitionToAccessorPair(Handle<Object> pair,
     241             :                                 PropertyAttributes attributes);
     242          80 :   PropertyDetails property_details() const {
     243             :     DCHECK(has_property_);
     244          80 :     return property_details_;
     245             :   }
     246             :   PropertyAttributes property_attributes() const {
     247             :     return property_details().attributes();
     248             :   }
     249             :   bool IsConfigurable() const { return property_details().IsConfigurable(); }
     250             :   bool IsReadOnly() const { return property_details().IsReadOnly(); }
     251             :   bool IsEnumerable() const { return property_details().IsEnumerable(); }
     252             :   Representation representation() const {
     253             :     return property_details().representation();
     254             :   }
     255             :   PropertyLocation location() const { return property_details().location(); }
     256             :   PropertyConstness constness() const { return property_details().constness(); }
     257             :   Handle<Map> GetFieldOwnerMap() const;
     258             :   FieldIndex GetFieldIndex() const;
     259             :   Handle<FieldType> GetFieldType() const;
     260             :   int GetFieldDescriptorIndex() const;
     261             :   int GetAccessorIndex() const;
     262             :   int GetConstantIndex() const;
     263             :   Handle<PropertyCell> GetPropertyCell() const;
     264             :   Handle<Object> GetAccessors() const;
     265      459246 :   inline Handle<InterceptorInfo> GetInterceptor() const {
     266             :     DCHECK_EQ(INTERCEPTOR, state_);
     267             :     InterceptorInfo* result =
     268             :         IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
     269      459246 :                     : GetInterceptor<false>(JSObject::cast(*holder_));
     270      918492 :     return handle(result, isolate_);
     271             :   }
     272             :   Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
     273             :   Handle<Object> GetDataValue() const;
     274             :   void WriteDataValue(Handle<Object> value, bool initializing_store);
     275   122176415 :   inline void UpdateProtector() {
     276   127824914 :     if (IsElement()) return;
     277             :     // This list must be kept in sync with
     278             :     // CodeStubAssembler::HasAssociatedProtector!
     279   174790885 :     if (*name_ == heap()->is_concat_spreadable_symbol() ||
     280   112932067 :         *name_ == heap()->constructor_string() ||
     281   167597238 :         *name_ == heap()->species_symbol() ||
     282    54664182 :         *name_ == heap()->iterator_symbol()) {
     283     3615441 :       InternalUpdateProtector();
     284             :     }
     285             :   }
     286             : 
     287             :   // Lookup a 'cached' private property for an accessor.
     288             :   // If not found returns false and leaves the LookupIterator unmodified.
     289             :   bool TryLookupCachedProperty();
     290             :   bool LookupCachedProperty();
     291             : 
     292             :  private:
     293             :   // For |ForTransitionHandler|.
     294             :   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
     295             :                  Handle<Map> transition_map, PropertyDetails details,
     296             :                  bool has_property);
     297             : 
     298             :   void InternalUpdateProtector();
     299             : 
     300             :   enum class InterceptorState {
     301             :     kUninitialized,
     302             :     kSkipNonMasking,
     303             :     kProcessNonMasking
     304             :   };
     305             : 
     306             :   Handle<Map> GetReceiverMap() const;
     307             : 
     308             :   MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
     309             : 
     310             :   template <bool is_element>
     311             :   V8_EXPORT_PRIVATE void Start();
     312             :   template <bool is_element>
     313             :   void NextInternal(Map* map, JSReceiver* holder);
     314             :   template <bool is_element>
     315   527204071 :   inline State LookupInHolder(Map* map, JSReceiver* holder) {
     316             :     return map->IsSpecialReceiverMap()
     317             :                ? LookupInSpecialHolder<is_element>(map, holder)
     318   527204071 :                : LookupInRegularHolder<is_element>(map, holder);
     319             :   }
     320             :   template <bool is_element>
     321             :   State LookupInRegularHolder(Map* map, JSReceiver* holder);
     322             :   template <bool is_element>
     323    35373751 :   State LookupInSpecialHolder(Map* map, JSReceiver* holder);
     324             :   template <bool is_element>
     325           0 :   void RestartLookupForNonMaskingInterceptors() {
     326         150 :     RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
     327           0 :   }
     328             :   template <bool is_element>
     329             :   void RestartInternal(InterceptorState interceptor_state);
     330             :   Handle<Object> FetchValue() const;
     331             :   bool IsConstFieldValueEqualTo(Object* value) const;
     332             :   template <bool is_element>
     333             :   void ReloadPropertyInformation();
     334             : 
     335             :   template <bool is_element>
     336             :   bool SkipInterceptor(JSObject* holder);
     337             :   template <bool is_element>
     338             :   inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
     339             :     return is_element ? holder->GetIndexedInterceptor()
     340     1419642 :                       : holder->GetNamedInterceptor();
     341             :   }
     342             : 
     343             :   bool check_interceptor() const {
     344    35373751 :     return (configuration_ & kInterceptor) != 0;
     345             :   }
     346             :   int descriptor_number() const {
     347             :     DCHECK(!IsElement());
     348             :     DCHECK(has_property_);
     349             :     DCHECK(holder_->HasFastProperties());
     350    25453354 :     return number_;
     351             :   }
     352             :   int dictionary_entry() const {
     353             :     DCHECK(!IsElement());
     354             :     DCHECK(has_property_);
     355             :     DCHECK(!holder_->HasFastProperties());
     356    26568820 :     return number_;
     357             :   }
     358             : 
     359             :   static Configuration ComputeConfiguration(
     360             :       Configuration configuration, Handle<Name> name) {
     361   179585242 :     return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
     362             :   }
     363             : 
     364             :   static Handle<JSReceiver> GetRootForNonJSReceiver(
     365             :       Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
     366   135049325 :   inline static Handle<JSReceiver> GetRoot(Isolate* isolate,
     367             :                                            Handle<Object> receiver,
     368             :                                            uint32_t index = kMaxUInt32) {
     369   135049323 :     if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
     370      165137 :     return GetRootForNonJSReceiver(isolate, receiver, index);
     371             :   }
     372             : 
     373             :   State NotFound(JSReceiver* const holder) const;
     374             : 
     375             :   // If configuration_ becomes mutable, update
     376             :   // HolderIsReceiverOrHiddenPrototype.
     377             :   const Configuration configuration_;
     378             :   State state_;
     379             :   bool has_property_;
     380             :   InterceptorState interceptor_state_;
     381             :   PropertyDetails property_details_;
     382             :   Isolate* const isolate_;
     383             :   Handle<Name> name_;
     384             :   Handle<Object> transition_;
     385             :   const Handle<Object> receiver_;
     386             :   Handle<JSReceiver> holder_;
     387             :   const Handle<JSReceiver> initial_holder_;
     388             :   const uint32_t index_;
     389             :   uint32_t number_;
     390             : };
     391             : 
     392             : 
     393             : }  // namespace internal
     394             : }  // namespace v8
     395             : 
     396             : #endif  // V8_LOOKUP_H_

Generated by: LCOV version 1.10