Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 584dba5998c0e461383e3668678f2dc5b73d78eb..0d839726881a2129cde78a497a9c7469d5275a69 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -3449,10 +3449,11 @@ void JSObject::LookupOwnRealNamedProperty(Handle<Name> name, |
LookupResult* result) { |
DisallowHeapAllocation no_gc; |
if (IsJSGlobalProxy()) { |
- Object* proto = GetPrototype(); |
- if (proto->IsNull()) return result->NotFound(); |
- ASSERT(proto->IsJSGlobalObject()); |
- return JSObject::cast(proto)->LookupOwnRealNamedProperty(name, result); |
+ PrototypeIterator iter(GetIsolate(), this); |
+ if (iter.IsAtEnd()) return result->NotFound(); |
+ ASSERT(iter.GetCurrent()->IsJSGlobalObject()); |
+ return JSObject::cast(iter.GetCurrent()) |
+ ->LookupOwnRealNamedProperty(name, result); |
} |
if (HasFastProperties()) { |
@@ -4076,11 +4077,12 @@ MaybeHandle<Object> JSObject::SetPropertyForResult( |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return value; |
- ASSERT(proto->IsJSGlobalObject()); |
- return SetPropertyForResult(Handle<JSObject>::cast(proto), lookup, name, |
- value, strict_mode, store_mode); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return value; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return SetPropertyForResult( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), lookup, |
+ name, value, strict_mode, store_mode); |
} |
ASSERT(!lookup->IsFound() || lookup->holder() == *object || |
@@ -4230,12 +4232,12 @@ MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes( |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return value; |
- ASSERT(proto->IsJSGlobalObject()); |
- return SetOwnPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), name, |
- value, attributes, mode, |
- extensibility_check); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return value; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return SetOwnPropertyIgnoreAttributes( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), name, |
+ value, attributes, mode, extensibility_check); |
} |
if (lookup.IsInterceptor() || |
@@ -4465,11 +4467,12 @@ PropertyAttributes JSObject::GetElementAttributeWithReceiver( |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return ABSENT; |
- ASSERT(proto->IsJSGlobalObject()); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return ABSENT; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
return JSObject::GetElementAttributeWithReceiver( |
- Handle<JSObject>::cast(proto), receiver, index, check_prototype); |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
+ index, check_prototype); |
} |
// Check for lookup interceptor except when bootstrapping. |
@@ -4537,15 +4540,17 @@ PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( |
if (!check_prototype) return ABSENT; |
- Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); |
- if (proto->IsJSProxy()) { |
+ PrototypeIterator iter(object->GetIsolate(), object); |
+ if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
// We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
return JSProxy::GetElementAttributeWithHandler( |
- Handle<JSProxy>::cast(proto), receiver, index); |
+ Handle<JSProxy>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
+ index); |
} |
- if (proto->IsNull()) return ABSENT; |
+ if (iter.IsAtEnd()) return ABSENT; |
return GetElementAttributeWithReceiver( |
- Handle<JSObject>::cast(proto), receiver, index, true); |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), receiver, |
+ index, true); |
} |
@@ -5023,11 +5028,11 @@ Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
// JSGlobalProxies store their hash internally. |
ASSERT(*key != GetHeap()->identity_hash_string()); |
// For a proxy, use the prototype as target object. |
- Object* proxy_parent = GetPrototype(); |
+ PrototypeIterator iter(GetIsolate(), this); |
// If the proxy is detached, return undefined. |
- if (proxy_parent->IsNull()) return GetHeap()->the_hole_value(); |
- ASSERT(proxy_parent->IsJSGlobalObject()); |
- return JSObject::cast(proxy_parent)->GetHiddenProperty(key); |
+ if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); |
+ ASSERT(iter.GetCurrent()->IsJSGlobalObject()); |
+ return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); |
} |
ASSERT(!IsJSGlobalProxy()); |
Object* inline_value = GetHiddenPropertiesHashTable(); |
@@ -5059,11 +5064,13 @@ Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
// JSGlobalProxies store their hash internally. |
ASSERT(*key != *isolate->factory()->identity_hash_string()); |
// For a proxy, use the prototype as target object. |
- Handle<Object> proxy_parent(object->GetPrototype(), isolate); |
+ PrototypeIterator iter(isolate, object); |
// If the proxy is detached, return undefined. |
- if (proxy_parent->IsNull()) return isolate->factory()->undefined_value(); |
- ASSERT(proxy_parent->IsJSGlobalObject()); |
- return SetHiddenProperty(Handle<JSObject>::cast(proxy_parent), key, value); |
+ if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return SetHiddenProperty( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, |
+ value); |
} |
ASSERT(!object->IsJSGlobalProxy()); |
@@ -5098,10 +5105,11 @@ void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
ASSERT(key->IsUniqueName()); |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return; |
- ASSERT(proto->IsJSGlobalObject()); |
- return DeleteHiddenProperty(Handle<JSObject>::cast(proto), key); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return DeleteHiddenProperty( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); |
} |
Object* inline_value = object->GetHiddenPropertiesHashTable(); |
@@ -5332,10 +5340,12 @@ MaybeHandle<Object> JSObject::DeleteElement(Handle<JSObject> object, |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return factory->false_value(); |
- ASSERT(proto->IsJSGlobalObject()); |
- return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return factory->false_value(); |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return DeleteElement( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
+ mode); |
} |
Handle<Object> old_value; |
@@ -5387,11 +5397,12 @@ MaybeHandle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
} |
if (object->IsJSGlobalProxy()) { |
- Object* proto = object->GetPrototype(); |
- if (proto->IsNull()) return isolate->factory()->false_value(); |
- ASSERT(proto->IsJSGlobalObject()); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return isolate->factory()->false_value(); |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
return JSGlobalObject::DeleteProperty( |
- handle(JSGlobalObject::cast(proto)), name, mode); |
+ Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)), name, |
+ mode); |
} |
uint32_t index = 0; |
@@ -5620,10 +5631,11 @@ MaybeHandle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return object; |
- ASSERT(proto->IsJSGlobalObject()); |
- return PreventExtensions(Handle<JSObject>::cast(proto)); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return object; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return PreventExtensions( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
} |
// It's not possible to seal objects with external array elements |
@@ -5703,10 +5715,10 @@ MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return object; |
- ASSERT(proto->IsJSGlobalObject()); |
- return Freeze(Handle<JSObject>::cast(proto)); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return object; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return Freeze(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); |
} |
// It's not possible to freeze objects with external array elements |
@@ -6091,12 +6103,11 @@ Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, |
// - This object has no elements. |
// - No prototype has enumerable properties/elements. |
bool JSReceiver::IsSimpleEnum() { |
- Heap* heap = GetHeap(); |
- for (Object* o = this; |
- o != heap->null_value(); |
- o = JSObject::cast(o)->GetPrototype()) { |
- if (!o->IsJSObject()) return false; |
- JSObject* curr = JSObject::cast(o); |
+ for (PrototypeIterator iter(GetIsolate(), this, |
+ PrototypeIterator::START_AT_RECEIVER); |
+ !iter.IsAtEnd(); iter.Advance()) { |
+ if (!iter.GetCurrent()->IsJSObject()) return false; |
+ JSObject* curr = JSObject::cast(iter.GetCurrent()); |
int enum_length = curr->map()->EnumLength(); |
if (enum_length == kInvalidEnumCacheSentinel) return false; |
if (curr->IsAccessCheckNeeded()) return false; |
@@ -6164,11 +6175,11 @@ void JSReceiver::LookupOwn( |
ASSERT(name->IsName()); |
if (IsJSGlobalProxy()) { |
- Object* proto = GetPrototype(); |
- if (proto->IsNull()) return result->NotFound(); |
- ASSERT(proto->IsJSGlobalObject()); |
- return JSReceiver::cast(proto)->LookupOwn( |
- name, result, search_hidden_prototypes); |
+ PrototypeIterator iter(GetIsolate(), this); |
+ if (iter.IsAtEnd()) return result->NotFound(); |
+ ASSERT(iter.GetCurrent()->IsJSGlobalObject()); |
+ return JSReceiver::cast(iter.GetCurrent()) |
+ ->LookupOwn(name, result, search_hidden_prototypes); |
} |
if (IsJSProxy()) { |
@@ -6194,9 +6205,9 @@ void JSReceiver::LookupOwn( |
js_object->LookupOwnRealNamedProperty(name, result); |
if (result->IsFound() || !search_hidden_prototypes) return; |
- Object* proto = js_object->GetPrototype(); |
- if (!proto->IsJSReceiver()) return; |
- JSReceiver* receiver = JSReceiver::cast(proto); |
+ PrototypeIterator iter(GetIsolate(), js_object); |
+ if (!iter.GetCurrent()->IsJSReceiver()) return; |
+ JSReceiver* receiver = JSReceiver::cast(iter.GetCurrent()); |
if (receiver->map()->is_hidden_prototype()) { |
receiver->LookupOwn(name, result, search_hidden_prototypes); |
} |
@@ -6206,11 +6217,10 @@ void JSReceiver::LookupOwn( |
void JSReceiver::Lookup(Handle<Name> name, LookupResult* result) { |
DisallowHeapAllocation no_gc; |
// Ecma-262 3rd 8.6.2.4 |
- Handle<Object> null_value = GetIsolate()->factory()->null_value(); |
- for (Object* current = this; |
- current != *null_value; |
- current = JSObject::cast(current)->GetPrototype()) { |
- JSReceiver::cast(current)->LookupOwn(name, result, false); |
+ for (PrototypeIterator iter(GetIsolate(), this, |
+ PrototypeIterator::START_AT_RECEIVER); |
+ !iter.IsAtEnd(); iter.Advance()) { |
+ JSReceiver::cast(iter.GetCurrent())->LookupOwn(name, result, false); |
if (result->IsFound()) return; |
} |
result->NotFound(); |
@@ -6690,14 +6700,11 @@ void JSObject::DefineAccessor(Handle<JSObject> object, |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return; |
- ASSERT(proto->IsJSGlobalObject()); |
- DefineAccessor(Handle<JSObject>::cast(proto), |
- name, |
- getter, |
- setter, |
- attributes); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ DefineAccessor(Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), |
+ name, getter, setter, attributes); |
return; |
} |
@@ -6866,10 +6873,11 @@ MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object, |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return object; |
- ASSERT(proto->IsJSGlobalObject()); |
- return SetAccessor(Handle<JSObject>::cast(proto), info); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return object; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return SetAccessor( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), info); |
} |
// Make sure that the top context does not change when doing callbacks or |
@@ -6950,11 +6958,14 @@ MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object, |
// Make the lookup and include prototypes. |
uint32_t index = 0; |
if (name->AsArrayIndex(&index)) { |
- for (Handle<Object> obj = object; |
- !obj->IsNull(); |
- obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
- if (obj->IsJSObject() && JSObject::cast(*obj)->HasDictionaryElements()) { |
- JSObject* js_object = JSObject::cast(*obj); |
+ for (PrototypeIterator iter(isolate, object, |
+ PrototypeIterator::START_AT_RECEIVER); |
+ !iter.IsAtEnd(); iter.Advance()) { |
+ if (PrototypeIterator::GetCurrent(iter)->IsJSObject() && |
+ JSObject::cast(*PrototypeIterator::GetCurrent(iter)) |
+ ->HasDictionaryElements()) { |
+ JSObject* js_object = |
+ JSObject::cast(*PrototypeIterator::GetCurrent(iter)); |
SeededNumberDictionary* dictionary = js_object->element_dictionary(); |
int entry = dictionary->FindEntry(index); |
if (entry != SeededNumberDictionary::kNotFound) { |
@@ -6968,11 +6979,12 @@ MaybeHandle<Object> JSObject::GetAccessor(Handle<JSObject> object, |
} |
} |
} else { |
- for (Handle<Object> obj = object; |
- !obj->IsNull(); |
- obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
+ for (PrototypeIterator iter(isolate, object, |
+ PrototypeIterator::START_AT_RECEIVER); |
+ !iter.IsAtEnd(); iter.Advance()) { |
LookupResult result(isolate); |
- JSReceiver::cast(*obj)->LookupOwn(name, &result); |
+ JSReceiver::cast(*PrototypeIterator::GetCurrent(iter)) |
+ ->LookupOwn(name, &result); |
if (result.IsFound()) { |
if (result.IsReadOnly()) return isolate->factory()->undefined_value(); |
if (result.IsPropertyCallbacks()) { |
@@ -12249,10 +12261,11 @@ MaybeHandle<AccessorPair> JSObject::GetOwnElementAccessorPair( |
Handle<JSObject> object, |
uint32_t index) { |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); |
- if (proto->IsNull()) return MaybeHandle<AccessorPair>(); |
- ASSERT(proto->IsJSGlobalObject()); |
- return GetOwnElementAccessorPair(Handle<JSObject>::cast(proto), index); |
+ PrototypeIterator iter(object->GetIsolate(), object); |
+ if (iter.IsAtEnd()) return MaybeHandle<AccessorPair>(); |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return GetOwnElementAccessorPair( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); |
} |
// Check for lookup interceptor. |
@@ -12855,13 +12868,12 @@ MaybeHandle<Object> JSObject::SetElement(Handle<JSObject> object, |
} |
if (object->IsJSGlobalProxy()) { |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return value; |
- ASSERT(proto->IsJSGlobalObject()); |
- return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, |
- strict_mode, |
- check_prototype, |
- set_mode); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return value; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return SetElement( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index, |
+ value, attributes, strict_mode, check_prototype, set_mode); |
} |
// Don't allow element properties to be redefined for external arrays. |
@@ -13359,9 +13371,10 @@ MaybeHandle<Object> JSObject::GetElementWithInterceptor( |
Object); |
if (!result->IsTheHole()) return result; |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return isolate->factory()->undefined_value(); |
- return Object::GetElementWithReceiver(isolate, proto, receiver, index); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
+ return Object::GetElementWithReceiver( |
+ isolate, PrototypeIterator::GetCurrent(iter), receiver, index); |
} |
@@ -13722,10 +13735,11 @@ bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { |
if (object->IsJSGlobalProxy()) { |
HandleScope scope(isolate); |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsNull()) return false; |
- ASSERT(proto->IsJSGlobalObject()); |
- return HasRealElementProperty(Handle<JSObject>::cast(proto), index); |
+ PrototypeIterator iter(isolate, object); |
+ if (iter.IsAtEnd()) return false; |
+ ASSERT(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
+ return HasRealElementProperty( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), index); |
} |
return GetElementAttributeWithoutInterceptor( |