LCOV - code coverage report
Current view: top level - src - lookup.h (source / functions) Hit Total Coverage
Test: app.info Lines: 83 83 100.0 %
Date: 2017-04-26 Functions: 26 27 96.3 %

          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             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : class V8_EXPORT_PRIVATE LookupIterator final BASE_EMBEDDED {
      18             :  public:
      19             :   enum Configuration {
      20             :     // Configuration bits.
      21             :     kInterceptor = 1 << 0,
      22             :     kPrototypeChain = 1 << 1,
      23             : 
      24             :     // Convience combinations of bits.
      25             :     OWN_SKIP_INTERCEPTOR = 0,
      26             :     OWN = kInterceptor,
      27             :     PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
      28             :     PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
      29             :     DEFAULT = PROTOTYPE_CHAIN
      30             :   };
      31             : 
      32             :   enum State {
      33             :     ACCESS_CHECK,
      34             :     INTEGER_INDEXED_EXOTIC,
      35             :     INTERCEPTOR,
      36             :     JSPROXY,
      37             :     NOT_FOUND,
      38             :     ACCESSOR,
      39             :     DATA,
      40             :     TRANSITION,
      41             :     // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
      42             :     // PROPERTY lookup.
      43             :     BEFORE_PROPERTY = INTERCEPTOR
      44             :   };
      45             : 
      46   184578847 :   LookupIterator(Handle<Object> receiver, Handle<Name> name,
      47             :                  Configuration configuration = DEFAULT)
      48   184578847 :       : LookupIterator(name->GetIsolate(), receiver, name, configuration) {}
      49             : 
      50   184579697 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      51             :                  Configuration configuration = DEFAULT)
      52             :       : LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
      53   184579697 :                        configuration) {}
      54             : 
      55   105553849 :   LookupIterator(Handle<Object> receiver, Handle<Name> name,
      56             :                  Handle<JSReceiver> holder,
      57             :                  Configuration configuration = DEFAULT)
      58             :       : LookupIterator(name->GetIsolate(), receiver, name, holder,
      59   105553849 :                        configuration) {}
      60             : 
      61   290133413 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
      62             :                  Handle<JSReceiver> holder,
      63             :                  Configuration configuration = DEFAULT)
      64             :       : configuration_(ComputeConfiguration(configuration, name)),
      65             :         interceptor_state_(InterceptorState::kUninitialized),
      66             :         property_details_(PropertyDetails::Empty()),
      67             :         isolate_(isolate),
      68             :         name_(isolate_->factory()->InternalizeName(name)),
      69             :         receiver_(receiver),
      70             :         initial_holder_(holder),
      71             :         // kMaxUInt32 isn't a valid index.
      72             :         index_(kMaxUInt32),
      73   870400147 :         number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
      74             : #ifdef DEBUG
      75             :     uint32_t index;  // Assert that the name is not an array index.
      76             :     DCHECK(!name->AsArrayIndex(&index));
      77             : #endif  // DEBUG
      78   290133394 :     Start<false>();
      79   290133490 :   }
      80             : 
      81    38138640 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
      82             :                  Configuration configuration = DEFAULT)
      83             :       : LookupIterator(isolate, receiver, index,
      84    76277280 :                        GetRoot(isolate, receiver, index), configuration) {}
      85             : 
      86         381 :   LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
      87             :                  Handle<JSReceiver> holder,
      88             :                  Configuration configuration = DEFAULT)
      89             :       : configuration_(configuration),
      90             :         interceptor_state_(InterceptorState::kUninitialized),
      91             :         property_details_(PropertyDetails::Empty()),
      92             :         isolate_(isolate),
      93             :         receiver_(receiver),
      94             :         initial_holder_(holder),
      95             :         index_(index),
      96   573296286 :         number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
      97             :     // kMaxUInt32 isn't a valid index.
      98             :     DCHECK_NE(kMaxUInt32, index_);
      99   191098762 :     Start<true>();
     100         381 :   }
     101             : 
     102    70676223 :   static LookupIterator PropertyOrElement(
     103             :       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
     104             :       Configuration configuration = DEFAULT) {
     105             :     uint32_t index;
     106    70676223 :     if (name->AsArrayIndex(&index)) {
     107             :       LookupIterator it =
     108       78184 :           LookupIterator(isolate, receiver, index, configuration);
     109       78184 :       it.name_ = name;
     110       78184 :       return it;
     111             :     }
     112    70598039 :     return LookupIterator(receiver, name, configuration);
     113             :   }
     114             : 
     115    16734519 :   static LookupIterator PropertyOrElement(
     116             :       Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
     117             :       Handle<JSReceiver> holder, Configuration configuration = DEFAULT) {
     118             :     uint32_t index;
     119    16734519 :     if (name->AsArrayIndex(&index)) {
     120             :       LookupIterator it =
     121      153656 :           LookupIterator(isolate, receiver, index, holder, configuration);
     122      153656 :       it.name_ = name;
     123      153656 :       return it;
     124             :     }
     125    16580865 :     return LookupIterator(receiver, name, holder, configuration);
     126             :   }
     127             : 
     128             :   static LookupIterator PropertyOrElement(
     129             :       Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
     130             :       bool* success, Configuration configuration = DEFAULT);
     131             : 
     132     5420671 :   void Restart() {
     133             :     InterceptorState state = InterceptorState::kUninitialized;
     134     5420671 :     IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
     135     5420671 :   }
     136             : 
     137             :   Isolate* isolate() const { return isolate_; }
     138    16680968 :   State state() const { return state_; }
     139             : 
     140         154 :   Handle<Name> name() const {
     141             :     DCHECK(!IsElement());
     142         154 :     return name_;
     143             :   }
     144     3733092 :   Handle<Name> GetName() {
     145     3551189 :     if (name_.is_null()) {
     146             :       DCHECK(IsElement());
     147      363806 :       name_ = factory()->Uint32ToString(index_);
     148             :     }
     149     3551189 :     return name_;
     150             :   }
     151             :   uint32_t index() const { return index_; }
     152             : 
     153             :   bool IsElement() const { return index_ != kMaxUInt32; }
     154             : 
     155     5680562 :   bool IsFound() const { return state_ != NOT_FOUND; }
     156             :   void Next();
     157             :   void NotFound() {
     158      635453 :     has_property_ = false;
     159      635453 :     state_ = NOT_FOUND;
     160             :   }
     161             : 
     162             :   Heap* heap() const { return isolate_->heap(); }
     163             :   Factory* factory() const { return isolate_->factory(); }
     164             :   Handle<Object> GetReceiver() const { return receiver_; }
     165             : 
     166    59565290 :   Handle<JSObject> GetStoreTarget() const {
     167             :     DCHECK(receiver_->IsJSObject());
     168    59565280 :     if (receiver_->IsJSGlobalProxy()) {
     169             :       Map* map = JSGlobalProxy::cast(*receiver_)->map();
     170       96860 :       if (map->has_hidden_prototype()) {
     171      193720 :         return handle(JSGlobalObject::cast(map->prototype()), isolate_);
     172             :       }
     173             :     }
     174             :     return Handle<JSObject>::cast(receiver_);
     175             :   }
     176             : 
     177     3672885 :   bool is_dictionary_holder() const { return !holder_->HasFastProperties(); }
     178             :   Handle<Map> transition_map() const {
     179             :     DCHECK_EQ(TRANSITION, state_);
     180             :     return Handle<Map>::cast(transition_);
     181             :   }
     182             :   Handle<PropertyCell> transition_cell() const {
     183             :     DCHECK_EQ(TRANSITION, state_);
     184             :     return Handle<PropertyCell>::cast(transition_);
     185             :   }
     186             :   template <class T>
     187      202749 :   Handle<T> GetHolder() const {
     188             :     DCHECK(IsFound());
     189      202749 :     return Handle<T>::cast(holder_);
     190             :   }
     191             : 
     192             :   bool HolderIsReceiverOrHiddenPrototype() const;
     193             : 
     194             :   bool check_prototype_chain() const {
     195   406710742 :     return (configuration_ & kPrototypeChain) != 0;
     196             :   }
     197             : 
     198             :   /* ACCESS_CHECK */
     199             :   bool HasAccess() const;
     200             : 
     201             :   /* PROPERTY */
     202    57604978 :   bool ExtendingNonExtensible(Handle<JSObject> receiver) {
     203             :     DCHECK(receiver.is_identical_to(GetStoreTarget()));
     204    57604978 :     return !receiver->map()->is_extensible() &&
     205        1341 :            (IsElement() || !name_->IsPrivate());
     206             :   }
     207             :   void PrepareForDataProperty(Handle<Object> value);
     208             :   void PrepareTransitionToDataProperty(Handle<JSObject> receiver,
     209             :                                        Handle<Object> value,
     210             :                                        PropertyAttributes attributes,
     211             :                                        Object::StoreFromKeyed store_mode);
     212     1442640 :   bool IsCacheableTransition() {
     213             :     DCHECK_EQ(TRANSITION, state_);
     214     1439918 :     return transition_->IsPropertyCell() ||
     215       23098 :            (transition_map()->is_dictionary_map() &&
     216     2910606 :             !GetStoreTarget()->HasFastProperties()) ||
     217     2864410 :            transition_map()->GetBackPointer()->IsMap();
     218             :   }
     219             :   void ApplyTransitionToDataProperty(Handle<JSObject> receiver);
     220             :   void ReconfigureDataProperty(Handle<Object> value,
     221             :                                PropertyAttributes attributes);
     222             :   void Delete();
     223             :   void TransitionToAccessorProperty(Handle<Object> getter,
     224             :                                     Handle<Object> setter,
     225             :                                     PropertyAttributes attributes);
     226             :   void TransitionToAccessorPair(Handle<Object> pair,
     227             :                                 PropertyAttributes attributes);
     228     5375903 :   PropertyDetails property_details() const {
     229             :     DCHECK(has_property_);
     230     5375903 :     return property_details_;
     231             :   }
     232             :   PropertyAttributes property_attributes() const {
     233             :     return property_details().attributes();
     234             :   }
     235             :   bool IsConfigurable() const { return property_details().IsConfigurable(); }
     236             :   bool IsReadOnly() const { return property_details().IsReadOnly(); }
     237             :   bool IsEnumerable() const { return property_details().IsEnumerable(); }
     238             :   Representation representation() const {
     239             :     return property_details().representation();
     240             :   }
     241             :   PropertyLocation location() const { return property_details().location(); }
     242             :   PropertyConstness constness() const { return property_details().constness(); }
     243             :   Handle<Map> GetFieldOwnerMap() const;
     244             :   FieldIndex GetFieldIndex() const;
     245             :   Handle<FieldType> GetFieldType() const;
     246             :   int GetFieldDescriptorIndex() const;
     247             :   int GetAccessorIndex() const;
     248             :   int GetConstantIndex() const;
     249             :   Handle<PropertyCell> GetPropertyCell() const;
     250             :   Handle<Object> GetAccessors() const;
     251      513290 :   inline Handle<InterceptorInfo> GetInterceptor() const {
     252             :     DCHECK_EQ(INTERCEPTOR, state_);
     253             :     InterceptorInfo* result =
     254             :         IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
     255      513290 :                     : GetInterceptor<false>(JSObject::cast(*holder_));
     256     1026580 :     return handle(result, isolate_);
     257             :   }
     258             :   Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
     259             :   Handle<Object> GetDataValue() const;
     260             :   void WriteDataValue(Handle<Object> value, bool initializing_store);
     261   187373422 :   inline void UpdateProtector() {
     262   190518463 :     if (IsElement()) return;
     263             :     // This list must be kept in sync with
     264             :     // CodeStubAssembler::HasAssociatedProtector!
     265   276341297 :     if (*name_ == heap()->is_concat_spreadable_symbol() ||
     266   179314520 :         *name_ == heap()->constructor_string() ||
     267   266511835 :         *name_ == heap()->species_symbol() ||
     268    87196039 :         *name_ == heap()->iterator_symbol()) {
     269     4933311 :       InternalUpdateProtector();
     270             :     }
     271             :   }
     272             : 
     273             :   // Lookup a 'cached' private property for an accessor.
     274             :   // If not found returns false and leaves the LookupIterator unmodified.
     275             :   bool TryLookupCachedProperty();
     276             :   bool LookupCachedProperty();
     277             : 
     278             :  private:
     279             :   void InternalUpdateProtector();
     280             : 
     281             :   enum class InterceptorState {
     282             :     kUninitialized,
     283             :     kSkipNonMasking,
     284             :     kProcessNonMasking
     285             :   };
     286             : 
     287             :   Handle<Map> GetReceiverMap() const;
     288             : 
     289             :   MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
     290             : 
     291             :   template <bool is_element>
     292             :   V8_EXPORT_PRIVATE void Start();
     293             :   template <bool is_element>
     294             :   void NextInternal(Map* map, JSReceiver* holder);
     295             :   template <bool is_element>
     296   806840317 :   inline State LookupInHolder(Map* map, JSReceiver* holder) {
     297             :     return map->IsSpecialReceiverMap()
     298             :                ? LookupInSpecialHolder<is_element>(map, holder)
     299   806840317 :                : LookupInRegularHolder<is_element>(map, holder);
     300             :   }
     301             :   template <bool is_element>
     302             :   State LookupInRegularHolder(Map* map, JSReceiver* holder);
     303             :   template <bool is_element>
     304    47759723 :   State LookupInSpecialHolder(Map* map, JSReceiver* holder);
     305             :   template <bool is_element>
     306         175 :   void RestartLookupForNonMaskingInterceptors() {
     307         175 :     RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
     308         175 :   }
     309             :   template <bool is_element>
     310             :   void RestartInternal(InterceptorState interceptor_state);
     311             :   Handle<Object> FetchValue() const;
     312             :   bool IsConstFieldValueEqualTo(Object* value) const;
     313             :   template <bool is_element>
     314             :   void ReloadPropertyInformation();
     315             : 
     316             :   template <bool is_element>
     317             :   bool SkipInterceptor(JSObject* holder);
     318             :   template <bool is_element>
     319             :   inline InterceptorInfo* GetInterceptor(JSObject* holder) const {
     320             :     return is_element ? holder->GetIndexedInterceptor()
     321     1580216 :                       : holder->GetNamedInterceptor();
     322             :   }
     323             : 
     324             :   bool check_interceptor() const {
     325    47759723 :     return (configuration_ & kInterceptor) != 0;
     326             :   }
     327             :   int descriptor_number() const {
     328             :     DCHECK(!IsElement());
     329             :     DCHECK(has_property_);
     330             :     DCHECK(holder_->HasFastProperties());
     331    50307034 :     return number_;
     332             :   }
     333             :   int dictionary_entry() const {
     334             :     DCHECK(!IsElement());
     335             :     DCHECK(has_property_);
     336             :     DCHECK(!holder_->HasFastProperties());
     337    38267008 :     return number_;
     338             :   }
     339             : 
     340             :   static Configuration ComputeConfiguration(
     341             :       Configuration configuration, Handle<Name> name) {
     342   290133413 :     return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
     343             :   }
     344             : 
     345             :   static Handle<JSReceiver> GetRootForNonJSReceiver(
     346             :       Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
     347   222718339 :   inline static Handle<JSReceiver> GetRoot(Isolate* isolate,
     348             :                                            Handle<Object> receiver,
     349             :                                            uint32_t index = kMaxUInt32) {
     350   222718345 :     if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
     351      252579 :     return GetRootForNonJSReceiver(isolate, receiver, index);
     352             :   }
     353             : 
     354             :   State NotFound(JSReceiver* const holder) const;
     355             : 
     356             :   // If configuration_ becomes mutable, update
     357             :   // HolderIsReceiverOrHiddenPrototype.
     358             :   const Configuration configuration_;
     359             :   State state_;
     360             :   bool has_property_;
     361             :   InterceptorState interceptor_state_;
     362             :   PropertyDetails property_details_;
     363             :   Isolate* const isolate_;
     364             :   Handle<Name> name_;
     365             :   Handle<Object> transition_;
     366             :   const Handle<Object> receiver_;
     367             :   Handle<JSReceiver> holder_;
     368             :   const Handle<JSReceiver> initial_holder_;
     369             :   const uint32_t index_;
     370             :   uint32_t number_;
     371             : };
     372             : 
     373             : 
     374             : }  // namespace internal
     375             : }  // namespace v8
     376             : 
     377             : #endif  // V8_LOOKUP_H_

Generated by: LCOV version 1.10