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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/objects-printer.cc ('k') | src/runtime.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/prototype-iterator.h
diff --git a/src/prototype-iterator.h b/src/prototype-iterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf56947a6b6c395b3cb755b1d0c9dab81467636a
--- /dev/null
+++ b/src/prototype-iterator.h
@@ -0,0 +1,291 @@
+// 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_PROTOTYPE_ITERATOR_H_
+#define V8_PROTOTYPE_ITERATOR_H_
+
+// This file defines an iterator that should be used to iterate over an
+// object's prototype chain. The iterator template can be specialized to
+// handle all common variations of iterating over the prototype chain,
+// and at the same time makes sure that security interceptors are honored.
+//
+// The iterator can also be used to look up just the prototype.
+//
+// The iterator should always be used unless it is safe to skip the security
+// interceptors, e.g., when all objects on the prototype chain are from the
+// same context.
+
+#include "src/v8.h"
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace internal {
+
+/**
+ * Whether to walk the prototype chain based on the map, or by using a switch
+ * over the type. The latter will also work for non-JSReceiver prototypes but
+ * is more expensive.
+ */
+enum WalkType { MAP_BASED_WALK, TYPE_BASED_WALK };
+
+
+/**
+ * Where to stop the chain walk: either at the null value, a given object, or
+ * the first non-hidden prototype.
+ */
+enum WhereToEnd { END_AT_NULL_VALUE, END_AT_GIVEN_OBJECT, END_AT_NON_HIDDEN };
+
+
+/**
+ * How the iterator stores the object.
+ */
+enum StorageType { STORE_AS_POINTER, STORE_AS_HANDLE };
+
+
+template <int storage_type>
+struct ObjectStorageType;
+
+
+template <>
+struct ObjectStorageType<STORE_AS_POINTER> {
+ typedef Object* storage_type;
+};
+
+
+template <>
+struct ObjectStorageType<STORE_AS_HANDLE> {
+ typedef Handle<Object> storage_type;
+};
+
+template <int store_as, int type_of_walk, int where_to_end>
+class PrototypeIterator;
+
+
+template <int store_as, int where_to_end>
+class PrototypeIterator<store_as, TYPE_BASED_WALK, where_to_end> {
+ public:
+ typedef typename ObjectStorageType<store_as>::storage_type storage_type;
+
+ PrototypeIterator(Isolate* isolate, storage_type object)
+ : isolate_(isolate), object_(object) {}
+ ~PrototypeIterator() {}
+
+ bool IsAtEnd();
+ PrototypeIterator& Advance();
+
+ storage_type GetCurrent() const { return object_; }
+
+ private:
+ Isolate* isolate_;
+ storage_type object_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
+};
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
+ END_AT_NULL_VALUE>::IsAtEnd() {
+ return object_->IsNull();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
+ END_AT_NULL_VALUE>::IsAtEnd() {
+ return object_->IsNull();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
+ END_AT_NON_HIDDEN>::IsAtEnd() {
+ return !object_->IsJSReceiver() ||
+ !JSReceiver::cast(object_)->map()->is_hidden_prototype();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
+ END_AT_NON_HIDDEN>::IsAtEnd() {
+ return !object_->IsJSReceiver() ||
+ !Handle<JSReceiver>::cast(object_)->map()->is_hidden_prototype();
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK, END_AT_NULL_VALUE>&
+PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
+ END_AT_NULL_VALUE>::Advance() {
+ object_ = object_->GetPrototype(isolate_);
+ return *this;
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NULL_VALUE>&
+PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
+ END_AT_NULL_VALUE>::Advance() {
+ object_ = Object::GetPrototype(isolate_, object_);
+ return *this;
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK, END_AT_NON_HIDDEN>&
+PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
+ END_AT_NON_HIDDEN>::Advance() {
+ object_ = object_->GetPrototype(isolate_);
+ return *this;
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NON_HIDDEN>&
+PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK,
+ END_AT_NON_HIDDEN>::Advance() {
+ object_ = Object::GetPrototype(isolate_, object_);
+ return *this;
+}
+
+
+template <>
+class PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_GIVEN_OBJECT> {
+ public:
+ PrototypeIterator(Isolate* isolate, Handle<Object> object, Handle<Object> end)
+ : isolate_(isolate), object_(object), end_(end) {}
+ ~PrototypeIterator() {}
+
+ bool IsAtEnd() { return object_->IsNull() || *object_ == *end_; }
+
+ PrototypeIterator& Advance() {
+ object_ = Object::GetPrototype(isolate_, object_);
+ return *this;
+ }
+
+ Handle<Object> GetCurrent() const { return object_; }
+
+ private:
+ Isolate* isolate_;
+ Handle<Object> object_;
+ Handle<Object> end_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
+};
+
+
+template <int store_as, int where_to_end>
+class PrototypeIterator<store_as, MAP_BASED_WALK, where_to_end> {
+ public:
+ typedef typename ObjectStorageType<store_as>::storage_type storage_type;
+
+ explicit PrototypeIterator(storage_type receiver) : object_(receiver) {}
+ ~PrototypeIterator() {}
+
+ bool IsAtEnd();
+
+ PrototypeIterator& Advance();
+
+ storage_type GetCurrent() const { return object_; }
+
+ private:
+ storage_type object_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
+};
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
+ END_AT_NULL_VALUE>::IsAtEnd() {
+ return object_->IsNull();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
+ END_AT_NULL_VALUE>::IsAtEnd() {
+ return object_->IsNull();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
+ END_AT_NON_HIDDEN>::IsAtEnd() {
+ return !object_->IsJSReceiver() ||
+ !JSReceiver::cast(object_)->map()->is_hidden_prototype();
+}
+
+
+template <>
+V8_INLINE bool PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
+ END_AT_NON_HIDDEN>::IsAtEnd() {
+ return !object_->IsJSReceiver() ||
+ !Handle<JSReceiver>::cast(object_)->map()->is_hidden_prototype();
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK, END_AT_NULL_VALUE>&
+PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
+ END_AT_NULL_VALUE>::Advance() {
+ object_ = JSReceiver::cast(object_)->GetPrototype();
+ return *this;
+}
+
+
+template <>
+V8_INLINE PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK, END_AT_NULL_VALUE>&
+PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
+ END_AT_NULL_VALUE>::Advance() {
+ object_ = handle(Handle<JSReceiver>::cast(object_)->GetPrototype(),
+ Handle<JSReceiver>::cast(object_)->GetIsolate());
+ return *this;
+}
+
+
+template <>
+V8_INLINE
+PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK, END_AT_NON_HIDDEN>&
+PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK,
+ END_AT_NON_HIDDEN>::Advance() {
+ object_ = JSReceiver::cast(object_)->GetPrototype();
+ return *this;
+}
+
+
+template <>
+V8_INLINE PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK, END_AT_NON_HIDDEN>&
+PrototypeIterator<STORE_AS_HANDLE, MAP_BASED_WALK,
+ END_AT_NON_HIDDEN>::Advance() {
+ object_ = handle(Handle<JSReceiver>::cast(object_)->GetPrototype(),
+ Handle<JSReceiver>::cast(object_)->GetIsolate());
+ return *this;
+}
+
+
+#define SAFE_GET_PROTOTYPE(isolate, object) \
+ v8::internal::PrototypeIterator< \
+ v8::internal::STORE_AS_POINTER, v8::internal::TYPE_BASED_WALK, \
+ v8::internal::END_AT_NULL_VALUE>(isolate, object) \
+ .Advance() \
+ .GetCurrent()
+
+
+#define SAFE_GET_PROTOTYPE_FAST(receiver) \
+ v8::internal::PrototypeIterator<v8::internal::STORE_AS_POINTER, \
+ v8::internal::MAP_BASED_WALK, \
+ v8::internal::END_AT_NULL_VALUE>(receiver) \
+ .Advance() \
+ .GetCurrent()
+}
+} // namespace v8::internal
+
+#endif // V8_PROTOTYPE_ITERATOR_H_
« 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