lookup.h 6.09 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_LOOKUP_H_
#define V8_LOOKUP_H_

#include "src/factory.h"
#include "src/isolate.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

15
class LookupIterator FINAL BASE_EMBEDDED {
16
 public:
17
  enum Configuration {
18
    // Configuration bits.
19 20 21
    kHidden = 1 << 0,
    kInterceptor = 1 << 1,
    kPrototypeChain = 1 << 2,
22 23

    // Convience combinations of bits.
24 25 26 27 28 29
    OWN_SKIP_INTERCEPTOR = 0,
    OWN = kInterceptor,
    HIDDEN_SKIP_INTERCEPTOR = kHidden,
    HIDDEN = kHidden | kInterceptor,
    PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain,
    PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor
30 31 32
  };

  enum State {
33 34 35
    ACCESS_CHECK,
    INTERCEPTOR,
    JSPROXY,
36
    NOT_FOUND,
37 38
    ACCESSOR,
    DATA,
39
    TRANSITION,
40 41 42
    // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a
    // PROPERTY lookup.
    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 51
        isolate_(name->GetIsolate()),
        name_(name),
52
        receiver_(receiver),
53
        number_(DescriptorArray::kNotFound) {
54 55
    holder_ = GetRoot();
    holder_map_ = handle(holder_->map(), isolate_);
56 57 58
    Next();
  }

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 66
        isolate_(name->GetIsolate()),
        name_(name),
67
        holder_map_(holder->map(), isolate_),
68 69
        receiver_(receiver),
        holder_(holder),
70 71 72 73 74 75 76 77 78 79
        number_(DescriptorArray::kNotFound) {
    Next();
  }

  Isolate* isolate() const { return isolate_; }
  State state() const { return state_; }
  Handle<Name> name() const { return name_; }

  bool IsFound() const { return state_ != NOT_FOUND; }
  void Next();
80 81 82 83
  void NotFound() {
    has_property_ = false;
    state_ = NOT_FOUND;
  }
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 90 91 92
  Handle<Map> transition_map() const {
    DCHECK_EQ(TRANSITION, state_);
    return transition_map_;
  }
93 94
  template <class T>
  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 102 103 104
  /* ACCESS_CHECK */
  bool HasAccess(v8::AccessType access_type) const;

  /* PROPERTY */
105
  void PrepareForDataProperty(Handle<Object> value);
106 107 108 109 110 111 112 113 114 115 116 117 118
  void PrepareTransitionToDataProperty(Handle<Object> value,
                                       PropertyAttributes attributes,
                                       Object::StoreFromKeyed store_mode);
  bool IsCacheableTransition() {
    bool cacheable =
        state_ == TRANSITION && transition_map()->GetBackPointer()->IsMap();
    if (cacheable) {
      property_details_ = transition_map_->GetLastDescriptorDetails();
      has_property_ = true;
    }
    return cacheable;
  }
  void ApplyTransitionToDataProperty();
119 120
  void ReconfigureDataProperty(Handle<Object> value,
                               PropertyAttributes attributes);
121 122 123
  void TransitionToAccessorProperty(AccessorComponent component,
                                    Handle<Object> accessor,
                                    PropertyAttributes attributes);
124
  PropertyDetails property_details() const {
125
    DCHECK(has_property_);
126 127
    return property_details_;
  }
128
  bool IsConfigurable() const { return property_details().IsConfigurable(); }
129
  bool IsReadOnly() const { return property_details().IsReadOnly(); }
130 131
  Representation representation() const {
    return property_details().representation();
132
  }
133
  FieldIndex GetFieldIndex() const;
134
  Handle<HeapType> GetFieldType() const;
135
  int GetConstantIndex() const;
136
  Handle<PropertyCell> GetPropertyCell() const;
137 138
  Handle<Object> GetAccessors() const;
  Handle<Object> GetDataValue() const;
139
  void WriteDataValue(Handle<Object> value);
140

141 142 143 144
  // Checks whether the receiver is an indexed exotic object
  // and name is a special numeric index.
  bool IsSpecialNumericIndex() const;

145
  void InternalizeName();
146 147 148 149

 private:
  Handle<Map> GetReceiverMap() const;

150
  MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
151
  inline State LookupInHolder(Map* map, JSReceiver* holder);
152
  Handle<Object> FetchValue() const;
153
  void ReloadPropertyInformation();
154 155 156

  bool IsBootstrapping() const;

157 158 159
  bool check_hidden() const { return (configuration_ & kHidden) != 0; }
  bool check_interceptor() const {
    return !IsBootstrapping() && (configuration_ & kInterceptor) != 0;
160
  }
161 162
  bool check_prototype_chain() const {
    return (configuration_ & kPrototypeChain) != 0;
163
  }
164
  int descriptor_number() const {
165
    DCHECK(has_property_);
166
    DCHECK(!holder_map_->is_dictionary_map());
167 168 169
    return number_;
  }
  int dictionary_entry() const {
170
    DCHECK(has_property_);
171
    DCHECK(holder_map_->is_dictionary_map());
172 173
    return number_;
  }
174

175 176 177
  static Configuration ComputeConfiguration(
      Configuration configuration, Handle<Name> name) {
    if (name->IsOwn()) {
178
      return static_cast<Configuration>(configuration & HIDDEN);
179 180 181 182 183
    } else {
      return configuration;
    }
  }

184 185
  // If configuration_ becomes mutable, update
  // HolderIsReceiverOrHiddenPrototype.
186
  Configuration configuration_;
187 188 189 190 191 192
  State state_;
  bool has_property_;
  PropertyDetails property_details_;
  Isolate* isolate_;
  Handle<Name> name_;
  Handle<Map> holder_map_;
193
  Handle<Map> transition_map_;
194 195
  Handle<Object> receiver_;
  Handle<JSReceiver> holder_;
196 197 198 199 200 201 202 203

  int number_;
};


} }  // namespace v8::internal

#endif  // V8_LOOKUP_H_