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) configuration_(configuration)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) configuration_(configuration)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 isolate()83 Isolate* isolate() const { return isolate_; } state()84 State state() const { return state_; } name()85 Handle<Name> name() const { return name_; } 86 IsFound()87 bool IsFound() const { return state_ != NOT_FOUND; } 88 void Next(); 89 heap()90 Heap* heap() const { return isolate_->heap(); } factory()91 Factory* factory() const { return isolate_->factory(); } GetReceiver()92 Handle<Object> GetReceiver() const { 93 return Handle<Object>::cast(maybe_receiver_.ToHandleChecked()); 94 } GetHolder()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. */ skip_interceptor()102 void skip_interceptor() { 103 configuration_ = static_cast<Configuration>( 104 configuration_ & ~CHECK_INTERCEPTOR); 105 } skip_access_check()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(); property_kind()119 PropertyKind property_kind() const { 120 ASSERT(has_property_); 121 return property_kind_; 122 } property_details()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 GetJSProxy()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. is_guaranteed_to_have_holder()149 bool is_guaranteed_to_have_holder() const { 150 return !maybe_receiver_.is_null(); 151 } check_interceptor()152 bool check_interceptor() const { 153 return !IsBootstrapping() && (configuration_ & CHECK_INTERCEPTOR) != 0; 154 } check_derived()155 bool check_derived() const { 156 return (configuration_ & CHECK_DERIVED) != 0; 157 } check_hidden()158 bool check_hidden() const { 159 return (configuration_ & CHECK_HIDDEN) != 0; 160 } check_access_check()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