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