"src/property-details.h",
"src/property.cc",
"src/property.h",
+ "src/prototype.h",
"src/regexp-macro-assembler-irregexp-inl.h",
"src/regexp-macro-assembler-irregexp.cc",
"src/regexp-macro-assembler-irregexp.h",
#include "src/isolate.h"
#include "src/list-inl.h"
#include "src/property-details.h"
+#include "src/prototype.h"
namespace v8 {
namespace internal {
template <class C>
static C* FindInstanceOf(Isolate* isolate, Object* obj) {
- for (Object* cur = obj; !cur->IsNull(); cur = cur->GetPrototype(isolate)) {
- if (Is<C>(cur)) return C::cast(cur);
+ for (PrototypeIterator iter(isolate, obj,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (Is<C>(iter.GetCurrent())) return C::cast(iter.GetCurrent());
}
return NULL;
}
#include "src/profile-generator-inl.h"
#include "src/property.h"
#include "src/property-details.h"
+#include "src/prototype.h"
#include "src/runtime.h"
#include "src/runtime-profiler.h"
#include "src/scanner-character-streams.h"
ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
ENTER_V8(isolate);
i::Handle<i::Object> self = Utils::OpenHandle(this);
- i::Handle<i::Object> result(self->GetPrototype(isolate), isolate);
- return Utils::ToLocal(result);
+ i::PrototypeIterator iter(isolate, self);
+ return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
}
#include "src/heap-profiler.h"
#include "src/ic-inl.h"
#include "src/mark-compact.h"
+#include "src/prototype.h"
#include "src/stub-cache.h"
#include "src/vm-state-inl.h"
static inline Object* FindHidden(Heap* heap,
Object* object,
FunctionTemplateInfo* type) {
- if (type->IsTemplateFor(object)) return object;
- Object* proto = object->GetPrototype(heap->isolate());
- if (proto->IsJSObject() &&
- JSObject::cast(proto)->map()->is_hidden_prototype()) {
- return FindHidden(heap, proto, type);
+ for (PrototypeIterator iter(heap->isolate(), object,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
+ if (type->IsTemplateFor(iter.GetCurrent())) {
+ return iter.GetCurrent();
+ }
}
return heap->null_value();
}
#include "src/compiler.h"
#include "src/debug.h"
#include "src/macro-assembler.h"
+#include "src/prototype.h"
namespace v8 {
namespace internal {
Object* object,
InlineCacheHolderFlag holder) {
if (object->IsSmi()) holder = PROTOTYPE_MAP;
- Object* map_owner = holder == OWN_MAP
- ? object : object->GetPrototype(isolate);
- return HeapObject::cast(map_owner);
+ PrototypeIterator iter(isolate, object,
+ holder == OWN_MAP
+ ? PrototypeIterator::START_AT_RECEIVER
+ : PrototypeIterator::START_AT_PROTOTYPE);
+ return HeapObject::cast(iter.GetCurrent());
}
#include "src/conversions.h"
#include "src/execution.h"
#include "src/ic-inl.h"
+#include "src/prototype.h"
#include "src/runtime.h"
#include "src/stub-cache.h"
break;
case PROTOTYPE_MAP:
// IC::GetCodeCacheHolder is not applicable.
- if (receiver->GetPrototype(isolate())->IsNull()) return false;
+ PrototypeIterator iter(isolate(), receiver);
+ if (iter.IsAtEnd()) return false;
break;
}
#include "src/lithium-allocator.h"
#include "src/log.h"
#include "src/messages.h"
+#include "src/prototype.h"
#include "src/regexp-stack.h"
#include "src/runtime-profiler.h"
#include "src/sampler.h"
js_builtins_object(), error_key).ToHandleChecked();
DisallowHeapAllocation no_gc;
- for (Object* prototype = *obj; !prototype->IsNull();
- prototype = prototype->GetPrototype(this)) {
- if (!prototype->IsJSObject()) return false;
- if (JSObject::cast(prototype)->map()->constructor() ==
+ for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (iter.GetCurrent()->IsJSProxy()) return false;
+ if (JSObject::cast(iter.GetCurrent())->map()->constructor() ==
*error_constructor) {
return true;
}
#include "src/mark-compact.h"
#include "src/objects-inl.h"
#include "src/objects-visiting-inl.h"
+#include "src/prototype.h"
#include "src/safepoint-table.h"
#include "src/string-search.h"
#include "src/string-stream.h"
Handle<Object> object,
Handle<Object> receiver,
uint32_t index) {
- Handle<Object> holder;
+ if (object->IsUndefined()) {
+ // TODO(verwaest): Why is this check here?
+ UNREACHABLE();
+ return isolate->factory()->undefined_value();
+ }
// Iterate up the prototype chain until an element is found or the null
// prototype is encountered.
- for (holder = object;
- !holder->IsNull();
- holder = Handle<Object>(holder->GetPrototype(isolate), isolate)) {
- if (!holder->IsJSObject()) {
- if (holder->IsJSProxy()) {
- return JSProxy::GetElementWithHandler(
- Handle<JSProxy>::cast(holder), receiver, index);
- } else if (holder->IsUndefined()) {
- // Undefined has no indexed properties.
- return isolate->factory()->undefined_value();
- } else {
- holder = Handle<Object>(holder->GetPrototype(isolate), isolate);
- ASSERT(holder->IsJSObject());
- }
+ for (PrototypeIterator iter(isolate, object,
+ object->IsJSProxy() || object->IsJSObject()
+ ? PrototypeIterator::START_AT_RECEIVER
+ : PrototypeIterator::START_AT_PROTOTYPE);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
+ return JSProxy::GetElementWithHandler(
+ Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver,
+ index);
}
// Inline the case for JSObjects. Doing so significantly improves the
// performance of fetching elements where checking the prototype chain is
// necessary.
- Handle<JSObject> js_object = Handle<JSObject>::cast(holder);
+ Handle<JSObject> js_object =
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
// Check access rights if needed.
if (js_object->IsAccessCheckNeeded()) {
}
-Object* Object::GetPrototype(Isolate* isolate) {
+Map* Object::GetRootMap(Isolate* isolate) {
DisallowHeapAllocation no_alloc;
if (IsSmi()) {
Context* context = isolate->context()->native_context();
- return context->number_function()->instance_prototype();
+ return context->number_function()->initial_map();
}
HeapObject* heap_object = HeapObject::cast(this);
// The object is either a number, a string, a boolean,
// a real JS object, or a Harmony proxy.
if (heap_object->IsJSReceiver()) {
- return heap_object->map()->prototype();
+ return heap_object->map();
}
Context* context = isolate->context()->native_context();
if (heap_object->IsHeapNumber()) {
- return context->number_function()->instance_prototype();
+ return context->number_function()->initial_map();
}
if (heap_object->IsString()) {
- return context->string_function()->instance_prototype();
+ return context->string_function()->initial_map();
}
if (heap_object->IsSymbol()) {
- return context->symbol_function()->instance_prototype();
+ return context->symbol_function()->initial_map();
}
if (heap_object->IsBoolean()) {
- return context->boolean_function()->instance_prototype();
- } else {
- return isolate->heap()->null_value();
+ return context->boolean_function()->initial_map();
}
-}
-
-
-Handle<Object> Object::GetPrototype(Isolate* isolate,
- Handle<Object> object) {
- return handle(object->GetPrototype(isolate), isolate);
+ return isolate->heap()->null_value()->map();
}
bool* found,
StrictMode strict_mode) {
Isolate *isolate = object->GetIsolate();
- for (Handle<Object> proto = handle(object->GetPrototype(), isolate);
- !proto->IsNull();
- proto = handle(proto->GetPrototype(isolate), isolate)) {
- if (proto->IsJSProxy()) {
+ for (PrototypeIterator iter(isolate, object); !iter.IsAtEnd();
+ iter.Advance()) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
return JSProxy::SetPropertyViaPrototypesWithHandler(
- Handle<JSProxy>::cast(proto),
- object,
+ Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), object,
isolate->factory()->Uint32ToString(index), // name
- value,
- NONE,
- strict_mode,
- found);
+ value, NONE, strict_mode, found);
}
- Handle<JSObject> js_proto = Handle<JSObject>::cast(proto);
+ Handle<JSObject> js_proto =
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
if (!js_proto->HasDictionaryElements()) {
continue;
}
LookupResult* result) {
DisallowHeapAllocation no_gc;
Isolate* isolate = GetIsolate();
- Heap* heap = isolate->heap();
- for (Object* pt = GetPrototype();
- pt != heap->null_value();
- pt = pt->GetPrototype(isolate)) {
- if (pt->IsJSProxy()) {
- return result->HandlerResult(JSProxy::cast(pt));
+ for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) {
+ if (iter.GetCurrent()->IsJSProxy()) {
+ return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
}
- JSObject::cast(pt)->LookupOwnRealNamedProperty(name, result);
+ JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name, result);
ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
if (result->IsFound()) return;
}
JSFunction::cast(isolate->sloppy_arguments_map()->constructor()));
// Only collect keys if access is permitted.
- for (Handle<Object> p = object;
- *p != isolate->heap()->null_value();
- p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
- if (p->IsJSProxy()) {
- Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
+ for (PrototypeIterator iter(isolate, object,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
+ Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)),
+ isolate);
Handle<Object> args[] = { proxy };
Handle<Object> names;
ASSIGN_RETURN_ON_EXCEPTION(
break;
}
- Handle<JSObject> current(JSObject::cast(*p), isolate);
+ Handle<JSObject> current =
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
// Check access rights if required.
if (current->IsAccessCheckNeeded() &&
bool Map::DictionaryElementsInPrototypeChainOnly() {
- Heap* heap = GetHeap();
-
if (IsDictionaryElementsKind(elements_kind())) {
return false;
}
- for (Object* prototype = this->prototype();
- prototype != heap->null_value();
- prototype = prototype->GetPrototype(GetIsolate())) {
- if (prototype->IsJSProxy()) {
+ for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
+ if (iter.GetCurrent()->IsJSProxy()) {
// Be conservative, don't walk into proxies.
return true;
}
if (IsDictionaryElementsKind(
- JSObject::cast(prototype)->map()->elements_kind())) {
+ JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
return true;
}
}
Handle<Object> prototype;
if (function->has_instance_prototype()) {
prototype = handle(function->instance_prototype(), isolate);
- for (Handle<Object> p = prototype; !p->IsNull() && !p->IsJSProxy();
- p = Object::GetPrototype(isolate, p)) {
- JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(p));
+ for (PrototypeIterator iter(isolate, prototype,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
+ break;
+ }
+ JSObject::OptimizeAsPrototype(
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
}
} else {
prototype = isolate->factory()->NewFunctionPrototype(function);
// prototype cycles are prevented.
// It is sufficient to validate that the receiver is not in the new prototype
// chain.
- for (Object* pt = *value;
- pt != heap->null_value();
- pt = pt->GetPrototype(isolate)) {
- if (JSReceiver::cast(pt) == *object) {
+ for (PrototypeIterator iter(isolate, *value,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (JSReceiver::cast(iter.GetCurrent()) == *object) {
// Cycle detected.
Handle<Object> error = isolate->factory()->NewError(
"cyclic_proto", HandleVector<Object>(NULL, 0));
if (skip_hidden_prototypes) {
// Find the first object in the chain whose prototype object is not
// hidden and set the new prototype on that object.
- Object* current_proto = real_receiver->GetPrototype();
- while (current_proto->IsJSObject() &&
- JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
- real_receiver = handle(JSObject::cast(current_proto), isolate);
- current_proto = current_proto->GetPrototype(isolate);
+ PrototypeIterator iter(isolate, real_receiver);
+ while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
+ real_receiver =
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
+ iter.Advance();
}
}
Handle<Object> receiver,
uint32_t index);
- // Return the object's prototype (might be Heap::null_value()).
- Object* GetPrototype(Isolate* isolate);
- static Handle<Object> GetPrototype(Isolate* isolate, Handle<Object> object);
-
// Returns the permanent hash code associated with this object. May return
// undefined if not yet created.
Object* GetHash();
#endif
private:
+ friend class PrototypeIterator;
+
+ // Return the map of the root of object's prototype chain.
+ Map* GetRootMap(Isolate* isolate);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};
--- /dev/null
+// 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_H_
+#define V8_PROTOTYPE_H_
+
+#include "src/isolate.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+/**
+ * A class to uniformly access the prototype of any Object and walk its
+ * prototype chain.
+ *
+ * The PrototypeIterator can either start at the prototype (default), or
+ * include the receiver itself. If a PrototypeIterator is constructed for a
+ * Map, it will always start at the prototype.
+ *
+ * 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 };
+
+ enum WhereToEnd { END_AT_NULL, END_AT_NON_HIDDEN };
+
+ PrototypeIterator(Isolate* isolate, Handle<Object> receiver,
+ WhereToStart where_to_start = START_AT_PROTOTYPE)
+ : did_jump_to_prototype_chain_(false),
+ object_(NULL),
+ handle_(receiver),
+ isolate_(isolate) {
+ CHECK(!handle_.is_null());
+ 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),
+ isolate_(isolate) {
+ 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()) {}
+ ~PrototypeIterator() {}
+
+ Object* GetCurrent() const {
+ ASSERT(handle_.is_null());
+ return object_;
+ }
+ static Handle<Object> GetCurrent(const PrototypeIterator& iterator) {
+ ASSERT(!iterator.handle_.is_null());
+ return iterator.handle_;
+ }
+ void Advance() {
+ if (handle_.is_null() && object_->IsJSProxy()) {
+ did_jump_to_prototype_chain_ = 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_);
+ 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_);
+ }
+ } else {
+ if (handle_.is_null()) {
+ object_ = HeapObject::cast(object_)->map()->prototype();
+ } else {
+ handle_ =
+ handle(HeapObject::cast(*handle_)->map()->prototype(), isolate_);
+ }
+ }
+ }
+ 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) {
+ ASSERT(handle_.is_null());
+ return object_->IsNull() || object_ == final_object;
+ }
+ bool IsAtEnd(Handle<Object> final_object) {
+ ASSERT(!handle_.is_null());
+ return handle_->IsNull() || *handle_ == *final_object;
+ }
+
+ private:
+ bool did_jump_to_prototype_chain_;
+ Object* object_;
+ Handle<Object> handle_;
+ Isolate* isolate_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrototypeIterator);
+};
+
+
+} // namespace internal
+
+} // namespace v8
+
+#endif // V8_PROTOTYPE_H_
#include "src/liveedit.h"
#include "src/misc-intrinsics.h"
#include "src/parser.h"
+#include "src/prototype.h"
#include "src/runtime.h"
#include "src/runtime-profiler.h"
#include "src/scopeinfo.h"
CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
// We don't expect access checks to be needed on JSProxy objects.
ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
+ PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
do {
- if (obj->IsAccessCheckNeeded() &&
- !isolate->MayNamedAccess(Handle<JSObject>::cast(obj),
- isolate->factory()->proto_string(),
- v8::ACCESS_GET)) {
- isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
- v8::ACCESS_GET);
+ if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
+ !isolate->MayNamedAccess(
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
+ isolate->factory()->proto_string(), v8::ACCESS_GET)) {
+ isolate->ReportFailedAccessCheck(
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)),
+ v8::ACCESS_GET);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return isolate->heap()->undefined_value();
}
- obj = Object::GetPrototype(isolate, obj);
- } while (obj->IsJSObject() &&
- JSObject::cast(*obj)->map()->is_hidden_prototype());
- return *obj;
+ iter.AdvanceIgnoringProxies();
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
+ return *PrototypeIterator::GetCurrent(iter);
+ }
+ } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
+ return *PrototypeIterator::GetCurrent(iter);
}
static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
Isolate* isolate, Handle<Object> receiver) {
- Handle<Object> current = Object::GetPrototype(isolate, receiver);
- while (current->IsJSObject() &&
- JSObject::cast(*current)->map()->is_hidden_prototype()) {
- current = Object::GetPrototype(isolate, current);
+ PrototypeIterator iter(isolate, receiver);
+ while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
+ return PrototypeIterator::GetCurrent(iter);
+ }
+ iter.Advance();
}
- return current;
+ return PrototypeIterator::GetCurrent(iter);
}
// See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
+ PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
while (true) {
- Handle<Object> prototype = Object::GetPrototype(isolate, V);
- if (prototype->IsNull()) return isolate->heap()->false_value();
- if (*O == *prototype) return isolate->heap()->true_value();
- V = prototype;
+ iter.AdvanceIgnoringProxies();
+ if (iter.IsAtEnd()) return isolate->heap()->false_value();
+ if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
}
}
Handle<Object> result;
if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
- Handle<Object> proto(object->GetPrototype(isolate), isolate);
- return Object::GetElement(isolate, proto, index);
+ PrototypeIterator iter(isolate, object);
+ return Object::GetElement(isolate, PrototypeIterator::GetCurrent(iter),
+ index);
} else {
return Object::GetElement(isolate, object, index);
}
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
if (array->elements()->IsDictionary()) {
Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
- for (Handle<Object> p = array;
- !p->IsNull();
- p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
- if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
+ for (PrototypeIterator iter(isolate, array,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy() ||
+ JSObject::cast(*PrototypeIterator::GetCurrent(iter))
+ ->HasIndexedInterceptor()) {
// Bail out if we find a proxy or interceptor, likely not worth
// collecting keys in that case.
return *isolate->factory()->NewNumberFromUint(length);
}
- Handle<JSObject> current = Handle<JSObject>::cast(p);
+ Handle<JSObject> current =
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
Handle<FixedArray> current_keys =
isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
current->GetOwnElementKeys(*current_keys, NONE);
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
if (result->IsJSGlobalProxy()) {
- result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
+ PrototypeIterator iter(isolate, result);
+ // TODO(verwaest): This will crash when the global proxy is detached.
+ result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
}
// Clear the oneshot breakpoints so that the debugger does not step further.
// Check instance filter if supplied. This is normally used to avoid
// references from mirror objects (see Runtime_IsInPrototypeChain).
if (!instance_filter->IsUndefined()) {
- Object* V = obj;
- while (true) {
- Object* prototype = V->GetPrototype(isolate);
- if (prototype->IsNull()) {
- break;
- }
- if (instance_filter == prototype) {
+ for (PrototypeIterator iter(isolate, obj); !iter.IsAtEnd();
+ iter.Advance()) {
+ if (iter.GetCurrent() == instance_filter) {
obj = NULL; // Don't add this object.
break;
}
- V = prototype;
}
}
#include "src/string-stream.h"
#include "src/handles-inl.h"
+#include "src/prototype.h"
namespace v8 {
namespace internal {
Object* name = fun->shared()->name();
bool print_name = false;
Isolate* isolate = fun->GetIsolate();
- for (Object* p = receiver;
- p != isolate->heap()->null_value();
- p = p->GetPrototype(isolate)) {
- if (p->IsJSObject()) {
- Object* key = JSObject::cast(p)->SlowReverseLookup(fun);
+ for (PrototypeIterator iter(isolate, receiver,
+ PrototypeIterator::START_AT_RECEIVER);
+ !iter.IsAtEnd(); iter.Advance()) {
+ if (iter.GetCurrent()->IsJSObject()) {
+ Object* key = JSObject::cast(iter.GetCurrent())->SlowReverseLookup(fun);
if (key != isolate->heap()->undefined_value()) {
if (!name->IsString() ||
!key->IsString() ||
'../../src/property-details.h',
'../../src/property.cc',
'../../src/property.h',
+ '../../src/prototype.h',
'../../src/regexp-macro-assembler-irregexp-inl.h',
'../../src/regexp-macro-assembler-irregexp.cc',
'../../src/regexp-macro-assembler-irregexp.h',