| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_LOOKUP_H_ | 5 #ifndef V8_LOOKUP_H_ |
| 6 #define V8_LOOKUP_H_ | 6 #define V8_LOOKUP_H_ |
| 7 | 7 |
| 8 #include "src/factory.h" | 8 #include "src/factory.h" |
| 9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
| 10 #include "src/objects.h" | 10 #include "src/objects.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 class LookupIterator V8_FINAL BASE_EMBEDDED { | 15 class LookupIterator V8_FINAL BASE_EMBEDDED { |
| 16 public: | 16 public: |
| 17 enum Configuration { | 17 enum Configuration { |
| 18 // Configuration bits. | 18 // Configuration bits. |
| 19 CHECK_HIDDEN_PROPERTY = 1 << 0, | 19 kAccessCheck = 1 << 0, |
| 20 CHECK_DERIVED_PROPERTY = 1 << 1, | 20 kHidden = 1 << 1, |
| 21 CHECK_INTERCEPTOR = 1 << 2, | 21 kInterceptor = 1 << 2, |
| 22 CHECK_ACCESS_CHECK = 1 << 3, | 22 kPrototypeChain = 1 << 3, |
| 23 | 23 |
| 24 // Convience combinations of bits. | 24 // Convience combinations of bits. |
| 25 CHECK_PROPERTY = 0, | 25 OWN_PROPERTY = 0, |
| 26 CHECK_OWN = CHECK_ACCESS_CHECK | CHECK_INTERCEPTOR, | 26 OWN_SKIP_INTERCEPTOR = kAccessCheck, |
| 27 CHECK_HIDDEN_SKIP_INTERCEPTOR = CHECK_HIDDEN_PROPERTY | CHECK_ACCESS_CHECK, | 27 OWN = kAccessCheck | kInterceptor, |
| 28 CHECK_DERIVED_SKIP_INTERCEPTOR = | 28 HIDDEN_PROPERTY = kHidden, |
| 29 CHECK_HIDDEN_SKIP_INTERCEPTOR | CHECK_DERIVED_PROPERTY, | 29 HIDDEN_SKIP_INTERCEPTOR = kAccessCheck | kHidden, |
| 30 CHECK_DERIVED = CHECK_DERIVED_SKIP_INTERCEPTOR | CHECK_INTERCEPTOR, | 30 HIDDEN = kAccessCheck | kHidden | kInterceptor, |
| 31 CHECK_HIDDEN = CHECK_HIDDEN_SKIP_INTERCEPTOR | CHECK_INTERCEPTOR | 31 PROTOTYPE_CHAIN_PROPERTY = kHidden | kPrototypeChain, |
| 32 PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kAccessCheck | kHidden | kPrototypeChain, |
| 33 PROTOTYPE_CHAIN = kAccessCheck | kHidden | kPrototypeChain | kInterceptor |
| 32 }; | 34 }; |
| 33 | 35 |
| 34 enum State { | 36 enum State { |
| 35 ACCESS_CHECK, | 37 ACCESS_CHECK, |
| 36 INTERCEPTOR, | 38 INTERCEPTOR, |
| 37 JSPROXY, | 39 JSPROXY, |
| 38 NOT_FOUND, | 40 NOT_FOUND, |
| 39 PROPERTY, | 41 PROPERTY, |
| 40 TRANSITION, | 42 TRANSITION, |
| 41 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a | 43 // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a |
| 42 // PROPERTY lookup. | 44 // PROPERTY lookup. |
| 43 BEFORE_PROPERTY = INTERCEPTOR | 45 BEFORE_PROPERTY = INTERCEPTOR |
| 44 }; | 46 }; |
| 45 | 47 |
| 46 enum PropertyKind { | 48 enum PropertyKind { |
| 47 DATA, | 49 DATA, |
| 48 ACCESSOR | 50 ACCESSOR |
| 49 }; | 51 }; |
| 50 | 52 |
| 51 enum PropertyEncoding { | 53 enum PropertyEncoding { |
| 52 DICTIONARY, | 54 DICTIONARY, |
| 53 DESCRIPTOR | 55 DESCRIPTOR |
| 54 }; | 56 }; |
| 55 | 57 |
| 56 LookupIterator(Handle<Object> receiver, Handle<Name> name, | 58 LookupIterator(Handle<Object> receiver, Handle<Name> name, |
| 57 Configuration configuration = CHECK_DERIVED) | 59 Configuration configuration = PROTOTYPE_CHAIN) |
| 58 : configuration_(ComputeConfiguration(configuration, name)), | 60 : configuration_(ComputeConfiguration(configuration, name)), |
| 59 state_(NOT_FOUND), | 61 state_(NOT_FOUND), |
| 60 property_kind_(DATA), | 62 property_kind_(DATA), |
| 61 property_encoding_(DESCRIPTOR), | 63 property_encoding_(DESCRIPTOR), |
| 62 property_details_(NONE, NORMAL, Representation::None()), | 64 property_details_(NONE, NORMAL, Representation::None()), |
| 63 isolate_(name->GetIsolate()), | 65 isolate_(name->GetIsolate()), |
| 64 name_(name), | 66 name_(name), |
| 65 maybe_receiver_(receiver), | 67 maybe_receiver_(receiver), |
| 66 number_(DescriptorArray::kNotFound) { | 68 number_(DescriptorArray::kNotFound) { |
| 67 Handle<JSReceiver> root = GetRoot(); | 69 Handle<JSReceiver> root = GetRoot(); |
| 68 holder_map_ = handle(root->map(), isolate_); | 70 holder_map_ = handle(root->map(), isolate_); |
| 69 maybe_holder_ = root; | 71 maybe_holder_ = root; |
| 70 Next(); | 72 Next(); |
| 71 } | 73 } |
| 72 | 74 |
| 73 LookupIterator(Handle<Object> receiver, Handle<Name> name, | 75 LookupIterator(Handle<Object> receiver, Handle<Name> name, |
| 74 Handle<JSReceiver> holder, | 76 Handle<JSReceiver> holder, |
| 75 Configuration configuration = CHECK_DERIVED) | 77 Configuration configuration = PROTOTYPE_CHAIN) |
| 76 : configuration_(ComputeConfiguration(configuration, name)), | 78 : configuration_(ComputeConfiguration(configuration, name)), |
| 77 state_(NOT_FOUND), | 79 state_(NOT_FOUND), |
| 78 property_kind_(DATA), | 80 property_kind_(DATA), |
| 79 property_encoding_(DESCRIPTOR), | 81 property_encoding_(DESCRIPTOR), |
| 80 property_details_(NONE, NORMAL, Representation::None()), | 82 property_details_(NONE, NORMAL, Representation::None()), |
| 81 isolate_(name->GetIsolate()), | 83 isolate_(name->GetIsolate()), |
| 82 name_(name), | 84 name_(name), |
| 83 holder_map_(holder->map(), isolate_), | 85 holder_map_(holder->map(), isolate_), |
| 84 maybe_receiver_(receiver), | 86 maybe_receiver_(receiver), |
| 85 maybe_holder_(holder), | 87 maybe_holder_(holder), |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 | 186 |
| 185 bool IsBootstrapping() const; | 187 bool IsBootstrapping() const; |
| 186 | 188 |
| 187 // Methods that fetch data from the holder ensure they always have a holder. | 189 // Methods that fetch data from the holder ensure they always have a holder. |
| 188 // This means the receiver needs to be present as opposed to just the receiver | 190 // This means the receiver needs to be present as opposed to just the receiver |
| 189 // map. Other objects in the prototype chain are transitively guaranteed to be | 191 // map. Other objects in the prototype chain are transitively guaranteed to be |
| 190 // present via the receiver map. | 192 // present via the receiver map. |
| 191 bool is_guaranteed_to_have_holder() const { | 193 bool is_guaranteed_to_have_holder() const { |
| 192 return !maybe_receiver_.is_null(); | 194 return !maybe_receiver_.is_null(); |
| 193 } | 195 } |
| 196 bool check_access_check() const { |
| 197 return (configuration_ & kAccessCheck) != 0; |
| 198 } |
| 199 bool check_hidden() const { return (configuration_ & kHidden) != 0; } |
| 194 bool check_interceptor() const { | 200 bool check_interceptor() const { |
| 195 return !IsBootstrapping() && (configuration_ & CHECK_INTERCEPTOR) != 0; | 201 return !IsBootstrapping() && (configuration_ & kInterceptor) != 0; |
| 196 } | 202 } |
| 197 bool check_derived() const { | 203 bool check_prototype_chain() const { |
| 198 return (configuration_ & CHECK_DERIVED_PROPERTY) != 0; | 204 return (configuration_ & kPrototypeChain) != 0; |
| 199 } | |
| 200 bool check_hidden() const { | |
| 201 return (configuration_ & CHECK_HIDDEN_PROPERTY) != 0; | |
| 202 } | |
| 203 bool check_access_check() const { | |
| 204 return (configuration_ & CHECK_ACCESS_CHECK) != 0; | |
| 205 } | 205 } |
| 206 int descriptor_number() const { | 206 int descriptor_number() const { |
| 207 DCHECK(has_property_); | 207 DCHECK(has_property_); |
| 208 DCHECK_EQ(DESCRIPTOR, property_encoding_); | 208 DCHECK_EQ(DESCRIPTOR, property_encoding_); |
| 209 return number_; | 209 return number_; |
| 210 } | 210 } |
| 211 int dictionary_entry() const { | 211 int dictionary_entry() const { |
| 212 DCHECK(has_property_); | 212 DCHECK(has_property_); |
| 213 DCHECK_EQ(DICTIONARY, property_encoding_); | 213 DCHECK_EQ(DICTIONARY, property_encoding_); |
| 214 return number_; | 214 return number_; |
| 215 } | 215 } |
| 216 | 216 |
| 217 static Configuration ComputeConfiguration( | 217 static Configuration ComputeConfiguration( |
| 218 Configuration configuration, Handle<Name> name) { | 218 Configuration configuration, Handle<Name> name) { |
| 219 if (name->IsOwn()) { | 219 if (name->IsOwn()) { |
| 220 return static_cast<Configuration>(configuration & CHECK_HIDDEN); | 220 return static_cast<Configuration>(configuration & HIDDEN); |
| 221 } else { | 221 } else { |
| 222 return configuration; | 222 return configuration; |
| 223 } | 223 } |
| 224 } | 224 } |
| 225 | 225 |
| 226 // If configuration_ becomes mutable, update | 226 // If configuration_ becomes mutable, update |
| 227 // HolderIsReceiverOrHiddenPrototype. | 227 // HolderIsReceiverOrHiddenPrototype. |
| 228 Configuration configuration_; | 228 Configuration configuration_; |
| 229 State state_; | 229 State state_; |
| 230 bool has_property_; | 230 bool has_property_; |
| 231 PropertyKind property_kind_; | 231 PropertyKind property_kind_; |
| 232 PropertyEncoding property_encoding_; | 232 PropertyEncoding property_encoding_; |
| 233 PropertyDetails property_details_; | 233 PropertyDetails property_details_; |
| 234 Isolate* isolate_; | 234 Isolate* isolate_; |
| 235 Handle<Name> name_; | 235 Handle<Name> name_; |
| 236 Handle<Map> holder_map_; | 236 Handle<Map> holder_map_; |
| 237 Handle<Map> transition_map_; | 237 Handle<Map> transition_map_; |
| 238 MaybeHandle<Object> maybe_receiver_; | 238 MaybeHandle<Object> maybe_receiver_; |
| 239 MaybeHandle<JSReceiver> maybe_holder_; | 239 MaybeHandle<JSReceiver> maybe_holder_; |
| 240 | 240 |
| 241 int number_; | 241 int number_; |
| 242 }; | 242 }; |
| 243 | 243 |
| 244 | 244 |
| 245 } } // namespace v8::internal | 245 } } // namespace v8::internal |
| 246 | 246 |
| 247 #endif // V8_LOOKUP_H_ | 247 #endif // V8_LOOKUP_H_ |
| OLD | NEW |