OLD | NEW |
---|---|
(Empty) | |
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 #include "src/v8.h" | |
6 | |
7 #include "src/bootstrapper.h" | |
8 #include "src/lookup.h" | |
9 | |
10 namespace v8 { | |
11 namespace internal { | |
12 | |
13 | |
14 void LookupIterator::Next() { | |
15 has_property_ = false; | |
16 do { | |
17 LookupInHolder(); | |
18 } while (!IsFound() && NextHolder()); | |
19 } | |
20 | |
21 | |
22 Handle<JSReceiver> LookupIterator::GetOrigin() const { | |
23 Handle<Object> receiver = GetReceiver(); | |
24 if (receiver->IsJSReceiver()) return Handle<JSReceiver>::cast(receiver); | |
25 Context* native_context = isolate_->context()->native_context(); | |
26 JSFunction* function; | |
27 if (receiver->IsNumber()) { | |
28 function = native_context->number_function(); | |
29 } else if (receiver->IsString()) { | |
30 function = native_context->string_function(); | |
31 } else if (receiver->IsSymbol()) { | |
32 function = native_context->symbol_function(); | |
33 } else if (receiver->IsBoolean()) { | |
34 function = native_context->boolean_function(); | |
35 } else { | |
36 UNREACHABLE(); | |
37 function = NULL; | |
38 } | |
39 return handle(JSReceiver::cast(function->instance_prototype())); | |
40 } | |
41 | |
42 | |
43 Handle<Map> LookupIterator::GetReceiverMap() const { | |
44 Handle<Object> receiver = GetReceiver(); | |
45 if (receiver->IsNumber()) return isolate_->factory()->heap_number_map(); | |
46 return handle(Handle<HeapObject>::cast(receiver)->map()); | |
47 } | |
48 | |
49 | |
50 bool LookupIterator::NextHolder() { | |
51 if (holder_map_->prototype()->IsNull()) return false; | |
52 | |
53 Handle<JSReceiver> next(JSReceiver::cast(holder_map_->prototype())); | |
54 | |
55 if (!check_derived() && | |
56 // TODO(verwaest): Check if this is actually necessary currently. If it | |
57 // is, this should be handled by setting is_hidden_prototype on the | |
58 // global object behind the proxy. | |
59 !holder_map_->IsJSGlobalProxyMap() && | |
60 !next->map()->is_hidden_prototype()) { | |
61 return false; | |
62 } | |
63 | |
64 holder_map_ = handle(next->map()); | |
65 maybe_holder_ = next; | |
66 return true; | |
67 } | |
68 | |
69 | |
70 void LookupIterator::LookupInHolder() { | |
71 State old_state = state_; | |
72 state_ = NOT_FOUND; | |
rossberg
2014/06/11 15:37:00
Might be clearer to not pre-default this. There ar
Toon Verwaest
2014/06/11 17:32:18
Done.
| |
73 switch (old_state) { | |
74 case NOT_FOUND: | |
75 if (holder_map_->IsJSProxyMap()) { | |
76 state_ = JSPROXY; | |
77 return; | |
78 } | |
79 if (check_access_check() && holder_map_->is_access_check_needed()) { | |
80 state_ = ACCESS_CHECK; | |
81 return; | |
82 } | |
rossberg
2014/06/11 15:37:00
Put a fall-through comment here and below.
Toon Verwaest
2014/06/11 17:32:18
Done.
| |
83 case ACCESS_CHECK: | |
84 if (check_interceptor() && holder_map_->has_named_interceptor()) { | |
85 state_ = INTERCEPTOR; | |
86 return; | |
87 } | |
88 case INTERCEPTOR: | |
89 if (holder_map_->is_dictionary_map()) { | |
90 property_encoding_ = DICTIONARY; | |
91 } else { | |
92 DescriptorArray* descriptors = holder_map_->instance_descriptors(); | |
93 number_ = descriptors->SearchWithCache(*name_, *holder_map_); | |
94 if (number_ == DescriptorArray::kNotFound) return; | |
95 property_encoding_ = DESCRIPTOR; | |
96 } | |
97 state_ = PROPERTY; | |
98 case PROPERTY: | |
99 return; | |
100 case JSPROXY: | |
101 UNREACHABLE(); | |
102 } | |
103 } | |
104 | |
105 | |
106 bool LookupIterator::IsBootstrapping() const { | |
107 return isolate_->bootstrapper()->IsActive(); | |
108 } | |
109 | |
110 | |
111 bool LookupIterator::HasAccess(v8::AccessType access_type) const { | |
112 ASSERT_EQ(ACCESS_CHECK, state_); | |
113 ASSERT(is_guaranteed_to_have_holder()); | |
114 return isolate_->MayNamedAccess(GetHolder(), name_, access_type); | |
115 } | |
116 | |
117 | |
118 bool LookupIterator::HasProperty() { | |
119 ASSERT_EQ(PROPERTY, state_); | |
120 ASSERT(is_guaranteed_to_have_holder()); | |
121 | |
122 if (property_encoding_ == DICTIONARY) { | |
123 Handle<JSObject> holder = GetHolder(); | |
124 number_ = holder->property_dictionary()->FindEntry(name_); | |
125 if (number_ == NameDictionary::kNotFound) return false; | |
126 | |
127 property_details_ = GetHolder()->property_dictionary()->DetailsAt(number_); | |
128 // Holes in dictionary cells are absent values unless marked as read-only. | |
129 if (holder->IsGlobalObject() && | |
130 (property_details_.IsDeleted() || | |
131 (!property_details_.IsReadOnly() && FetchValue()->IsTheHole()))) { | |
132 return false; | |
133 } | |
134 } else { | |
135 property_details_ = holder_map_->instance_descriptors()->GetDetails( | |
136 number_); | |
137 } | |
138 | |
139 switch (property_details_.type()) { | |
140 case v8::internal::FIELD: | |
141 case v8::internal::NORMAL: | |
142 case v8::internal::CONSTANT: | |
143 property_type_ = DATA; | |
144 break; | |
145 case v8::internal::CALLBACKS: | |
146 property_type_ = ACCESSORS; | |
147 break; | |
148 case v8::internal::HANDLER: | |
149 case v8::internal::NONEXISTENT: | |
150 case v8::internal::INTERCEPTOR: | |
151 UNREACHABLE(); | |
152 } | |
153 | |
154 has_property_ = true; | |
155 return true; | |
156 } | |
157 | |
158 | |
159 Handle<Object> LookupIterator::FetchValue() const { | |
160 Object* result = NULL; | |
161 switch (property_encoding_) { | |
162 case DICTIONARY: | |
163 result = GetHolder()->property_dictionary()->ValueAt(number_); | |
164 if (GetHolder()->IsGlobalObject()) { | |
165 result = PropertyCell::cast(result)->value(); | |
166 } | |
167 break; | |
168 case DESCRIPTOR: | |
169 if (property_details_.type() == v8::internal::FIELD) { | |
170 FieldIndex field_index = FieldIndex::ForDescriptor( | |
171 *holder_map_, number_); | |
172 return JSObject::FastPropertyAt( | |
173 GetHolder(), property_details_.representation(), field_index); | |
174 } | |
175 result = holder_map_->instance_descriptors()->GetValue(number_); | |
176 } | |
177 return handle(result, isolate_); | |
178 } | |
179 | |
180 | |
181 Handle<Object> LookupIterator::GetAccessors() const { | |
182 ASSERT(has_property_); | |
183 ASSERT_EQ(ACCESSORS, property_type_); | |
184 return FetchValue(); | |
185 } | |
186 | |
187 | |
188 Handle<Object> LookupIterator::GetDataValue() const { | |
189 ASSERT(has_property_); | |
190 ASSERT_EQ(DATA, property_type_); | |
191 Handle<Object> value = FetchValue(); | |
192 if (value->IsTheHole()) { | |
193 ASSERT_EQ(DICTIONARY, property_encoding_); | |
194 ASSERT(GetHolder()->IsGlobalObject()); | |
195 ASSERT(property_details_.IsReadOnly()); | |
196 return factory()->undefined_value(); | |
197 } | |
198 return value; | |
199 } | |
200 | |
201 | |
202 } } // namespace v8::internal | |
OLD | NEW |