Home | History | Annotate | Download | only in src
      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/isolate.h"
     10 #include "src/objects.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 class LookupIterator FINAL BASE_EMBEDDED {
     16  public:
     17   enum Configuration {
     18     // Configuration bits.
     19     kHidden = 1 << 0,
     20     kInterceptor = 1 << 1,
     21     kPrototypeChain = 1 << 2,
     22 
     23     // Convience combinations of bits.
     24     OWN_SKIP_INTERCEPTOR = 0,
     25     OWN = kInterceptor,
     26     HIDDEN_SKIP_INTERCEPTOR = kHidden,
     27     HIDDEN = kHidden | kInterceptor,
     28     PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain,
     29     PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor
     30   };
     31 
     32   enum State {
     33     ACCESS_CHECK,
     34     INTERCEPTOR,
     35     JSPROXY,
     36     NOT_FOUND,
     37     ACCESSOR,
     38     DATA,
     39     TRANSITION,
     40     // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
     41     // PROPERTY lookup.
     42     BEFORE_PROPERTY = INTERCEPTOR
     43   };
     44 
     45   LookupIterator(Handle<Object> receiver, Handle<Name> name,
     46                  Configuration configuration = PROTOTYPE_CHAIN)
     47       : configuration_(ComputeConfiguration(configuration, name)),
     48         state_(NOT_FOUND),
     49         property_details_(NONE, NORMAL, Representation::None()),
     50         isolate_(name->GetIsolate()),
     51         name_(name),
     52         receiver_(receiver),
     53         number_(DescriptorArray::kNotFound) {
     54     holder_ = GetRoot();
     55     holder_map_ = handle(holder_->map(), isolate_);
     56     Next();
     57   }
     58 
     59   LookupIterator(Handle<Object> receiver, Handle<Name> name,
     60                  Handle<JSReceiver> holder,
     61                  Configuration configuration = PROTOTYPE_CHAIN)
     62       : configuration_(ComputeConfiguration(configuration, name)),
     63         state_(NOT_FOUND),
     64         property_details_(NONE, NORMAL, Representation::None()),
     65         isolate_(name->GetIsolate()),
     66         name_(name),
     67         holder_map_(holder->map(), isolate_),
     68         receiver_(receiver),
     69         holder_(holder),
     70         number_(DescriptorArray::kNotFound) {
     71     Next();
     72   }
     73 
     74   Isolate* isolate() const { return isolate_; }
     75   State state() const { return state_; }
     76   Handle<Name> name() const { return name_; }
     77 
     78   bool IsFound() const { return state_ != NOT_FOUND; }
     79   void Next();
     80   void NotFound() {
     81     has_property_ = false;
     82     state_ = NOT_FOUND;
     83   }
     84 
     85   Factory* factory() const { return isolate_->factory(); }
     86   Handle<Object> GetReceiver() const { return receiver_; }
     87   Handle<JSObject> GetStoreTarget() const;
     88   bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
     89   Handle<Map> transition_map() const {
     90     DCHECK_EQ(TRANSITION, state_);
     91     return transition_map_;
     92   }
     93   template <class T>
     94   Handle<T> GetHolder() const {
     95     DCHECK(IsFound());
     96     return Handle<T>::cast(holder_);
     97   }
     98   Handle<JSReceiver> GetRoot() const;
     99   bool HolderIsReceiverOrHiddenPrototype() const;
    100 
    101   /* ACCESS_CHECK */
    102   bool HasAccess(v8::AccessType access_type) const;
    103 
    104   /* PROPERTY */
    105   void PrepareForDataProperty(Handle<Object> value);
    106   void PrepareTransitionToDataProperty(Handle<Object> value,
    107                                        PropertyAttributes attributes,
    108                                        Object::StoreFromKeyed store_mode);
    109   bool IsCacheableTransition() {
    110     bool cacheable =
    111         state_ == TRANSITION && transition_map()->GetBackPointer()->IsMap();
    112     if (cacheable) {
    113       property_details_ = transition_map_->GetLastDescriptorDetails();
    114       has_property_ = true;
    115     }
    116     return cacheable;
    117   }
    118   void ApplyTransitionToDataProperty();
    119   void ReconfigureDataProperty(Handle<Object> value,
    120                                PropertyAttributes attributes);
    121   void TransitionToAccessorProperty(AccessorComponent component,
    122                                     Handle<Object> accessor,
    123                                     PropertyAttributes attributes);
    124   PropertyDetails property_details() const {
    125     DCHECK(has_property_);
    126     return property_details_;
    127   }
    128   bool IsConfigurable() const { return property_details().IsConfigurable(); }
    129   bool IsReadOnly() const { return property_details().IsReadOnly(); }
    130   Representation representation() const {
    131     return property_details().representation();
    132   }
    133   FieldIndex GetFieldIndex() const;
    134   Handle<HeapType> GetFieldType() const;
    135   int GetConstantIndex() const;
    136   Handle<PropertyCell> GetPropertyCell() const;
    137   Handle<Object> GetAccessors() const;
    138   Handle<Object> GetDataValue() const;
    139   void WriteDataValue(Handle<Object> value);
    140 
    141   void InternalizeName();
    142 
    143  private:
    144   Handle<Map> GetReceiverMap() const;
    145 
    146   MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
    147   inline State LookupInHolder(Map* map, JSReceiver* holder);
    148   Handle<Object> FetchValue() const;
    149   void ReloadPropertyInformation();
    150 
    151   bool IsBootstrapping() const;
    152 
    153   bool check_hidden() const { return (configuration_ & kHidden) != 0; }
    154   bool check_interceptor() const {
    155     return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
    156   }
    157   bool check_prototype_chain() const {
    158     return (configuration_ & kPrototypeChain) != 0;
    159   }
    160   int descriptor_number() const {
    161     DCHECK(has_property_);
    162     DCHECK(!holder_map_->is_dictionary_map());
    163     return number_;
    164   }
    165   int dictionary_entry() const {
    166     DCHECK(has_property_);
    167     DCHECK(holder_map_->is_dictionary_map());
    168     return number_;
    169   }
    170 
    171   static Configuration ComputeConfiguration(
    172       Configuration configuration, Handle<Name> name) {
    173     if (name->IsOwn()) {
    174       return static_cast<Configuration>(configuration & HIDDEN);
    175     } else {
    176       return configuration;
    177     }
    178   }
    179 
    180   // If configuration_ becomes mutable, update
    181   // HolderIsReceiverOrHiddenPrototype.
    182   Configuration configuration_;
    183   State state_;
    184   bool has_property_;
    185   PropertyDetails property_details_;
    186   Isolate* isolate_;
    187   Handle<Name> name_;
    188   Handle<Map> holder_map_;
    189   Handle<Map> transition_map_;
    190   Handle<Object> receiver_;
    191   Handle<JSReceiver> holder_;
    192 
    193   int number_;
    194 };
    195 
    196 
    197 } }  // namespace v8::internal
    198 
    199 #endif  // V8_LOOKUP_H_
    200