blob: abe865f69c9db16f654afb91fe61186966c88009 [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_INL_H_
#define V8_LOOKUP_INL_H_
#include "src/lookup.h"
#include "src/handles-inl.h"
#include "src/heap/factory-inl.h"
#include "src/objects-inl.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/name-inl.h"
#include "src/objects/map-inl.h"
namespace v8 {
namespace internal {
LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
Handle<Name> name, Configuration configuration)
: LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
configuration) {}
LookupIterator::LookupIterator(Handle<Object> receiver, Handle<Name> name,
Handle<JSReceiver> holder,
Configuration configuration)
: LookupIterator(holder->GetIsolate(), receiver, name, holder,
configuration) {}
LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
Handle<Name> name, Handle<JSReceiver> holder,
Configuration configuration)
: configuration_(ComputeConfiguration(configuration, name)),
interceptor_state_(InterceptorState::kUninitialized),
property_details_(PropertyDetails::Empty()),
isolate_(isolate),
name_(isolate_->factory()->InternalizeName(name)),
receiver_(receiver),
initial_holder_(holder),
// kMaxUInt32 isn't a valid index.
index_(kMaxUInt32),
number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
#ifdef DEBUG
uint32_t index; // Assert that the name is not an array index.
DCHECK(!name->AsArrayIndex(&index));
#endif // DEBUG
Start<false>();
}
LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
uint32_t index, Configuration configuration)
: LookupIterator(isolate, receiver, index,
GetRoot(isolate, receiver, index), configuration) {}
LookupIterator LookupIterator::PropertyOrElement(
Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
Handle<JSReceiver> holder, Configuration configuration) {
uint32_t index;
if (name->AsArrayIndex(&index)) {
LookupIterator it =
LookupIterator(isolate, receiver, index, holder, configuration);
it.name_ = name;
return it;
}
return LookupIterator(receiver, name, holder, configuration);
}
LookupIterator LookupIterator::PropertyOrElement(
Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
Configuration configuration) {
uint32_t index;
if (name->AsArrayIndex(&index)) {
LookupIterator it = LookupIterator(isolate, receiver, index, configuration);
it.name_ = name;
return it;
}
return LookupIterator(isolate, receiver, name, configuration);
}
Handle<Name> LookupIterator::GetName() {
if (name_.is_null()) {
DCHECK(IsElement());
name_ = factory()->Uint32ToString(index_);
}
return name_;
}
bool LookupIterator::is_dictionary_holder() const {
return !holder_->HasFastProperties();
}
Handle<Map> LookupIterator::transition_map() const {
DCHECK_EQ(TRANSITION, state_);
return Handle<Map>::cast(transition_);
}
Handle<PropertyCell> LookupIterator::transition_cell() const {
DCHECK_EQ(TRANSITION, state_);
return Handle<PropertyCell>::cast(transition_);
}
template <class T>
Handle<T> LookupIterator::GetHolder() const {
DCHECK(IsFound());
return Handle<T>::cast(holder_);
}
bool LookupIterator::ExtendingNonExtensible(Handle<JSReceiver> receiver) {
DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
return !receiver->map()->is_extensible() &&
(IsElement() || !name_->IsPrivate());
}
bool LookupIterator::IsCacheableTransition() {
DCHECK_EQ(TRANSITION, state_);
return transition_->IsPropertyCell() ||
(transition_map()->is_dictionary_map() &&
!GetStoreTarget<JSReceiver>()->HasFastProperties()) ||
transition_map()->GetBackPointer()->IsMap();
}
void LookupIterator::UpdateProtector() {
if (IsElement()) return;
// This list must be kept in sync with
// CodeStubAssembler::CheckForAssociatedProtector!
ReadOnlyRoots roots(heap());
if (*name_ == roots.is_concat_spreadable_symbol() ||
*name_ == roots.constructor_string() || *name_ == roots.next_string() ||
*name_ == roots.species_symbol() || *name_ == roots.iterator_symbol() ||
*name_ == roots.resolve_string() || *name_ == roots.then_string()) {
InternalUpdateProtector();
}
}
int LookupIterator::descriptor_number() const {
DCHECK(!IsElement());
DCHECK(has_property_);
DCHECK(holder_->HasFastProperties());
return number_;
}
int LookupIterator::dictionary_entry() const {
DCHECK(!IsElement());
DCHECK(has_property_);
DCHECK(!holder_->HasFastProperties());
return number_;
}
LookupIterator::Configuration LookupIterator::ComputeConfiguration(
Configuration configuration, Handle<Name> name) {
return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
}
Handle<JSReceiver> LookupIterator::GetRoot(Isolate* isolate,
Handle<Object> receiver,
uint32_t index) {
if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
return GetRootForNonJSReceiver(isolate, receiver, index);
}
template <class T>
Handle<T> LookupIterator::GetStoreTarget() const {
DCHECK(receiver_->IsJSReceiver());
if (receiver_->IsJSGlobalProxy()) {
Map map = JSGlobalProxy::cast(*receiver_)->map();
if (map->has_hidden_prototype()) {
return handle(JSGlobalObject::cast(map->prototype()), isolate_);
}
}
return Handle<T>::cast(receiver_);
}
template <bool is_element>
InterceptorInfo LookupIterator::GetInterceptor(JSObject holder) {
return is_element ? holder->GetIndexedInterceptor()
: holder->GetNamedInterceptor();
}
inline Handle<InterceptorInfo> LookupIterator::GetInterceptor() const {
DCHECK_EQ(INTERCEPTOR, state_);
InterceptorInfo result =
IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
: GetInterceptor<false>(JSObject::cast(*holder_));
return handle(result, isolate_);
}
} // namespace internal
} // namespace v8
#endif // V8_LOOKUP_INL_H_