056f927861
Tbr: ahaas@chromium.org,leszeks@chromium.org,verwaest@chromium.org Bug: v8:3770 Change-Id: Ia6530fbb70dac05e9972283781c3550d8b50e1eb Reviewed-on: https://chromium-review.googlesource.com/c/1390116 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Alexei Filippov <alph@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#58470}
284 lines
9.7 KiB
C++
284 lines
9.7 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/globals.h"
|
|
#include "src/heap/factory.h"
|
|
#include "src/isolate.h"
|
|
#include "src/objects.h"
|
|
#include "src/objects/descriptor-array.h"
|
|
#include "src/objects/js-objects.h"
|
|
#include "src/objects/map.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
class V8_EXPORT_PRIVATE LookupIterator final {
|
|
public:
|
|
enum Configuration {
|
|
// Configuration bits.
|
|
kInterceptor = 1 << 0,
|
|
kPrototypeChain = 1 << 1,
|
|
|
|
// Convenience combinations of bits.
|
|
OWN_SKIP_INTERCEPTOR = 0,
|
|
OWN = kInterceptor,
|
|
PROTOTYPE_CHAIN_SKIP_INTERCEPTOR = kPrototypeChain,
|
|
PROTOTYPE_CHAIN = kPrototypeChain | kInterceptor,
|
|
DEFAULT = PROTOTYPE_CHAIN
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
|
|
Handle<Name> name,
|
|
Configuration configuration = DEFAULT);
|
|
|
|
inline LookupIterator(Handle<Object> receiver, Handle<Name> name,
|
|
Handle<JSReceiver> holder,
|
|
Configuration configuration = DEFAULT);
|
|
|
|
inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
|
|
Handle<Name> name, Handle<JSReceiver> holder,
|
|
Configuration configuration = DEFAULT);
|
|
|
|
inline LookupIterator(Isolate* isolate, Handle<Object> receiver,
|
|
uint32_t index, Configuration configuration = DEFAULT);
|
|
|
|
LookupIterator(Isolate* isolate, Handle<Object> receiver, uint32_t index,
|
|
Handle<JSReceiver> holder,
|
|
Configuration configuration = DEFAULT)
|
|
: configuration_(configuration),
|
|
interceptor_state_(InterceptorState::kUninitialized),
|
|
property_details_(PropertyDetails::Empty()),
|
|
isolate_(isolate),
|
|
receiver_(receiver),
|
|
initial_holder_(holder),
|
|
index_(index),
|
|
number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
|
|
// kMaxUInt32 isn't a valid index.
|
|
DCHECK_NE(kMaxUInt32, index_);
|
|
Start<true>();
|
|
}
|
|
|
|
static inline LookupIterator PropertyOrElement(
|
|
Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
|
|
Configuration configuration = DEFAULT);
|
|
|
|
static inline LookupIterator PropertyOrElement(
|
|
Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
|
|
Handle<JSReceiver> holder, Configuration configuration = DEFAULT);
|
|
|
|
static LookupIterator PropertyOrElement(
|
|
Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
|
|
bool* success, Handle<JSReceiver> holder,
|
|
Configuration configuration = DEFAULT);
|
|
|
|
static LookupIterator PropertyOrElement(
|
|
Isolate* isolate, Handle<Object> receiver, Handle<Object> key,
|
|
bool* success, Configuration configuration = DEFAULT);
|
|
|
|
static LookupIterator ForTransitionHandler(
|
|
Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
|
|
Handle<Object> value, MaybeHandle<Map> maybe_transition_map);
|
|
|
|
void Restart() {
|
|
InterceptorState state = InterceptorState::kUninitialized;
|
|
IsElement() ? RestartInternal<true>(state) : RestartInternal<false>(state);
|
|
}
|
|
|
|
Isolate* isolate() const { return isolate_; }
|
|
State state() const { return state_; }
|
|
|
|
Handle<Name> name() const {
|
|
DCHECK(!IsElement());
|
|
return name_;
|
|
}
|
|
inline Handle<Name> GetName();
|
|
uint32_t index() const { return index_; }
|
|
|
|
bool IsElement() const { return index_ != kMaxUInt32; }
|
|
|
|
bool IsFound() const { return state_ != NOT_FOUND; }
|
|
void Next();
|
|
void NotFound() {
|
|
has_property_ = false;
|
|
state_ = NOT_FOUND;
|
|
}
|
|
|
|
Heap* heap() const { return isolate_->heap(); }
|
|
Factory* factory() const { return isolate_->factory(); }
|
|
Handle<Object> GetReceiver() const { return receiver_; }
|
|
|
|
template <class T>
|
|
inline Handle<T> GetStoreTarget() const;
|
|
inline bool is_dictionary_holder() const;
|
|
inline Handle<Map> transition_map() const;
|
|
inline Handle<PropertyCell> transition_cell() const;
|
|
template <class T>
|
|
inline Handle<T> GetHolder() const;
|
|
|
|
bool HolderIsReceiver() const;
|
|
bool HolderIsReceiverOrHiddenPrototype() const;
|
|
|
|
bool check_prototype_chain() const {
|
|
return (configuration_ & kPrototypeChain) != 0;
|
|
}
|
|
|
|
/* ACCESS_CHECK */
|
|
bool HasAccess() const;
|
|
|
|
/* PROPERTY */
|
|
inline bool ExtendingNonExtensible(Handle<JSReceiver> receiver);
|
|
void PrepareForDataProperty(Handle<Object> value);
|
|
void PrepareTransitionToDataProperty(Handle<JSReceiver> receiver,
|
|
Handle<Object> value,
|
|
PropertyAttributes attributes,
|
|
StoreOrigin store_origin);
|
|
inline bool IsCacheableTransition();
|
|
void ApplyTransitionToDataProperty(Handle<JSReceiver> receiver);
|
|
void ReconfigureDataProperty(Handle<Object> value,
|
|
PropertyAttributes attributes);
|
|
void Delete();
|
|
void TransitionToAccessorProperty(Handle<Object> getter,
|
|
Handle<Object> setter,
|
|
PropertyAttributes attributes);
|
|
void TransitionToAccessorPair(Handle<Object> pair,
|
|
PropertyAttributes attributes);
|
|
PropertyDetails property_details() const {
|
|
DCHECK(has_property_);
|
|
return property_details_;
|
|
}
|
|
PropertyAttributes property_attributes() const {
|
|
return property_details().attributes();
|
|
}
|
|
bool IsConfigurable() const { return property_details().IsConfigurable(); }
|
|
bool IsReadOnly() const { return property_details().IsReadOnly(); }
|
|
bool IsEnumerable() const { return property_details().IsEnumerable(); }
|
|
Representation representation() const {
|
|
return property_details().representation();
|
|
}
|
|
PropertyLocation location() const { return property_details().location(); }
|
|
PropertyConstness constness() const { return property_details().constness(); }
|
|
Handle<Map> GetFieldOwnerMap() const;
|
|
FieldIndex GetFieldIndex() const;
|
|
Handle<FieldType> GetFieldType() const;
|
|
int GetFieldDescriptorIndex() const;
|
|
int GetAccessorIndex() const;
|
|
int GetConstantIndex() const;
|
|
Handle<PropertyCell> GetPropertyCell() const;
|
|
Handle<Object> GetAccessors() const;
|
|
inline Handle<InterceptorInfo> GetInterceptor() const;
|
|
Handle<InterceptorInfo> GetInterceptorForFailedAccessCheck() const;
|
|
Handle<Object> GetDataValue() const;
|
|
void WriteDataValue(Handle<Object> value, bool initializing_store);
|
|
inline void UpdateProtector();
|
|
|
|
// Lookup a 'cached' private property for an accessor.
|
|
// If not found returns false and leaves the LookupIterator unmodified.
|
|
bool TryLookupCachedProperty();
|
|
bool LookupCachedProperty();
|
|
|
|
private:
|
|
// For |ForTransitionHandler|.
|
|
LookupIterator(Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
|
|
Handle<Map> transition_map, PropertyDetails details,
|
|
bool has_property);
|
|
|
|
void InternalUpdateProtector();
|
|
|
|
enum class InterceptorState {
|
|
kUninitialized,
|
|
kSkipNonMasking,
|
|
kProcessNonMasking
|
|
};
|
|
|
|
Handle<Map> GetReceiverMap() const;
|
|
|
|
V8_WARN_UNUSED_RESULT inline JSReceiver NextHolder(Map map);
|
|
|
|
template <bool is_element>
|
|
V8_EXPORT_PRIVATE void Start();
|
|
template <bool is_element>
|
|
void NextInternal(Map map, JSReceiver holder);
|
|
template <bool is_element>
|
|
inline State LookupInHolder(Map map, JSReceiver holder) {
|
|
return map->IsSpecialReceiverMap()
|
|
? LookupInSpecialHolder<is_element>(map, holder)
|
|
: LookupInRegularHolder<is_element>(map, holder);
|
|
}
|
|
template <bool is_element>
|
|
State LookupInRegularHolder(Map map, JSReceiver holder);
|
|
template <bool is_element>
|
|
State LookupInSpecialHolder(Map map, JSReceiver holder);
|
|
template <bool is_element>
|
|
void RestartLookupForNonMaskingInterceptors() {
|
|
RestartInternal<is_element>(InterceptorState::kProcessNonMasking);
|
|
}
|
|
template <bool is_element>
|
|
void RestartInternal(InterceptorState interceptor_state);
|
|
Handle<Object> FetchValue() const;
|
|
bool IsConstFieldValueEqualTo(Object value) const;
|
|
template <bool is_element>
|
|
void ReloadPropertyInformation();
|
|
|
|
template <bool is_element>
|
|
bool SkipInterceptor(JSObject holder);
|
|
template <bool is_element>
|
|
static inline InterceptorInfo GetInterceptor(JSObject holder);
|
|
|
|
bool check_interceptor() const {
|
|
return (configuration_ & kInterceptor) != 0;
|
|
}
|
|
inline int descriptor_number() const;
|
|
inline int dictionary_entry() const;
|
|
|
|
static inline Configuration ComputeConfiguration(
|
|
Configuration configuration, Handle<Name> name);
|
|
|
|
static Handle<JSReceiver> GetRootForNonJSReceiver(
|
|
Isolate* isolate, Handle<Object> receiver, uint32_t index = kMaxUInt32);
|
|
static inline Handle<JSReceiver> GetRoot(Isolate* isolate,
|
|
Handle<Object> receiver,
|
|
uint32_t index = kMaxUInt32);
|
|
|
|
State NotFound(JSReceiver const holder) const;
|
|
|
|
// If configuration_ becomes mutable, update
|
|
// HolderIsReceiverOrHiddenPrototype.
|
|
const Configuration configuration_;
|
|
State state_;
|
|
bool has_property_;
|
|
InterceptorState interceptor_state_;
|
|
PropertyDetails property_details_;
|
|
Isolate* const isolate_;
|
|
Handle<Name> name_;
|
|
Handle<Object> transition_;
|
|
const Handle<Object> receiver_;
|
|
Handle<JSReceiver> holder_;
|
|
const Handle<JSReceiver> initial_holder_;
|
|
const uint32_t index_;
|
|
uint32_t number_;
|
|
};
|
|
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_LOOKUP_H_
|