| 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(
|
|
|