Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Side by Side Diff: src/prototype-iterator.h

Issue 348313002: Introduce a PrototypeIterator template and use it all over the place (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebase Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects-printer.cc ('k') | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #ifndef V8_PROTOTYPE_ITERATOR_H_
6 #define V8_PROTOTYPE_ITERATOR_H_
7
8 // This file defines an iterator that should be used to iterate over an
9 // object's prototype chain. The iterator template can be specialized to
10 // handle all common variations of iterating over the prototype chain,
11 // and at the same time makes sure that security interceptors are honored.
12 //
13 // The iterator can also be used to look up just the prototype.
14 //
15 // The iterator should always be used unless it is safe to skip the security
16 // interceptors, e.g., when all objects on the prototype chain are from the
17 // same context.
18
19 #include "src/v8.h"
20
21 #include "src/base/macros.h"
22
23 namespace v8 {
24 namespace internal {
25
26 /**
27 * Whether to walk the prototype chain based on the map, or by using a switch
28 * over the type. The latter will also work for non-JSReceiver prototypes but
29 * is more expensive.
30 */
31 enum WalkType { MAP_BASED_WALK, TYPE_BASED_WALK };
32
33
34 /**
35 * Where to stop the chain walk: either at the null value, a given object, or
36 * the first non-hidden prototype.
37 */
38 enum WhereToEnd { END_AT_NULL_VALUE, END_AT_GIVEN_OBJECT, END_AT_NON_HIDDEN };
39
40
41 /**
42 * How the iterator stores the object.
43 */
44 enum StorageType { STORE_AS_POINTER, STORE_AS_HANDLE };
45
46
47 template <int storage_type>
48 struct ObjectStorageType;
49
50
51 template <>
52 struct ObjectStorageType<STORE_AS_POINTER> {
53 typedef Object* storage_type;
54 };
55
56
57 template <>
58 struct ObjectStorageType<STORE_AS_HANDLE> {
59 typedef Handle<Object> storage_type;
60 };
61
62 template <int store_as, int type_of_walk, int where_to_end>
63 class PrototypeIterator;
64
65
66 template <int store_as, int where_to_end>
67 class PrototypeIterator<store_as, TYPE_BASED_WALK, where_to_end> {
68 public:
69 typedef typename ObjectStorageType<store_as>::storage_type storage_type;
70
71 PrototypeIterator(Isolate* isolate, storage_type object)
72 : isolate_(isolate), object_(object) {}
73 ~PrototypeIterator() {}
74
75 bool IsAtEnd();
76 PrototypeIterator& Advance();
77
78 storage_type GetCurrent() const { return object_; }
79
80 private:
81 Isolate* isolate_;
82 storage_type object_;
83
84 DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
85 };
86
87
88 template <>
89 V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
90 END_AT_NULL_VALUE>::IsAtEnd() {
91 return object_->IsNull();
92 }
93
94
95 template <>
96 V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
97 END_AT_NULL_VALUE>::IsAtEnd() {
98 return object_->IsNull();
99 }
100
101
102 template <>
103 V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
104 END_AT_NON_HIDDEN>::IsAtEnd() {
105 return !object_->IsJSReceiver() ||
106 !JSReceiver::cast(object_)->map()->is_hidden_prototype();
107 }
108
109
110 template <>
111 V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
112 END_AT_NON_HIDDEN>::IsAtEnd() {
113 return !object_->IsJSReceiver() ||
114 !Handle<JSReceiver>::cast(object_)->map()->is_hidden_prototype();
115 }
116
117
118 template <>
119 V8_INLINE
120 PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK, END_AT_NULL_VALUE>&
121 PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
122 END_AT_NULL_VALUE>::Advance() {
123 object_ = object_->GetPrototype(isolate_);
124 return *this;
125 }
126
127
128 template <>
129 V8_INLINE
130 PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NULL_VALUE>&
131 PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
132 END_AT_NULL_VALUE>::Advance() {
133 object_ = Object::GetPrototype(isolate_, object_);
134 return *this;
135 }
136
137
138 template <>
139 V8_INLINE
140 PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK, END_AT_NON_HIDDEN>&
141 PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
142 END_AT_NON_HIDDEN>::Advance() {
143 object_ = object_->GetPrototype(isolate_);
144 return *this;
145 }
146
147
148 template <>
149 V8_INLINE
150 PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NON_HIDDEN>&
151 PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
152 END_AT_NON_HIDDEN>::Advance() {
153 object_ = Object::GetPrototype(isolate_, object_);
154 return *this;
155 }
156
157
158 template <>
159 class PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_GIVEN_OBJECT> {
160 public:
161 PrototypeIterator(Isolate* isolate, Handle<Object> object, Handle<Object> end)
162 : isolate_(isolate), object_(object), end_(end) {}
163 ~PrototypeIterator() {}
164
165 bool IsAtEnd() { return object_->IsNull() || *object_ == *end_; }
166
167 PrototypeIterator& Advance() {
168 object_ = Object::GetPrototype(isolate_, object_);
169 return *this;
170 }
171
172 Handle<Object> GetCurrent() const { return object_; }
173
174 private:
175 Isolate* isolate_;
176 Handle<Object> object_;
177 Handle<Object> end_;
178
179 DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
180 };
181
182
183 template <int store_as, int where_to_end>
184 class PrototypeIterator<store_as, MAP_BASED_WALK, where_to_end> {
185 public:
186 typedef typename ObjectStorageType<store_as>::storage_type storage_type;
187
188 explicit PrototypeIterator(storage_type receiver) : object_(receiver) {}
189 ~PrototypeIterator() {}
190
191 bool IsAtEnd();
192
193 PrototypeIterator& Advance();
194
195 storage_type GetCurrent() const { return object_; }
196
197 private:
198 storage_type object_;
199
200 DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
201 };
202
203
204 template <>
205 V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
206 END_AT_NULL_VALUE>::IsAtEnd() {
207 return object_->IsNull();
208 }
209
210
211 template <>
212 V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
213 END_AT_NULL_VALUE>::IsAtEnd() {
214 return object_->IsNull();
215 }
216
217
218 template <>
219 V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
220 END_AT_NON_HIDDEN>::IsAtEnd() {
221 return !object_->IsJSReceiver() ||
222 !JSReceiver::cast(object_)->map()->is_hidden_prototype();
223 }
224
225
226 template <>
227 V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
228 END_AT_NON_HIDDEN>::IsAtEnd() {
229 return !object_->IsJSReceiver() ||
230 !Handle<JSReceiver>::cast(object_)->map()->is_hidden_prototype();
231 }
232
233
234 template <>
235 V8_INLINE
236 PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK, END_AT_NULL_VALUE>&
237 PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
238 END_AT_NULL_VALUE>::Advance() {
239 object_ = JSReceiver::cast(object_)->GetPrototype();
240 return *this;
241 }
242
243
244 template <>
245 V8_INLINE PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK, END_AT_NULL_VALUE>&
246 PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
247 END_AT_NULL_VALUE>::Advance() {
248 object_ = handle(Handle<JSReceiver>::cast(object_)->GetPrototype(),
249 Handle<JSReceiver>::cast(object_)->GetIsolate());
250 return *this;
251 }
252
253
254 template <>
255 V8_INLINE
256 PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK, END_AT_NON_HIDDEN>&
257 PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
258 END_AT_NON_HIDDEN>::Advance() {
259 object_ = JSReceiver::cast(object_)->GetPrototype();
260 return *this;
261 }
262
263
264 template <>
265 V8_INLINE PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK, END_AT_NON_HIDDEN>&
266 PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
267 END_AT_NON_HIDDEN>::Advance() {
268 object_ = handle(Handle<JSReceiver>::cast(object_)->GetPrototype(),
269 Handle<JSReceiver>::cast(object_)->GetIsolate());
270 return *this;
271 }
272
273
274 #define SAFE_GET_PROTOTYPE(isolate, object) \
275 v8::internal::PrototypeIterator< \
276 v8::internal::STORE_AS_POINTER, v8::internal::TYPE_BASED_WALK, \
277 v8::internal::END_AT_NULL_VALUE>(isolate, object) \
278 .Advance() \
279 .GetCurrent()
280
281
282 #define SAFE_GET_PROTOTYPE_FAST(receiver) \
283 v8::internal::PrototypeIterator<v8::internal::STORE_AS_POINTER, \
284 v8::internal::MAP_BASED_WALK, \
285 v8::internal::END_AT_NULL_VALUE>(receiver) \
286 .Advance() \
287 .GetCurrent()
288 }
289 } // namespace v8::internal
290
291 #endif // V8_PROTOTYPE_ITERATOR_H_
OLDNEW
« no previous file with comments | « src/objects-printer.cc ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698