Index: src/prototype.h |
diff --git a/src/prototype.h b/src/prototype.h |
index 3253791f9078561dba12302b4457398615596743..c5e954554ca88cf6f76f2a06e03be2710b52a383 100644 |
--- a/src/prototype.h |
+++ b/src/prototype.h |
@@ -22,6 +22,7 @@ namespace internal { |
* The PrototypeIterator can either run to the null_value(), the first |
* non-hidden prototype, or a given object. |
*/ |
+ |
class PrototypeIterator { |
public: |
enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE }; |
@@ -30,40 +31,42 @@ class PrototypeIterator { |
const int kProxyPrototypeLimit = 100 * 1000; |
- PrototypeIterator(Isolate* isolate, Handle<Object> receiver, |
- WhereToStart where_to_start = START_AT_PROTOTYPE) |
- : did_jump_to_prototype_chain_(false), |
- object_(NULL), |
+ PrototypeIterator(Isolate* isolate, Handle<JSReceiver> receiver, |
+ WhereToStart where_to_start = START_AT_PROTOTYPE, |
+ WhereToEnd where_to_end = END_AT_NULL) |
+ : object_(NULL), |
handle_(receiver), |
isolate_(isolate), |
+ where_to_end_(where_to_end), |
+ is_at_end_(false), |
seen_proxies_(0) { |
CHECK(!handle_.is_null()); |
- if (where_to_start == START_AT_PROTOTYPE) { |
- Advance(); |
- } |
+ if (where_to_start == START_AT_PROTOTYPE) Advance(); |
} |
- PrototypeIterator(Isolate* isolate, Object* receiver, |
- WhereToStart where_to_start = START_AT_PROTOTYPE) |
- : did_jump_to_prototype_chain_(false), |
- object_(receiver), |
+ PrototypeIterator(Isolate* isolate, JSReceiver* receiver, |
+ WhereToStart where_to_start = START_AT_PROTOTYPE, |
+ WhereToEnd where_to_end = END_AT_NULL) |
+ : object_(receiver), |
isolate_(isolate), |
+ where_to_end_(where_to_end), |
+ is_at_end_(false), |
seen_proxies_(0) { |
- if (where_to_start == START_AT_PROTOTYPE) { |
- Advance(); |
- } |
+ if (where_to_start == START_AT_PROTOTYPE) Advance(); |
} |
explicit PrototypeIterator(Map* receiver_map) |
- : did_jump_to_prototype_chain_(true), |
- object_(receiver_map->prototype()), |
- isolate_(receiver_map->GetIsolate()) {} |
+ : object_(receiver_map->prototype()), |
+ isolate_(receiver_map->GetIsolate()), |
+ where_to_end_(END_AT_NULL), |
+ is_at_end_(object_->IsNull()) {} |
explicit PrototypeIterator(Handle<Map> receiver_map) |
- : did_jump_to_prototype_chain_(true), |
- object_(NULL), |
+ : object_(NULL), |
handle_(handle(receiver_map->prototype(), receiver_map->GetIsolate())), |
- isolate_(receiver_map->GetIsolate()) {} |
+ isolate_(receiver_map->GetIsolate()), |
+ where_to_end_(END_AT_NULL), |
+ is_at_end_(handle_->IsNull()) {} |
~PrototypeIterator() {} |
@@ -93,32 +96,30 @@ class PrototypeIterator { |
void Advance() { |
if (handle_.is_null() && object_->IsJSProxy()) { |
- did_jump_to_prototype_chain_ = true; |
+ is_at_end_ = true; |
object_ = isolate_->heap()->null_value(); |
return; |
} else if (!handle_.is_null() && handle_->IsJSProxy()) { |
- did_jump_to_prototype_chain_ = true; |
- handle_ = handle(isolate_->heap()->null_value(), isolate_); |
+ is_at_end_ = true; |
+ handle_ = isolate_->factory()->null_value(); |
return; |
} |
AdvanceIgnoringProxies(); |
} |
void AdvanceIgnoringProxies() { |
- if (!did_jump_to_prototype_chain_) { |
- did_jump_to_prototype_chain_ = true; |
- if (handle_.is_null()) { |
- object_ = object_->GetRootMap(isolate_)->prototype(); |
- } else { |
- handle_ = handle(handle_->GetRootMap(isolate_)->prototype(), isolate_); |
- } |
+ Object* object = handle_.is_null() ? object_ : *handle_; |
+ Map* map = HeapObject::cast(object)->map(); |
+ |
+ Object* prototype = map->prototype(); |
+ is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN |
+ ? !map->has_hidden_prototype() |
+ : prototype->IsNull(); |
+ |
+ if (handle_.is_null()) { |
+ object_ = prototype; |
} else { |
- if (handle_.is_null()) { |
- object_ = HeapObject::cast(object_)->map()->prototype(); |
- } else { |
- handle_ = |
- handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_); |
- } |
+ handle_ = handle(prototype, isolate_); |
} |
} |
@@ -129,6 +130,7 @@ class PrototypeIterator { |
if (!HasAccess()) { |
// Abort the lookup if we do not have access to the current object. |
handle_ = isolate_->factory()->null_value(); |
+ is_at_end_ = true; |
return true; |
} |
if (handle_.is_null() || !handle_->IsJSProxy()) { |
@@ -143,41 +145,21 @@ class PrototypeIterator { |
*isolate_->factory()->NewRangeError(MessageTemplate::kStackOverflow)); |
return false; |
} |
- did_jump_to_prototype_chain_ = true; |
MaybeHandle<Object> proto = |
JSProxy::GetPrototype(Handle<JSProxy>::cast(handle_)); |
- return proto.ToHandle(&handle_); |
- } |
- |
- bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const { |
- if (handle_.is_null()) { |
- return object_->IsNull() || |
- (did_jump_to_prototype_chain_ && |
- where_to_end == END_AT_NON_HIDDEN && |
- !HeapObject::cast(object_)->map()->is_hidden_prototype()); |
- } else { |
- return handle_->IsNull() || |
- (did_jump_to_prototype_chain_ && |
- where_to_end == END_AT_NON_HIDDEN && |
- !Handle<HeapObject>::cast(handle_)->map()->is_hidden_prototype()); |
- } |
- } |
- |
- bool IsAtEnd(Object* final_object) { |
- DCHECK(handle_.is_null()); |
- return object_->IsNull() || object_ == final_object; |
+ if (!proto.ToHandle(&handle_)) return false; |
+ is_at_end_ = where_to_end_ == END_AT_NON_HIDDEN || handle_->IsNull(); |
+ return true; |
} |
- bool IsAtEnd(Handle<Object> final_object) { |
- DCHECK(!handle_.is_null()); |
- return handle_->IsNull() || *handle_ == *final_object; |
- } |
+ bool IsAtEnd() const { return is_at_end_; } |
private: |
- bool did_jump_to_prototype_chain_; |
Object* object_; |
Handle<Object> handle_; |
Isolate* isolate_; |
+ WhereToEnd where_to_end_; |
+ bool is_at_end_; |
int seen_proxies_; |
DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); |