blob: 923e8107fd3a36c159b4396b458de7962baca666 [file] [log] [blame]
// 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_