ecdcae8492
CallbackInfo, InterceptorInfo, Tuple3 Bug: v8:3770 Change-Id: I47a380949c031ed9eba0e5a7d752669efc0af76c Reviewed-on: https://chromium-review.googlesource.com/c/1377771 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#58284}
192 lines
6.3 KiB
C++
192 lines
6.3 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_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_
|