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 #ifndef V8_PROTOTYPE_H_ |
| 6 #define V8_PROTOTYPE_H_ |
| 7 |
| 8 #include "src/isolate.h" |
| 9 #include "src/objects.h" |
| 10 |
| 11 namespace v8 { |
| 12 namespace internal { |
| 13 |
| 14 /** |
| 15 * A class to uniformly access the prototype of any Object and walk its |
| 16 * prototype chain. |
| 17 * |
| 18 * The PrototypeIterator can either start at the prototype (default), or |
| 19 * include the receiver itself. If a PrototypeIterator is constructed for a |
| 20 * Map, it will always start at the prototype. |
| 21 * |
| 22 * The PrototypeIterator can either run to the null_value(), the first |
| 23 * non-hidden prototype, or a given object. |
| 24 */ |
| 25 class PrototypeIterator { |
| 26 public: |
| 27 enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE }; |
| 28 |
| 29 enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN }; |
| 30 |
| 31 PrototypeIterator(Isolate* isolate, Handle<Object> receiver, |
| 32 WhereToStart where_to_start = START_AT_PROTOTYPE) |
| 33 : did_jump_to_prototype_chain_(false), |
| 34 object_(NULL), |
| 35 handle_(receiver), |
| 36 isolate_(isolate) { |
| 37 CHECK(!handle_.is_null()); |
| 38 if (where_to_start == START_AT_PROTOTYPE) { |
| 39 Advance(); |
| 40 } |
| 41 } |
| 42 PrototypeIterator(Isolate* isolate, Object* receiver, |
| 43 WhereToStart where_to_start = START_AT_PROTOTYPE) |
| 44 : did_jump_to_prototype_chain_(false), |
| 45 object_(receiver), |
| 46 isolate_(isolate) { |
| 47 if (where_to_start == START_AT_PROTOTYPE) { |
| 48 Advance(); |
| 49 } |
| 50 } |
| 51 explicit PrototypeIterator(Map* receiver_map) |
| 52 : did_jump_to_prototype_chain_(true), |
| 53 object_(receiver_map->prototype()), |
| 54 isolate_(receiver_map->GetIsolate()) {} |
| 55 ~PrototypeIterator() {} |
| 56 |
| 57 Object* GetCurrent() const { |
| 58 ASSERT(handle_.is_null()); |
| 59 return object_; |
| 60 } |
| 61 static Handle<Object> GetCurrent(const PrototypeIterator& iterator) { |
| 62 ASSERT(!iterator.handle_.is_null()); |
| 63 return iterator.handle_; |
| 64 } |
| 65 void Advance() { |
| 66 if (handle_.is_null() && object_->IsJSProxy()) { |
| 67 did_jump_to_prototype_chain_ = true; |
| 68 object_ = isolate_->heap()->null_value(); |
| 69 return; |
| 70 } else if (!handle_.is_null() && handle_->IsJSProxy()) { |
| 71 did_jump_to_prototype_chain_ = true; |
| 72 handle_ = handle(isolate_->heap()->null_value(), isolate_); |
| 73 return; |
| 74 } |
| 75 AdvanceIgnoringProxies(); |
| 76 } |
| 77 void AdvanceIgnoringProxies() { |
| 78 if (!did_jump_to_prototype_chain_) { |
| 79 did_jump_to_prototype_chain_ = true; |
| 80 if (handle_.is_null()) { |
| 81 object_ = object_->GetRootMap(isolate_)->prototype(); |
| 82 } else { |
| 83 handle_ = handle(handle_->GetRootMap(isolate_)->prototype(), isolate_); |
| 84 } |
| 85 } else { |
| 86 if (handle_.is_null()) { |
| 87 object_ = HeapObject::cast(object_)->map()->prototype(); |
| 88 } else { |
| 89 handle_ = |
| 90 handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_); |
| 91 } |
| 92 } |
| 93 } |
| 94 bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const { |
| 95 if (handle_.is_null()) { |
| 96 return object_->IsNull() || |
| 97 (did_jump_to_prototype_chain_ && |
| 98 where_to_end == END_AT_NON_HIDDEN && |
| 99 !HeapObject::cast(object_)->map()->is_hidden_prototype()); |
| 100 } else { |
| 101 return handle_->IsNull() || |
| 102 (did_jump_to_prototype_chain_ && |
| 103 where_to_end == END_AT_NON_HIDDEN && |
| 104 !Handle<HeapObject>::cast(handle_)->map()->is_hidden_prototype()); |
| 105 } |
| 106 } |
| 107 bool IsAtEnd(Object* final_object) { |
| 108 ASSERT(handle_.is_null()); |
| 109 return object_->IsNull() || object_ == final_object; |
| 110 } |
| 111 bool IsAtEnd(Handle<Object> final_object) { |
| 112 ASSERT(!handle_.is_null()); |
| 113 return handle_->IsNull() || *handle_ == *final_object; |
| 114 } |
| 115 |
| 116 private: |
| 117 bool did_jump_to_prototype_chain_; |
| 118 Object* object_; |
| 119 Handle<Object> handle_; |
| 120 Isolate* isolate_; |
| 121 |
| 122 DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); |
| 123 }; |
| 124 |
| 125 |
| 126 } // namespace internal |
| 127 |
| 128 } // namespace v8 |
| 129 |
| 130 #endif // V8_PROTOTYPE_H_ |
OLD | NEW |