1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_LOOKUP_INL_H_
6#define V8_LOOKUP_INL_H_
7
8#include "src/lookup.h"
9
10#include "src/handles-inl.h"
11#include "src/heap/factory-inl.h"
12#include "src/objects-inl.h"
13#include "src/objects/api-callbacks.h"
14#include "src/objects/name-inl.h"
15#include "src/objects/map-inl.h"
16
17namespace v8 {
18namespace internal {
19
20LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
21 Handle<Name> name, Configuration configuration)
22 : LookupIterator(isolate, receiver, name, GetRoot(isolate, receiver),
23 configuration) {}
24
25LookupIterator::LookupIterator(Handle<Object> receiver, Handle<Name> name,
26 Handle<JSReceiver> holder,
27 Configuration configuration)
28 : LookupIterator(holder->GetIsolate(), receiver, name, holder,
29 configuration) {}
30
31LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
32 Handle<Name> name, Handle<JSReceiver> holder,
33 Configuration configuration)
34 : configuration_(ComputeConfiguration(configuration, name)),
35 interceptor_state_(InterceptorState::kUninitialized),
36 property_details_(PropertyDetails::Empty()),
37 isolate_(isolate),
38 name_(isolate_->factory()->InternalizeName(name)),
39 receiver_(receiver),
40 initial_holder_(holder),
41 // kMaxUInt32 isn't a valid index.
42 index_(kMaxUInt32),
43 number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
44#ifdef DEBUG
45 uint32_t index; // Assert that the name is not an array index.
46 DCHECK(!name->AsArrayIndex(&index));
47#endif // DEBUG
48 Start<false>();
49}
50
51LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
52 uint32_t index, Configuration configuration)
53 : LookupIterator(isolate, receiver, index,
54 GetRoot(isolate, receiver, index), configuration) {}
55
56LookupIterator LookupIterator::PropertyOrElement(
57 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
58 Handle<JSReceiver> holder, Configuration configuration) {
59 uint32_t index;
60 if (name->AsArrayIndex(&index)) {
61 LookupIterator it =
62 LookupIterator(isolate, receiver, index, holder, configuration);
63 it.name_ = name;
64 return it;
65 }
66 return LookupIterator(receiver, name, holder, configuration);
67}
68
69LookupIterator LookupIterator::PropertyOrElement(
70 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
71 Configuration configuration) {
72 uint32_t index;
73 if (name->AsArrayIndex(&index)) {
74 LookupIterator it = LookupIterator(isolate, receiver, index, configuration);
75 it.name_ = name;
76 return it;
77 }
78 return LookupIterator(isolate, receiver, name, configuration);
79}
80
81Handle<Name> LookupIterator::GetName() {
82 if (name_.is_null()) {
83 DCHECK(IsElement());
84 name_ = factory()->Uint32ToString(index_);
85 }
86 return name_;
87}
88
89bool LookupIterator::is_dictionary_holder() const {
90 return !holder_->HasFastProperties();
91}
92
93Handle<Map> LookupIterator::transition_map() const {
94 DCHECK_EQ(TRANSITION, state_);
95 return Handle<Map>::cast(transition_);
96}
97
98Handle<PropertyCell> LookupIterator::transition_cell() const {
99 DCHECK_EQ(TRANSITION, state_);
100 return Handle<PropertyCell>::cast(transition_);
101}
102
103template <class T>
104Handle<T> LookupIterator::GetHolder() const {
105 DCHECK(IsFound());
106 return Handle<T>::cast(holder_);
107}
108
109bool LookupIterator::ExtendingNonExtensible(Handle<JSReceiver> receiver) {
110 DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
111 return !receiver->map()->is_extensible() &&
112 (IsElement() || !name_->IsPrivate());
113}
114
115bool LookupIterator::IsCacheableTransition() {
116 DCHECK_EQ(TRANSITION, state_);
117 return transition_->IsPropertyCell() ||
118 (transition_map()->is_dictionary_map() &&
119 !GetStoreTarget<JSReceiver>()->HasFastProperties()) ||
120 transition_map()->GetBackPointer()->IsMap();
121}
122
123void LookupIterator::UpdateProtector() {
124 if (IsElement()) return;
125 // This list must be kept in sync with
126 // CodeStubAssembler::CheckForAssociatedProtector!
127 ReadOnlyRoots roots(heap());
128 if (*name_ == roots.is_concat_spreadable_symbol() ||
129 *name_ == roots.constructor_string() || *name_ == roots.next_string() ||
130 *name_ == roots.species_symbol() || *name_ == roots.iterator_symbol() ||
131 *name_ == roots.resolve_string() || *name_ == roots.then_string()) {
132 InternalUpdateProtector();
133 }
134}
135
136int LookupIterator::descriptor_number() const {
137 DCHECK(!IsElement());
138 DCHECK(has_property_);
139 DCHECK(holder_->HasFastProperties());
140 return number_;
141}
142
143int LookupIterator::dictionary_entry() const {
144 DCHECK(!IsElement());
145 DCHECK(has_property_);
146 DCHECK(!holder_->HasFastProperties());
147 return number_;
148}
149
150LookupIterator::Configuration LookupIterator::ComputeConfiguration(
151 Configuration configuration, Handle<Name> name) {
152 return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
153}
154
155Handle<JSReceiver> LookupIterator::GetRoot(Isolate* isolate,
156 Handle<Object> receiver,
157 uint32_t index) {
158 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
159 return GetRootForNonJSReceiver(isolate, receiver, index);
160}
161
162template <class T>
163Handle<T> LookupIterator::GetStoreTarget() const {
164 DCHECK(receiver_->IsJSReceiver());
165 if (receiver_->IsJSGlobalProxy()) {
166 Map map = JSGlobalProxy::cast(*receiver_)->map();
167 if (map->has_hidden_prototype()) {
168 return handle(JSGlobalObject::cast(map->prototype()), isolate_);
169 }
170 }
171 return Handle<T>::cast(receiver_);
172}
173
174template <bool is_element>
175InterceptorInfo LookupIterator::GetInterceptor(JSObject holder) {
176 return is_element ? holder->GetIndexedInterceptor()
177 : holder->GetNamedInterceptor();
178}
179
180inline Handle<InterceptorInfo> LookupIterator::GetInterceptor() const {
181 DCHECK_EQ(INTERCEPTOR, state_);
182 InterceptorInfo result =
183 IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
184 : GetInterceptor<false>(JSObject::cast(*holder_));
185 return handle(result, isolate_);
186}
187
188} // namespace internal
189} // namespace v8
190
191#endif // V8_LOOKUP_INL_H_
192