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
17 namespace v8 {
18 namespace internal {
19
LookupIterator(Handle<Object> receiver,Handle<Name> name,Handle<JSReceiver> holder,Configuration configuration)20 LookupIterator::LookupIterator(Handle<Object> receiver, Handle<Name> name,
21 Handle<JSReceiver> holder,
22 Configuration configuration)
23 : LookupIterator(holder->GetIsolate(), receiver, name, holder,
24 configuration) {}
25
LookupIterator(Isolate * isolate,Handle<Object> receiver,Handle<Name> name,Handle<JSReceiver> holder,Configuration configuration)26 LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
27 Handle<Name> name, Handle<JSReceiver> holder,
28 Configuration configuration)
29 : configuration_(ComputeConfiguration(configuration, name)),
30 interceptor_state_(InterceptorState::kUninitialized),
31 property_details_(PropertyDetails::Empty()),
32 isolate_(isolate),
33 name_(isolate_->factory()->InternalizeName(name)),
34 receiver_(receiver),
35 initial_holder_(holder),
36 // kMaxUInt32 isn't a valid index.
37 index_(kMaxUInt32),
38 number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
39 #ifdef DEBUG
40 uint32_t index; // Assert that the name is not an array index.
41 DCHECK(!name->AsArrayIndex(&index));
42 #endif // DEBUG
43 Start<false>();
44 }
45
PropertyOrElement(Isolate * isolate,Handle<Object> receiver,Handle<Name> name,Handle<JSReceiver> holder,Configuration configuration)46 LookupIterator LookupIterator::PropertyOrElement(
47 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
48 Handle<JSReceiver> holder, Configuration configuration) {
49 uint32_t index;
50 if (name->AsArrayIndex(&index)) {
51 LookupIterator it =
52 LookupIterator(isolate, receiver, index, holder, configuration);
53 it.name_ = name;
54 return it;
55 }
56 return LookupIterator(receiver, name, holder, configuration);
57 }
58
PropertyOrElement(Isolate * isolate,Handle<Object> receiver,Handle<Name> name,Configuration configuration)59 LookupIterator LookupIterator::PropertyOrElement(
60 Isolate* isolate, Handle<Object> receiver, Handle<Name> name,
61 Configuration configuration) {
62 uint32_t index;
63 if (name->AsArrayIndex(&index)) {
64 LookupIterator it = LookupIterator(isolate, receiver, index, configuration);
65 it.name_ = name;
66 return it;
67 }
68 return LookupIterator(isolate, receiver, name, configuration);
69 }
70
GetName()71 Handle<Name> LookupIterator::GetName() {
72 if (name_.is_null()) {
73 DCHECK(IsElement());
74 name_ = factory()->Uint32ToString(index_);
75 }
76 return name_;
77 }
78
is_dictionary_holder()79 bool LookupIterator::is_dictionary_holder() const {
80 return !holder_->HasFastProperties();
81 }
82
ExtendingNonExtensible(Handle<JSReceiver> receiver)83 bool LookupIterator::ExtendingNonExtensible(Handle<JSReceiver> receiver) {
84 DCHECK(receiver.is_identical_to(GetStoreTarget<JSReceiver>()));
85 return !receiver->map()->is_extensible() &&
86 (IsElement() || !name_->IsPrivate());
87 }
88
IsCacheableTransition()89 bool LookupIterator::IsCacheableTransition() {
90 DCHECK_EQ(TRANSITION, state_);
91 return transition_->IsPropertyCell() ||
92 (transition_map()->is_dictionary_map() &&
93 !GetStoreTarget<JSReceiver>()->HasFastProperties()) ||
94 transition_map()->GetBackPointer()->IsMap();
95 }
96
UpdateProtector()97 void LookupIterator::UpdateProtector() {
98 if (IsElement()) return;
99 // This list must be kept in sync with
100 // CodeStubAssembler::CheckForAssociatedProtector!
101 ReadOnlyRoots roots(heap());
102 if (*name_ == roots.is_concat_spreadable_symbol() ||
103 *name_ == roots.constructor_string() || *name_ == roots.next_string() ||
104 *name_ == roots.species_symbol() || *name_ == roots.iterator_symbol() ||
105 *name_ == roots.resolve_string() || *name_ == roots.then_string()) {
106 InternalUpdateProtector();
107 }
108 }
109
ComputeConfiguration(Configuration configuration,Handle<Name> name)110 LookupIterator::Configuration LookupIterator::ComputeConfiguration(
111 Configuration configuration, Handle<Name> name) {
112 return name->IsPrivate() ? OWN_SKIP_INTERCEPTOR : configuration;
113 }
114
GetRoot(Isolate * isolate,Handle<Object> receiver,uint32_t index)115 Handle<JSReceiver> LookupIterator::GetRoot(Isolate* isolate,
116 Handle<Object> receiver,
117 uint32_t index) {
118 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver);
119 return GetRootForNonJSReceiver(isolate, receiver, index);
120 }
121
122 template <class T>
GetStoreTarget()123 Handle<T> LookupIterator::GetStoreTarget() const {
124 DCHECK(receiver_->IsJSReceiver());
125 if (receiver_->IsJSGlobalProxy()) {
126 Map* map = JSGlobalProxy::cast(*receiver_)->map();
127 if (map->has_hidden_prototype()) {
128 return handle(JSGlobalObject::cast(map->prototype()), isolate_);
129 }
130 }
131 return Handle<T>::cast(receiver_);
132 }
GetInterceptor()133 inline Handle<InterceptorInfo> LookupIterator::GetInterceptor() const {
134 DCHECK_EQ(INTERCEPTOR, state_);
135 InterceptorInfo* result =
136 IsElement() ? GetInterceptor<true>(JSObject::cast(*holder_))
137 : GetInterceptor<false>(JSObject::cast(*holder_));
138 return handle(result, isolate_);
139 }
140
141 } // namespace internal
142 } // namespace v8
143
144 #endif // V8_LOOKUP_INL_H_
145