| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 3cb6fe20a20b752b42e042f33585459df27ef8aa..b1ade5e0ce491412912a5d445ea425021cf67281 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -34,6 +34,7 @@
|
| #include "src/misc-intrinsics.h"
|
| #include "src/parser.h"
|
| #include "src/platform.h"
|
| +#include "src/prototype-iterator.h"
|
| #include "src/runtime.h"
|
| #include "src/runtime-profiler.h"
|
| #include "src/scopeinfo.h"
|
| @@ -1809,31 +1810,30 @@ RUNTIME_FUNCTION(Runtime_GetPrototype) {
|
| CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
|
| // We don't expect access checks to be needed on JSProxy objects.
|
| ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
|
| + PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NON_HIDDEN> iter(
|
| + isolate, obj);
|
| do {
|
| - if (obj->IsAccessCheckNeeded() &&
|
| - !isolate->MayNamedAccess(Handle<JSObject>::cast(obj),
|
| + if (iter.GetCurrent()->IsAccessCheckNeeded() &&
|
| + !isolate->MayNamedAccess(Handle<JSObject>::cast(iter.GetCurrent()),
|
| isolate->factory()->proto_string(),
|
| v8::ACCESS_GET)) {
|
| - isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
|
| - v8::ACCESS_GET);
|
| + isolate->ReportFailedAccessCheck(
|
| + Handle<JSObject>::cast(iter.GetCurrent()), v8::ACCESS_GET);
|
| RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| return isolate->heap()->undefined_value();
|
| }
|
| - obj = Object::GetPrototype(isolate, obj);
|
| - } while (obj->IsJSObject() &&
|
| - JSObject::cast(*obj)->map()->is_hidden_prototype());
|
| - return *obj;
|
| + iter.Advance();
|
| + } while (!iter.IsAtEnd());
|
| + return *iter.GetCurrent();
|
| }
|
|
|
|
|
| static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
|
| Isolate* isolate, Handle<Object> receiver) {
|
| - Handle<Object> current = Object::GetPrototype(isolate, receiver);
|
| - while (current->IsJSObject() &&
|
| - JSObject::cast(*current)->map()->is_hidden_prototype()) {
|
| - current = Object::GetPrototype(isolate, current);
|
| - }
|
| - return current;
|
| + PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NON_HIDDEN> iter(
|
| + isolate, receiver);
|
| + while (!iter.IsAtEnd()) iter.Advance();
|
| + return iter.GetCurrent();
|
| }
|
|
|
|
|
| @@ -1878,12 +1878,11 @@ RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
|
| // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
|
| CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
|
| CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
|
| - while (true) {
|
| - Handle<Object> prototype = Object::GetPrototype(isolate, V);
|
| - if (prototype->IsNull()) return isolate->heap()->false_value();
|
| - if (*O == *prototype) return isolate->heap()->true_value();
|
| - V = prototype;
|
| - }
|
| + PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_GIVEN_OBJECT> iter(
|
| + isolate, V, O);
|
| + while (!iter.IsAtEnd()) iter.Advance();
|
| + if (iter.GetCurrent()->IsNull()) return isolate->heap()->false_value();
|
| + return isolate->heap()->true_value();
|
| }
|
|
|
|
|
| @@ -2006,7 +2005,7 @@ RUNTIME_FUNCTION(Runtime_IsExtensible) {
|
| ASSERT(args.length() == 1);
|
| CONVERT_ARG_CHECKED(JSObject, obj, 0);
|
| if (obj->IsJSGlobalProxy()) {
|
| - Object* proto = obj->GetPrototype();
|
| + Object* proto = SAFE_GET_PROTOTYPE_FAST(obj);
|
| if (proto->IsNull()) return isolate->heap()->false_value();
|
| ASSERT(proto->IsJSGlobalObject());
|
| obj = JSObject::cast(proto);
|
| @@ -4833,7 +4832,7 @@ MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
|
|
|
| Handle<Object> result;
|
| if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
|
| - Handle<Object> proto(object->GetPrototype(isolate), isolate);
|
| + Handle<Object> proto(SAFE_GET_PROTOTYPE(isolate, *object), isolate);
|
| return Object::GetElement(isolate, proto, index);
|
| } else {
|
| return Object::GetElement(isolate, object, index);
|
| @@ -5097,7 +5096,8 @@ RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) {
|
| 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()));
|
| + js_object =
|
| + Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE_FAST(*js_object)));
|
| }
|
|
|
| if (attr != lookup.GetAttributes() ||
|
| @@ -5572,7 +5572,7 @@ 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);
|
| + Handle<Object> proto(SAFE_GET_PROTOTYPE_FAST(*object), isolate);
|
| if (proto->IsJSObject() &&
|
| Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
|
| return HasOwnPropertyImplementation(isolate,
|
| @@ -5714,12 +5714,10 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
|
| // prototype object is hidden it is to be viewed as part of the the object it
|
| // 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()) {
|
| - count++;
|
| - proto = JSObject::cast(proto)->GetPrototype();
|
| + int count = 0;
|
| + for (PrototypeIterator<STORE_AS_POINTER, MAP_BASED_WALK, END_AT_NON_HIDDEN>
|
| + iter(obj); !iter.IsAtEnd(); iter.Advance()) {
|
| + ++count;
|
| }
|
| return count;
|
| }
|
| @@ -5749,7 +5747,7 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| return *isolate->factory()->NewJSArray(0);
|
| }
|
| - obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
|
| + obj = Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE_FAST(*obj)));
|
| }
|
|
|
| // Find the number of objects making up this.
|
| @@ -5773,7 +5771,8 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| own_property_count[i] = n;
|
| total_property_count += n;
|
| if (i < length - 1) {
|
| - jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
| + jsproto =
|
| + Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE_FAST(*jsproto)));
|
| }
|
| }
|
|
|
| @@ -5814,7 +5813,8 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| hidden_strings++;
|
| }
|
| if (i < length - 1) {
|
| - jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
| + jsproto =
|
| + Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE_FAST(*jsproto)));
|
| }
|
| }
|
|
|
| @@ -5925,7 +5925,7 @@ RUNTIME_FUNCTION(Runtime_OwnKeys) {
|
| return *isolate->factory()->NewJSArray(0);
|
| }
|
|
|
| - Handle<Object> proto(object->GetPrototype(), isolate);
|
| + Handle<Object> proto(SAFE_GET_PROTOTYPE_FAST(*object), isolate);
|
| // If proxy is detached we simply return an empty array.
|
| if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
|
| object = Handle<JSObject>::cast(proto);
|
| @@ -10212,7 +10212,7 @@ static void CollectElementIndices(Handle<JSObject> object,
|
| }
|
| }
|
|
|
| - Handle<Object> prototype(object->GetPrototype(), isolate);
|
| + Handle<Object> prototype(SAFE_GET_PROTOTYPE_FAST(*object), isolate);
|
| if (prototype->IsJSObject()) {
|
| // The prototype will usually have no inherited element indices,
|
| // but we have to check.
|
| @@ -10645,15 +10645,15 @@ RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
|
| CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
|
| if (array->elements()->IsDictionary()) {
|
| Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
|
| - for (Handle<Object> p = array;
|
| - !p->IsNull();
|
| - p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
|
| - if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
|
| + for (PrototypeIterator<STORE_AS_HANDLE, TYPE_BASED_WALK, END_AT_NULL_VALUE>
|
| + iter(isolate, array); !iter.IsAtEnd(); iter.Advance()) {
|
| + if (iter.GetCurrent()->IsJSProxy() ||
|
| + JSObject::cast(*iter.GetCurrent())->HasIndexedInterceptor()) {
|
| // Bail out if we find a proxy or interceptor, likely not worth
|
| // collecting keys in that case.
|
| return *isolate->factory()->NewNumberFromUint(length);
|
| }
|
| - Handle<JSObject> current = Handle<JSObject>::cast(p);
|
| + Handle<JSObject> current = Handle<JSObject>::cast(iter.GetCurrent());
|
| Handle<FixedArray> current_keys =
|
| isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
|
| current->GetOwnElementKeys(*current_keys, NONE);
|
| @@ -10872,7 +10872,8 @@ RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
|
| return *isolate->factory()->NewJSArrayWithElements(details);
|
| }
|
| if (i < length - 1) {
|
| - jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
|
| + jsproto =
|
| + Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE_FAST(*jsproto)));
|
| }
|
| }
|
|
|
| @@ -12820,7 +12821,8 @@ static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
|
| // Skip the global proxy as it has no properties and always delegates to the
|
| // real global object.
|
| if (result->IsJSGlobalProxy()) {
|
| - result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
|
| + result =
|
| + Handle<JSObject>(JSObject::cast(SAFE_GET_PROTOTYPE(isolate, *result)));
|
| }
|
|
|
| // Clear the oneshot breakpoints so that the debugger does not step further.
|
| @@ -12996,17 +12998,13 @@ static int DebugReferencedBy(HeapIterator* iterator,
|
| // Check instance filter if supplied. This is normally used to avoid
|
| // references from mirror objects (see Runtime_IsInPrototypeChain).
|
| if (!instance_filter->IsUndefined()) {
|
| - Object* V = obj;
|
| - while (true) {
|
| - Object* prototype = V->GetPrototype(isolate);
|
| - if (prototype->IsNull()) {
|
| - break;
|
| - }
|
| - if (instance_filter == prototype) {
|
| - obj = NULL; // Don't add this object.
|
| + for (PrototypeIterator<STORE_AS_POINTER, TYPE_BASED_WALK,
|
| + END_AT_NULL_VALUE> iter(isolate, obj);
|
| + !iter.IsAtEnd(); iter.Advance()) {
|
| + if (instance_filter == iter.GetCurrent()) {
|
| + obj = NULL;
|
| break;
|
| }
|
| - V = prototype;
|
| }
|
| }
|
|
|
|
|