// 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(Handle receiver, Handle name, Handle holder, Configuration configuration) : LookupIterator(holder->GetIsolate(), receiver, name, holder, configuration) {} LookupIterator::LookupIterator(Isolate* isolate, Handle receiver, Handle name, Handle 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(DescriptorArray::kNotFound)) { #ifdef DEBUG uint32_t index; // Assert that the name is not an array index. DCHECK(!name->AsArrayIndex(&index)); #endif // DEBUG Start(); } LookupIterator LookupIterator::PropertyOrElement( Isolate* isolate, Handle receiver, Handle name, Handle 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 receiver, Handle 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 LookupIterator::GetName() { if (name_.is_null()) { DCHECK(IsElement()); name_ = factory()->Uint32ToString(index_); } return name_; } bool LookupIterator::is_dictionary_holder() const { return !holder_->HasFastProperties(); } bool LookupIterator::ExtendingNonExtensible(Handle receiver) { DCHECK(receiver.is_identical_to(GetStoreTarget())); return !receiver->map()->is_extensible() && (IsElement() || !name_->IsPrivate()); } bool LookupIterator::IsCacheableTransition() { DCHECK_EQ(TRANSITION, state_); return transition_->IsPropertyCell() || (transition_map()->is_dictionary_map() && !GetStoreTarget()->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(); } } LookupIterator::Configuration LookupIterator::ComputeConfiguration( Configuration configuration, Handle name) { return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration; } Handle LookupIterator::GetRoot(Isolate* isolate, Handle receiver, uint32_t index) { if (receiver->IsJSReceiver()) return Handle::cast(receiver); return GetRootForNonJSReceiver(isolate, receiver, index); } template Handle 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::cast(receiver_); } inline Handle LookupIterator::GetInterceptor() const { DCHECK_EQ(INTERCEPTOR, state_); InterceptorInfo* result = IsElement() ? GetInterceptor(JSObject::cast(*holder_)) : GetInterceptor(JSObject::cast(*holder_)); return handle(result, isolate_); } } // namespace internal } // namespace v8 #endif // V8_LOOKUP_INL_H_