19bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved. 29bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be 39bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org// found in the LICENSE file. 49bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 59bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#ifndef V8_PROTOTYPE_H_ 69bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#define V8_PROTOTYPE_H_ 79bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 89bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#include "src/isolate.h" 99bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#include "src/objects.h" 109bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 119bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgnamespace v8 { 129bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgnamespace internal { 139bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 149bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org/** 159bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * A class to uniformly access the prototype of any Object and walk its 169bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * prototype chain. 179bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * 189bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * The PrototypeIterator can either start at the prototype (default), or 199bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * include the receiver itself. If a PrototypeIterator is constructed for a 209bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * Map, it will always start at the prototype. 219bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * 229bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * The PrototypeIterator can either run to the null_value(), the first 239bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org * non-hidden prototype, or a given object. 249bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org */ 259bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgclass PrototypeIterator { 269bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org public: 279bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org enum WhereToStart { START_AT_RECEIVER, START_AT_PROTOTYPE }; 289bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 299bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN }; 309bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 319bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org PrototypeIterator(Isolate* isolate, Handle<Object> receiver, 329bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org WhereToStart where_to_start = START_AT_PROTOTYPE) 339bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org : did_jump_to_prototype_chain_(false), 349bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_(NULL), 359bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org handle_(receiver), 369bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org isolate_(isolate) { 379bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org CHECK(!handle_.is_null()); 389bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (where_to_start == START_AT_PROTOTYPE) { 399bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Advance(); 409bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 419bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 429bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org PrototypeIterator(Isolate* isolate, Object* receiver, 439bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org WhereToStart where_to_start = START_AT_PROTOTYPE) 449bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org : did_jump_to_prototype_chain_(false), 459bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_(receiver), 469bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org isolate_(isolate) { 479bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (where_to_start == START_AT_PROTOTYPE) { 489bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Advance(); 499bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 509bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 519bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org explicit PrototypeIterator(Map* receiver_map) 529bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org : did_jump_to_prototype_chain_(true), 539bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_(receiver_map->prototype()), 549bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org isolate_(receiver_map->GetIsolate()) {} 5593720aaa16a789ba13d52a265a479b26f4885e2emachenbach@chromium.org explicit PrototypeIterator(Handle<Map> receiver_map) 5693720aaa16a789ba13d52a265a479b26f4885e2emachenbach@chromium.org : did_jump_to_prototype_chain_(true), 5793720aaa16a789ba13d52a265a479b26f4885e2emachenbach@chromium.org object_(NULL), 5893720aaa16a789ba13d52a265a479b26f4885e2emachenbach@chromium.org handle_(handle(receiver_map->prototype(), receiver_map->GetIsolate())), 5993720aaa16a789ba13d52a265a479b26f4885e2emachenbach@chromium.org isolate_(receiver_map->GetIsolate()) {} 609bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org ~PrototypeIterator() {} 619bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 629bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Object* GetCurrent() const { 63e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(handle_.is_null()); 649bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return object_; 659bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 669bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org static Handle<Object> GetCurrent(const PrototypeIterator& iterator) { 67e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!iterator.handle_.is_null()); 689bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return iterator.handle_; 699bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 709bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org void Advance() { 719bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (handle_.is_null() && object_->IsJSProxy()) { 729bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org did_jump_to_prototype_chain_ = true; 739bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_ = isolate_->heap()->null_value(); 749bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return; 759bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } else if (!handle_.is_null() && handle_->IsJSProxy()) { 769bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org did_jump_to_prototype_chain_ = true; 779bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org handle_ = handle(isolate_->heap()->null_value(), isolate_); 789bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return; 799bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 809bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org AdvanceIgnoringProxies(); 819bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 829bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org void AdvanceIgnoringProxies() { 839bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (!did_jump_to_prototype_chain_) { 849bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org did_jump_to_prototype_chain_ = true; 859bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (handle_.is_null()) { 869bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_ = object_->GetRootMap(isolate_)->prototype(); 879bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } else { 889bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org handle_ = handle(handle_->GetRootMap(isolate_)->prototype(), isolate_); 899bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 909bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } else { 919bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (handle_.is_null()) { 929bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org object_ = HeapObject::cast(object_)->map()->prototype(); 939bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } else { 949bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org handle_ = 959bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_); 969bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 979bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 989bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 999bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org bool IsAtEnd(WhereToEnd where_to_end = END_AT_NULL) const { 1009bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org if (handle_.is_null()) { 1019bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return object_->IsNull() || 1029bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org (did_jump_to_prototype_chain_ && 1039bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org where_to_end == END_AT_NON_HIDDEN && 1049bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org !HeapObject::cast(object_)->map()->is_hidden_prototype()); 1059bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } else { 1069bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return handle_->IsNull() || 1079bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org (did_jump_to_prototype_chain_ && 1089bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org where_to_end == END_AT_NON_HIDDEN && 1099bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org !Handle<HeapObject>::cast(handle_)->map()->is_hidden_prototype()); 1109bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 1119bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 1129bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org bool IsAtEnd(Object* final_object) { 113e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(handle_.is_null()); 1149bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return object_->IsNull() || object_ == final_object; 1159bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 1169bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org bool IsAtEnd(Handle<Object> final_object) { 117e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!handle_.is_null()); 1189bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org return handle_->IsNull() || *handle_ == *final_object; 1199bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org } 1209bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1219bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org private: 1229bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org bool did_jump_to_prototype_chain_; 1239bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Object* object_; 1249bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Handle<Object> handle_; 1259bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org Isolate* isolate_; 1269bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1279bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org DISALLOW_COPY_AND_ASSIGN(PrototypeIterator); 1289bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org}; 1299bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1309bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1319bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org} // namespace internal 1329bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1339bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org} // namespace v8 1349bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org 1359bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org#endif // V8_PROTOTYPE_H_ 136