// 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 FINAL BASE_EMBEDDED { public: enum Configuration { // Configuration bits. kHidden = 1 << 0, kInterceptor = 1 << 1, kPrototypeChain = 1 << 2, // Convience combinations of bits. OWN_SKIP_INTERCEPTOR = 0, OWN = kInterceptor, HIDDEN_SKIP_INTERCEPTOR = kHidden, HIDDEN = kHidden | kInterceptor, PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kHidden | kPrototypeChain, PROTOTYPE_CHAIN = kHidden | kPrototypeChain | kInterceptor }; enum State { ACCESS_CHECK, INTERCEPTOR, JSPROXY, NOT_FOUND, ACCESSOR, DATA, TRANSITION, // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will be a // PROPERTY lookup. BEFORE_PROPERTY = INTERCEPTOR }; LookupIterator(Handle receiver, Handle name, Configuration configuration = PROTOTYPE_CHAIN) : configuration_(ComputeConfiguration(configuration, name)), state_(NOT_FOUND), property_details_(NONE, NORMAL, Representation::None()), isolate_(name->GetIsolate()), name_(name), receiver_(receiver), number_(DescriptorArray::kNotFound) { holder_ = GetRoot(); holder_map_ = handle(holder_->map(), isolate_); Next(); } LookupIterator(Handle receiver, Handle name, Handle holder, Configuration configuration = PROTOTYPE_CHAIN) : configuration_(ComputeConfiguration(configuration, name)), state_(NOT_FOUND), property_details_(NONE, NORMAL, Representation::None()), isolate_(name->GetIsolate()), name_(name), holder_map_(holder->map(), isolate_), receiver_(receiver), holder_(holder), number_(DescriptorArray::kNotFound) { Next(); } Isolate* isolate() const { return isolate_; } State state() const { return state_; } Handle name() const { return name_; } bool IsFound() const { return state_ != NOT_FOUND; } void Next(); void NotFound() { has_property_ = false; state_ = NOT_FOUND; } Factory* factory() const { return isolate_->factory(); } Handle GetReceiver() const { return receiver_; } Handle GetStoreTarget() const; bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); } Handle transition_map() const { DCHECK_EQ(TRANSITION, state_); return transition_map_; } template Handle GetHolder() const { DCHECK(IsFound()); return Handle::cast(holder_); } Handle GetRoot() const; bool HolderIsReceiverOrHiddenPrototype() const; /* ACCESS_CHECK */ bool HasAccess(v8::AccessType access_type) const; /* PROPERTY */ void PrepareForDataProperty(Handle value); void PrepareTransitionToDataProperty(Handle 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(); void ReconfigureDataProperty(Handle value, PropertyAttributes attributes); void TransitionToAccessorProperty(AccessorComponent component, Handle accessor, PropertyAttributes attributes); PropertyDetails property_details() const { DCHECK(has_property_); return property_details_; } bool IsConfigurable() const { return property_details().IsConfigurable(); } bool IsReadOnly() const { return property_details().IsReadOnly(); } Representation representation() const { return property_details().representation(); } FieldIndex GetFieldIndex() const; Handle GetFieldType() const; int GetConstantIndex() const; Handle GetPropertyCell() const; Handle GetAccessors() const; Handle GetDataValue() const; void WriteDataValue(Handle value); void InternalizeName(); private: Handle GetReceiverMap() const; MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map); inline State LookupInHolder(Map* map, JSReceiver* holder); Handle FetchValue() const; void ReloadPropertyInformation(); bool IsBootstrapping() const; bool check_hidden() const { return (configuration_ & kHidden) != 0; } bool check_interceptor() const { return !IsBootstrapping() && (configuration_ & kInterceptor) != 0; } bool check_prototype_chain() const { return (configuration_ & kPrototypeChain) != 0; } int descriptor_number() const { DCHECK(has_property_); DCHECK(!holder_map_->is_dictionary_map()); return number_; } int dictionary_entry() const { DCHECK(has_property_); DCHECK(holder_map_->is_dictionary_map()); return number_; } static Configuration ComputeConfiguration( Configuration configuration, Handle name) { if (name->IsOwn()) { return static_cast(configuration & HIDDEN); } else { return configuration; } } // If configuration_ becomes mutable, update // HolderIsReceiverOrHiddenPrototype. Configuration configuration_; State state_; bool has_property_; PropertyDetails property_details_; Isolate* isolate_; Handle name_; Handle holder_map_; Handle transition_map_; Handle receiver_; Handle holder_; int number_; }; } } // namespace v8::internal #endif // V8_LOOKUP_H_