Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index d980d327aa89640d2b44cbef8e08b58be0eb3257..559a62199e06a6c294cdd41fbdbe05f6ed20ab15 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2012,10 +2012,10 @@ RUNTIME_FUNCTION(Runtime_IsExtensible) { |
ASSERT(args.length() == 1); |
CONVERT_ARG_CHECKED(JSObject, obj, 0); |
if (obj->IsJSGlobalProxy()) { |
- Object* proto = obj->GetPrototype(); |
- if (proto->IsNull()) return isolate->heap()->false_value(); |
- ASSERT(proto->IsJSGlobalObject()); |
- obj = JSObject::cast(proto); |
+ PrototypeIterator iter(isolate, obj); |
+ if (iter.IsAtEnd()) return isolate->heap()->false_value(); |
+ ASSERT(iter.GetCurrent()->IsJSGlobalObject()); |
+ obj = JSObject::cast(iter.GetCurrent()); |
} |
return isolate->heap()->ToBoolean(obj->map()->is_extensible()); |
} |
@@ -4952,7 +4952,8 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { |
if (js_object->IsJSGlobalProxy()) { |
// Since the result is a property, the prototype will exist so |
// we don't have to check for null. |
- js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); |
+ PrototypeIterator iter(isolate, js_object); |
+ js_object = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
} |
if (attr != lookup.GetAttributes() || |
@@ -5473,12 +5474,16 @@ static Object* HasOwnPropertyImplementation(Isolate* isolate, |
// Handle hidden prototypes. If there's a hidden prototype above this thing |
// then we have to check it for properties, because they are supposed to |
// look like they are on this object. |
- Handle<Object> proto(object->GetPrototype(), isolate); |
- if (proto->IsJSObject() && |
- Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) { |
- return HasOwnPropertyImplementation(isolate, |
- Handle<JSObject>::cast(proto), |
- key); |
+ PrototypeIterator iter(isolate, object); |
+ if (!iter.IsAtEnd() && |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)) |
+ ->map() |
+ ->is_hidden_prototype()) { |
+ // TODO(verwaest): The recursion is not necessary for keys that are array |
+ // indicies. Removing this. |
+ return HasOwnPropertyImplementation( |
+ isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), |
+ key); |
} |
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
return isolate->heap()->false_value(); |
@@ -5616,11 +5621,9 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { |
// is prototype for. |
static int OwnPrototypeChainLength(JSObject* obj) { |
int count = 1; |
- Object* proto = obj->GetPrototype(); |
- while (proto->IsJSObject() && |
- JSObject::cast(proto)->map()->is_hidden_prototype()) { |
+ for (PrototypeIterator iter(obj->GetIsolate(), obj); |
+ !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { |
count++; |
- proto = JSObject::cast(proto)->GetPrototype(); |
} |
return count; |
} |
@@ -5650,7 +5653,8 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { |
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
return *isolate->factory()->NewJSArray(0); |
} |
- obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype())); |
+ PrototypeIterator iter(isolate, obj); |
+ obj = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
} |
// Find the number of objects making up this. |
@@ -5659,22 +5663,26 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { |
// Find the number of own properties for each of the objects. |
ScopedVector<int> own_property_count(length); |
int total_property_count = 0; |
- Handle<JSObject> jsproto = obj; |
- for (int i = 0; i < length; i++) { |
- // Only collect names if access is permitted. |
- if (jsproto->IsAccessCheckNeeded() && |
- !isolate->MayNamedAccess( |
- jsproto, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { |
- isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS); |
- RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
- return *isolate->factory()->NewJSArray(0); |
- } |
- int n; |
- n = jsproto->NumberOfOwnProperties(filter); |
- own_property_count[i] = n; |
- total_property_count += n; |
- if (i < length - 1) { |
- jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); |
+ { |
+ PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
+ for (int i = 0; i < length; i++) { |
+ ASSERT(!iter.IsAtEnd()); |
+ Handle<JSObject> jsproto = |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
+ // Only collect names if access is permitted. |
+ if (jsproto->IsAccessCheckNeeded() && |
+ !isolate->MayNamedAccess(jsproto, |
+ isolate->factory()->undefined_value(), |
+ v8::ACCESS_KEYS)) { |
+ isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS); |
+ RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
+ return *isolate->factory()->NewJSArray(0); |
+ } |
+ int n; |
+ n = jsproto->NumberOfOwnProperties(filter); |
+ own_property_count[i] = n; |
+ total_property_count += n; |
+ iter.Advance(); |
} |
} |
@@ -5683,39 +5691,41 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { |
isolate->factory()->NewFixedArray(total_property_count); |
// Get the property names. |
- jsproto = obj; |
int next_copy_index = 0; |
int hidden_strings = 0; |
- for (int i = 0; i < length; i++) { |
- jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); |
- if (i > 0) { |
- // Names from hidden prototypes may already have been added |
- // for inherited function template instances. Count the duplicates |
- // and stub them out; the final copy pass at the end ignores holes. |
- for (int j = next_copy_index; |
- j < next_copy_index + own_property_count[i]; |
- j++) { |
- Object* name_from_hidden_proto = names->get(j); |
- for (int k = 0; k < next_copy_index; k++) { |
- if (names->get(k) != isolate->heap()->hidden_string()) { |
- Object* name = names->get(k); |
- if (name_from_hidden_proto == name) { |
- names->set(j, isolate->heap()->hidden_string()); |
- hidden_strings++; |
- break; |
+ { |
+ PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
+ for (int i = 0; i < length; i++) { |
+ ASSERT(!iter.IsAtEnd()); |
+ Handle<JSObject> jsproto = |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
+ jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); |
+ if (i > 0) { |
+ // Names from hidden prototypes may already have been added |
+ // for inherited function template instances. Count the duplicates |
+ // and stub them out; the final copy pass at the end ignores holes. |
+ for (int j = next_copy_index; |
+ j < next_copy_index + own_property_count[i]; j++) { |
+ Object* name_from_hidden_proto = names->get(j); |
+ for (int k = 0; k < next_copy_index; k++) { |
+ if (names->get(k) != isolate->heap()->hidden_string()) { |
+ Object* name = names->get(k); |
+ if (name_from_hidden_proto == name) { |
+ names->set(j, isolate->heap()->hidden_string()); |
+ hidden_strings++; |
+ break; |
+ } |
} |
} |
} |
} |
- } |
- next_copy_index += own_property_count[i]; |
+ next_copy_index += own_property_count[i]; |
- // Hidden properties only show up if the filter does not skip strings. |
- if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) { |
- hidden_strings++; |
- } |
- if (i < length - 1) { |
- jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); |
+ // Hidden properties only show up if the filter does not skip strings. |
+ if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) { |
+ hidden_strings++; |
+ } |
+ iter.Advance(); |
} |
} |
@@ -5826,10 +5836,10 @@ RUNTIME_FUNCTION(Runtime_OwnKeys) { |
return *isolate->factory()->NewJSArray(0); |
} |
- Handle<Object> proto(object->GetPrototype(), isolate); |
+ PrototypeIterator iter(isolate, object); |
// If proxy is detached we simply return an empty array. |
- if (proto->IsNull()) return *isolate->factory()->NewJSArray(0); |
- object = Handle<JSObject>::cast(proto); |
+ if (iter.IsAtEnd()) return *isolate->factory()->NewJSArray(0); |
+ object = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
} |
Handle<FixedArray> contents; |
@@ -10103,11 +10113,13 @@ static void CollectElementIndices(Handle<JSObject> object, |
} |
} |
- Handle<Object> prototype(object->GetPrototype(), isolate); |
- if (prototype->IsJSObject()) { |
+ PrototypeIterator iter(isolate, object); |
+ if (!iter.IsAtEnd()) { |
// The prototype will usually have no inherited element indices, |
// but we have to check. |
- CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices); |
+ CollectElementIndices( |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), range, |
+ indices); |
} |
} |
@@ -10729,8 +10741,11 @@ RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) { |
int length = OwnPrototypeChainLength(*obj); |
// Try own lookup on each of the objects. |
- Handle<JSObject> jsproto = obj; |
+ PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
for (int i = 0; i < length; i++) { |
+ ASSERT(!iter.IsAtEnd()); |
+ Handle<JSObject> jsproto = |
+ Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
LookupResult result(isolate); |
jsproto->LookupOwn(name, &result); |
if (result.IsFound()) { |
@@ -10765,9 +10780,7 @@ RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) { |
return *isolate->factory()->NewJSArrayWithElements(details); |
} |
- if (i < length - 1) { |
- jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); |
- } |
+ iter.Advance(); |
} |
return isolate->heap()->undefined_value(); |