| // 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 { |
| |
| class LookupIterator V8_FINAL BASE_EMBEDDED { |
| public: |
| enum Configuration { |
| CHECK_OWN_REAL = 0, |
| CHECK_HIDDEN = 1 << 0, |
| CHECK_DERIVED = 1 << 1, |
| CHECK_INTERCEPTOR = 1 << 2, |
| CHECK_ACCESS_CHECK = 1 << 3, |
| CHECK_ALL = CHECK_HIDDEN | CHECK_DERIVED | |
| CHECK_INTERCEPTOR | CHECK_ACCESS_CHECK, |
| SKIP_INTERCEPTOR = CHECK_ALL ^ CHECK_INTERCEPTOR, |
| CHECK_OWN = CHECK_ALL ^ CHECK_DERIVED |
| }; |
| |
| enum State { |
| NOT_FOUND, |
| PROPERTY, |
| INTERCEPTOR, |
| ACCESS_CHECK, |
| JSPROXY |
| }; |
| |
| enum PropertyKind { |
| DATA, |
| ACCESSOR |
| }; |
| |
| enum PropertyEncoding { |
| DICTIONARY, |
| DESCRIPTOR |
| }; |
| |
| LookupIterator(Handle<Object> receiver, |
| Handle<Name> name, |
| Configuration configuration = CHECK_ALL) |
| : configuration_(configuration), |
| state_(NOT_FOUND), |
| property_kind_(DATA), |
| property_encoding_(DESCRIPTOR), |
| property_details_(NONE, NONEXISTENT, Representation::None()), |
| isolate_(name->GetIsolate()), |
| name_(name), |
| maybe_receiver_(receiver), |
| number_(DescriptorArray::kNotFound) { |
| Handle<JSReceiver> root = GetRoot(); |
| holder_map_ = handle(root->map()); |
| maybe_holder_ = root; |
| Next(); |
| } |
| |
| LookupIterator(Handle<Object> receiver, |
| Handle<Name> name, |
| Handle<JSReceiver> holder, |
| Configuration configuration = CHECK_ALL) |
| : configuration_(configuration), |
| state_(NOT_FOUND), |
| property_kind_(DATA), |
| property_encoding_(DESCRIPTOR), |
| property_details_(NONE, NONEXISTENT, Representation::None()), |
| isolate_(name->GetIsolate()), |
| name_(name), |
| holder_map_(holder->map()), |
| maybe_receiver_(receiver), |
| maybe_holder_(holder), |
| 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(); |
| |
| Heap* heap() const { return isolate_->heap(); } |
| Factory* factory() const { return isolate_->factory(); } |
| Handle<Object> GetReceiver() const { |
| return Handle<Object>::cast(maybe_receiver_.ToHandleChecked()); |
| } |
| Handle<Map> holder_map() const { return holder_map_; } |
| template <class T> |
| Handle<T> GetHolder() const { |
| DCHECK(IsFound()); |
| return Handle<T>::cast(maybe_holder_.ToHandleChecked()); |
| } |
| Handle<JSReceiver> GetRoot() const; |
| bool HolderIsReceiverOrHiddenPrototype() const; |
| |
| /* Dynamically reduce the trapped types. */ |
| void skip_interceptor() { |
| configuration_ = static_cast<Configuration>( |
| configuration_ & ~CHECK_INTERCEPTOR); |
| } |
| void skip_access_check() { |
| configuration_ = static_cast<Configuration>( |
| configuration_ & ~CHECK_ACCESS_CHECK); |
| } |
| |
| /* ACCESS_CHECK */ |
| bool HasAccess(v8::AccessType access_type) const; |
| |
| /* PROPERTY */ |
| // HasProperty needs to be called before any of the other PROPERTY methods |
| // below can be used. It ensures that we are able to provide a definite |
| // answer, and loads extra information about the property. |
| bool HasProperty(); |
| void PrepareForDataProperty(Handle<Object> value); |
| void TransitionToDataProperty(Handle<Object> value, |
| PropertyAttributes attributes, |
| Object::StoreFromKeyed store_mode); |
| PropertyKind property_kind() const { |
| DCHECK(has_property_); |
| return property_kind_; |
| } |
| PropertyEncoding property_encoding() const { |
| DCHECK(has_property_); |
| return property_encoding_; |
| } |
| PropertyDetails property_details() const { |
| DCHECK(has_property_); |
| return property_details_; |
| } |
| bool IsConfigurable() const { return !property_details().IsDontDelete(); } |
| Representation representation() const { |
| return property_details().representation(); |
| } |
| FieldIndex GetFieldIndex() const; |
| int GetConstantIndex() const; |
| Handle<PropertyCell> GetPropertyCell() const; |
| Handle<Object> GetAccessors() const; |
| Handle<Object> GetDataValue() const; |
| void WriteDataValue(Handle<Object> value); |
| |
| void InternalizeName(); |
| |
| private: |
| Handle<Map> GetReceiverMap() const; |
| |
| MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map); |
| inline State LookupInHolder(Map* map); |
| Handle<Object> FetchValue() const; |
| |
| bool IsBootstrapping() const; |
| |
| // Methods that fetch data from the holder ensure they always have a holder. |
| // This means the receiver needs to be present as opposed to just the receiver |
| // map. Other objects in the prototype chain are transitively guaranteed to be |
| // present via the receiver map. |
| bool is_guaranteed_to_have_holder() const { |
| return !maybe_receiver_.is_null(); |
| } |
| bool check_interceptor() const { |
| return !IsBootstrapping() && (configuration_ & CHECK_INTERCEPTOR) != 0; |
| } |
| bool check_derived() const { |
| return (configuration_ & CHECK_DERIVED) != 0; |
| } |
| bool check_hidden() const { |
| return (configuration_ & CHECK_HIDDEN) != 0; |
| } |
| bool check_access_check() const { |
| return (configuration_ & CHECK_ACCESS_CHECK) != 0; |
| } |
| int descriptor_number() const { |
| DCHECK(has_property_); |
| DCHECK_EQ(DESCRIPTOR, property_encoding_); |
| return number_; |
| } |
| int dictionary_entry() const { |
| DCHECK(has_property_); |
| DCHECK_EQ(DICTIONARY, property_encoding_); |
| return number_; |
| } |
| |
| Configuration configuration_; |
| State state_; |
| bool has_property_; |
| PropertyKind property_kind_; |
| PropertyEncoding property_encoding_; |
| PropertyDetails property_details_; |
| Isolate* isolate_; |
| Handle<Name> name_; |
| Handle<Map> holder_map_; |
| MaybeHandle<Object> maybe_receiver_; |
| MaybeHandle<JSReceiver> maybe_holder_; |
| |
| int number_; |
| }; |
| |
| |
| } } // namespace v8::internal |
| |
| #endif // V8_LOOKUP_H_ |