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) configuration_(ComputeConfiguration (configuration,name))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) configuration_(ComputeConfiguration (configuration,name))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 isolate()74 Isolate* isolate() const { return isolate_; } state()75 State state() const { return state_; } name()76 Handle<Name> name() const { return name_; } 77 IsFound()78 bool IsFound() const { return state_ != NOT_FOUND; } 79 void Next(); NotFound()80 void NotFound() { 81 has_property_ = false; 82 state_ = NOT_FOUND; 83 } 84 factory()85 Factory* factory() const { return isolate_->factory(); } GetReceiver()86 Handle<Object> GetReceiver() const { return receiver_; } 87 Handle<JSObject> GetStoreTarget() const; is_dictionary_holder()88 bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); } transition_map()89 Handle<Map> transition_map() const { 90 DCHECK_EQ(TRANSITION, state_); 91 return transition_map_; 92 } 93 template <class T> GetHolder()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); IsCacheableTransition()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); property_details()124 PropertyDetails property_details() const { 125 DCHECK(has_property_); 126 return property_details_; 127 } IsConfigurable()128 bool IsConfigurable() const { return property_details().IsConfigurable(); } IsReadOnly()129 bool IsReadOnly() const { return property_details().IsReadOnly(); } representation()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 check_hidden()153 bool check_hidden() const { return (configuration_ & kHidden) != 0; } check_interceptor()154 bool check_interceptor() const { 155 return !IsBootstrapping() && (configuration_ & kInterceptor) != 0; 156 } check_prototype_chain()157 bool check_prototype_chain() const { 158 return (configuration_ & kPrototypeChain) != 0; 159 } descriptor_number()160 int descriptor_number() const { 161 DCHECK(has_property_); 162 DCHECK(!holder_map_->is_dictionary_map()); 163 return number_; 164 } dictionary_entry()165 int dictionary_entry() const { 166 DCHECK(has_property_); 167 DCHECK(holder_map_->is_dictionary_map()); 168 return number_; 169 } 170 ComputeConfiguration(Configuration configuration,Handle<Name> name)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