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 V8_FINAL BASE_EMBEDDED {
     16  public:
     17   enum Configuration {
     18     CHECK_OWN_REAL     = 0,
     19     CHECK_HIDDEN       = 1 << 0,
     20     CHECK_DERIVED      = 1 << 1,
     21     CHECK_INTERCEPTOR  = 1 << 2,
     22     CHECK_ACCESS_CHECK = 1 << 3,
     23     CHECK_ALL          = CHECK_HIDDEN | CHECK_DERIVED |
     24                          CHECK_INTERCEPTOR | CHECK_ACCESS_CHECK,
     25     SKIP_INTERCEPTOR   = CHECK_ALL ^ CHECK_INTERCEPTOR,
     26     CHECK_OWN          = CHECK_ALL ^ CHECK_DERIVED
     27   };
     28 
     29   enum State {
     30     NOT_FOUND,
     31     PROPERTY,
     32     INTERCEPTOR,
     33     ACCESS_CHECK,
     34     JSPROXY
     35   };
     36 
     37   enum PropertyKind {
     38     DATA,
     39     ACCESSOR
     40   };
     41 
     42   enum PropertyEncoding {
     43     DICTIONARY,
     44     DESCRIPTOR
     45   };
     46 
     47   LookupIterator(Handle<Object> receiver,
     48                  Handle<Name> name,
     49                  Configuration configuration = CHECK_ALL)
     50       : configuration_(configuration),
     51         state_(NOT_FOUND),
     52         property_kind_(DATA),
     53         property_encoding_(DESCRIPTOR),
     54         property_details_(NONE, NONEXISTENT, Representation::None()),
     55         isolate_(name->GetIsolate()),
     56         name_(name),
     57         maybe_receiver_(receiver),
     58         number_(DescriptorArray::kNotFound) {
     59     Handle<JSReceiver> root = GetRoot();
     60     holder_map_ = handle(root->map());
     61     maybe_holder_ = root;
     62     Next();
     63   }
     64 
     65   LookupIterator(Handle<Object> receiver,
     66                  Handle<Name> name,
     67                  Handle<JSReceiver> holder,
     68                  Configuration configuration = CHECK_ALL)
     69       : configuration_(configuration),
     70         state_(NOT_FOUND),
     71         property_kind_(DATA),
     72         property_encoding_(DESCRIPTOR),
     73         property_details_(NONE, NONEXISTENT, Representation::None()),
     74         isolate_(name->GetIsolate()),
     75         name_(name),
     76         holder_map_(holder->map()),
     77         maybe_receiver_(receiver),
     78         maybe_holder_(holder),
     79         number_(DescriptorArray::kNotFound) {
     80     Next();
     81   }
     82 
     83   Isolate* isolate() const { return isolate_; }
     84   State state() const { return state_; }
     85   Handle<Name> name() const { return name_; }
     86 
     87   bool IsFound() const { return state_ != NOT_FOUND; }
     88   void Next();
     89 
     90   Heap* heap() const { return isolate_->heap(); }
     91   Factory* factory() const { return isolate_->factory(); }
     92   Handle<Object> GetReceiver() const {
     93     return Handle<Object>::cast(maybe_receiver_.ToHandleChecked());
     94   }
     95   Handle<JSObject> GetHolder() const {
     96     ASSERT(IsFound() && state_ != JSPROXY);
     97     return Handle<JSObject>::cast(maybe_holder_.ToHandleChecked());
     98   }
     99   Handle<JSReceiver> GetRoot() const;
    100 
    101   /* Dynamically reduce the trapped types. */
    102   void skip_interceptor() {
    103     configuration_ = static_cast<Configuration>(
    104         configuration_ & ~CHECK_INTERCEPTOR);
    105   }
    106   void skip_access_check() {
    107     configuration_ = static_cast<Configuration>(
    108         configuration_ & ~CHECK_ACCESS_CHECK);
    109   }
    110 
    111   /* ACCESS_CHECK */
    112   bool HasAccess(v8::AccessType access_type) const;
    113 
    114   /* PROPERTY */
    115   // HasProperty needs to be called before any of the other PROPERTY methods
    116   // below can be used. It ensures that we are able to provide a definite
    117   // answer, and loads extra information about the property.
    118   bool HasProperty();
    119   PropertyKind property_kind() const {
    120     ASSERT(has_property_);
    121     return property_kind_;
    122   }
    123   PropertyDetails property_details() const {
    124     ASSERT(has_property_);
    125     return property_details_;
    126   }
    127   Handle<Object> GetAccessors() const;
    128   Handle<Object> GetDataValue() const;
    129 
    130   /* JSPROXY */
    131 
    132   Handle<JSProxy> GetJSProxy() const {
    133     return Handle<JSProxy>::cast(maybe_holder_.ToHandleChecked());
    134   }
    135 
    136  private:
    137   Handle<Map> GetReceiverMap() const;
    138 
    139   MUST_USE_RESULT bool NextHolder();
    140   State LookupInHolder();
    141   Handle<Object> FetchValue() const;
    142 
    143   bool IsBootstrapping() const;
    144 
    145   // Methods that fetch data from the holder ensure they always have a holder.
    146   // This means the receiver needs to be present as opposed to just the receiver
    147   // map. Other objects in the prototype chain are transitively guaranteed to be
    148   // present via the receiver map.
    149   bool is_guaranteed_to_have_holder() const {
    150     return !maybe_receiver_.is_null();
    151   }
    152   bool check_interceptor() const {
    153     return !IsBootstrapping() && (configuration_ & CHECK_INTERCEPTOR) != 0;
    154   }
    155   bool check_derived() const {
    156     return (configuration_ & CHECK_DERIVED) != 0;
    157   }
    158   bool check_hidden() const {
    159     return (configuration_ & CHECK_HIDDEN) != 0;
    160   }
    161   bool check_access_check() const {
    162     return (configuration_ & CHECK_ACCESS_CHECK) != 0;
    163   }
    164 
    165   Configuration configuration_;
    166   State state_;
    167   bool has_property_;
    168   PropertyKind property_kind_;
    169   PropertyEncoding property_encoding_;
    170   PropertyDetails property_details_;
    171   Isolate* isolate_;
    172   Handle<Name> name_;
    173   Handle<Map> holder_map_;
    174   MaybeHandle<Object> maybe_receiver_;
    175   MaybeHandle<JSReceiver> maybe_holder_;
    176 
    177   int number_;
    178 };
    179 
    180 
    181 } }  // namespace v8::internal
    182 
    183 #endif  // V8_LOOKUP_H_
    184