v8/src/lookup.h
2015-03-18 12:50:48 +00:00

224 lines
7.1 KiB
C++

// 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,
INTEGER_INDEXED_EXOTIC,
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<Object> receiver, Handle<Name> name,
Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(name->GetIsolate()),
name_(name),
receiver_(receiver),
holder_(GetRoot(receiver_, isolate_)),
holder_map_(holder_->map(), isolate_),
initial_holder_(holder_),
number_(DescriptorArray::kNotFound) {
Next();
}
LookupIterator(Handle<Object> receiver, Handle<Name> name,
Handle<JSReceiver> holder,
Configuration configuration = PROTOTYPE_CHAIN)
: configuration_(ComputeConfiguration(configuration, name)),
state_(NOT_FOUND),
exotic_index_state_(ExoticIndexState::kUninitialized),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(name->GetIsolate()),
name_(name),
receiver_(receiver),
holder_(holder),
holder_map_(holder_->map(), isolate_),
initial_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();
void NotFound() {
has_property_ = false;
state_ = NOT_FOUND;
}
Factory* factory() const { return isolate_->factory(); }
Handle<Object> GetReceiver() const { return receiver_; }
Handle<JSObject> GetStoreTarget() const;
bool is_dictionary_holder() const { return holder_map_->is_dictionary_map(); }
Handle<Map> transition_map() const {
DCHECK_EQ(TRANSITION, state_);
return Handle<Map>::cast(transition_);
}
template <class T>
Handle<T> GetHolder() const {
DCHECK(IsFound());
return Handle<T>::cast(holder_);
}
static Handle<JSReceiver> GetRoot(Handle<Object> receiver, Isolate* isolate);
bool HolderIsReceiverOrHiddenPrototype() const;
/* ACCESS_CHECK */
bool HasAccess() const;
/* PROPERTY */
void PrepareForDataProperty(Handle<Object> value);
void PrepareTransitionToDataProperty(Handle<Object> value,
PropertyAttributes attributes,
Object::StoreFromKeyed store_mode);
bool IsCacheableTransition() {
if (state_ != TRANSITION) return false;
return transition_->IsPropertyCell() ||
transition_map()->GetBackPointer()->IsMap();
}
void ApplyTransitionToDataProperty();
void ReconfigureDataProperty(Handle<Object> value,
PropertyAttributes attributes);
void TransitionToAccessorProperty(AccessorComponent component,
Handle<Object> 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<HeapType> GetFieldType() const;
int GetAccessorIndex() const;
int GetConstantIndex() const;
Handle<PropertyCell> GetPropertyCell() const;
Handle<PropertyCell> GetTransitionPropertyCell() const {
DCHECK_EQ(TRANSITION, state_);
return Handle<PropertyCell>::cast(transition_);
}
Handle<Object> GetAccessors() const;
Handle<Object> GetDataValue() const;
// Usually returns the value that was passed in, but may perform
// non-observable modifications on it, such as internalize strings.
Handle<Object> WriteDataValue(Handle<Object> value);
void InternalizeName();
private:
enum class InterceptorState {
kUninitialized,
kSkipNonMasking,
kProcessNonMasking
};
Handle<Map> GetReceiverMap() const;
MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
inline State LookupInHolder(Map* map, JSReceiver* holder);
void RestartLookupForNonMaskingInterceptors();
State LookupNonMaskingInterceptorInHolder(Map* map, JSReceiver* holder);
Handle<Object> FetchValue() const;
void ReloadPropertyInformation();
bool SkipInterceptor(JSObject* holder);
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> name) {
if (name->IsOwn()) {
return static_cast<Configuration>(configuration &
HIDDEN_SKIP_INTERCEPTOR);
} else {
return configuration;
}
}
enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex };
bool IsIntegerIndexedExotic(JSReceiver* holder);
// If configuration_ becomes mutable, update
// HolderIsReceiverOrHiddenPrototype.
const Configuration configuration_;
State state_;
bool has_property_;
ExoticIndexState exotic_index_state_;
InterceptorState interceptor_state_;
PropertyDetails property_details_;
Isolate* const isolate_;
Handle<Name> name_;
Handle<Object> transition_;
const Handle<Object> receiver_;
Handle<JSReceiver> holder_;
Handle<Map> holder_map_;
const Handle<JSReceiver> initial_holder_;
int number_;
};
} } // namespace v8::internal
#endif // V8_LOOKUP_H_