Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index d980d327aa89640d2b44cbef8e08b58be0eb3257..1069858805e41cf2e76bbe92eecf60a47015d3e4 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,14 @@ 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()) { |
| + return HasOwnPropertyImplementation( |
|
Toon Verwaest
2014/07/16 15:41:01
The recursion isn't necessary for keys that are ar
jochen (gone - plz use gerrit)
2014/07/17 06:58:02
Done.
|
| + isolate, Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), |
| + key); |
| } |
| RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
| return isolate->heap()->false_value(); |
| @@ -5616,11 +5619,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 +5651,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 +5661,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 +5689,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 +5834,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 +10111,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 +10739,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 +10778,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(); |