From 17f88aafc3306a6959f5cd3e48e299fbf27abfcf Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Mon, 28 Apr 2014 14:59:29 +0000 Subject: [PATCH] Convert array.length to API-style accessor. BUG= R=yangguo@chromium.org Review URL: https://codereview.chromium.org/259773009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@21023 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/accessors.cc | 92 +++++++++++++++++++++++++++------------------ src/accessors.h | 3 +- src/bootstrapper.cc | 13 ++++--- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/accessors.cc b/src/accessors.cc index 277b4ceef1..d932ffd338 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -174,15 +174,6 @@ bool Accessors::IsJSObjectFieldAccessor(Handle type, // -Object* Accessors::ArrayGetLength(Isolate* isolate, - Object* object, - void*) { - // Traverse the prototype chain until we reach an array. - JSArray* holder = FindInstanceOf(isolate, object); - return holder == NULL ? Smi::FromInt(0) : holder->length(); -} - - // The helper function will 'flatten' Number objects. Handle Accessors::FlattenNumber(Isolate* isolate, Handle value) { @@ -199,55 +190,84 @@ Handle Accessors::FlattenNumber(Isolate* isolate, } -Object* Accessors::ArraySetLength(Isolate* isolate, - JSObject* object_raw, - Object* value_raw, - void*) { +void Accessors::ArrayLengthGetter( + v8::Local name, + const v8::PropertyCallbackInfo& info) { + i::Isolate* isolate = reinterpret_cast(info.GetIsolate()); + DisallowHeapAllocation no_allocation; HandleScope scope(isolate); - Handle object(object_raw, isolate); - Handle value(value_raw, isolate); + Object* object = *Utils::OpenHandle(*info.This()); + // Traverse the prototype chain until we reach an array. + JSArray* holder = FindInstanceOf(isolate, object); + Object* result; + if (holder != NULL) { + result = holder->length(); + } else { + result = Smi::FromInt(0); + } + info.GetReturnValue().Set(Utils::ToLocal(Handle(result, isolate))); +} + +void Accessors::ArrayLengthSetter( + v8::Local name, + v8::Local val, + const v8::PropertyCallbackInfo& info) { + i::Isolate* isolate = reinterpret_cast(info.GetIsolate()); + HandleScope scope(isolate); + Handle object = Handle::cast( + Utils::OpenHandle(*info.This())); + Handle value = Utils::OpenHandle(*val); // This means one of the object's prototypes is a JSArray and the // object does not have a 'length' property. Calling SetProperty // causes an infinite loop. if (!object->IsJSArray()) { - Handle result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, + MaybeHandle maybe_result = JSObject::SetLocalPropertyIgnoreAttributes( - object, isolate->factory()->length_string(), value, NONE)); - return *result; + object, isolate->factory()->length_string(), value, NONE); + maybe_result.ToHandleChecked(); + return; } value = FlattenNumber(isolate, value); Handle array_handle = Handle::cast(object); - + MaybeHandle maybe; Handle uint32_v; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, uint32_v, Execution::ToUint32(isolate, value)); + maybe = Execution::ToUint32(isolate, value); + if (!maybe.ToHandle(&uint32_v)) { + isolate->OptionalRescheduleException(false); + return; + } Handle number_v; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, number_v, Execution::ToNumber(isolate, value)); + maybe = Execution::ToNumber(isolate, value); + if (!maybe.ToHandle(&number_v)) { + isolate->OptionalRescheduleException(false); + return; + } if (uint32_v->Number() == number_v->Number()) { - Handle result; - ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, - JSArray::SetElementsLength(array_handle, uint32_v)); - return *result; + MaybeHandle result; + result = JSArray::SetElementsLength(array_handle, uint32_v); + USE(result); + return; } - return isolate->Throw( + + isolate->ScheduleThrow( *isolate->factory()->NewRangeError("invalid_array_length", HandleVector(NULL, 0))); } -const AccessorDescriptor Accessors::ArrayLength = { - ArrayGetLength, - ArraySetLength, - 0 -}; +Handle Accessors::ArrayLengthInfo( + Isolate* isolate, PropertyAttributes attributes) { + return MakeAccessor(isolate, + isolate->factory()->length_string(), + &ArrayLengthGetter, + &ArrayLengthSetter, + attributes); +} + // diff --git a/src/accessors.h b/src/accessors.h index ed092057be..866847a0d9 100644 --- a/src/accessors.h +++ b/src/accessors.h @@ -37,9 +37,10 @@ namespace internal { // The list of accessor descriptors. This is a second-order macro // taking a macro to be applied to all accessor descriptor names. #define ACCESSOR_DESCRIPTOR_LIST(V) \ - V(ArrayLength) + #define ACCESSOR_INFO_LIST(V) \ + V(ArrayLength) \ V(FunctionArguments) \ V(FunctionCaller) \ V(FunctionName) \ diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 5101b87f81..33cdfcdd8e 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -863,12 +863,15 @@ void Genesis::InitializeGlobal(Handle inner_global, ASSERT(initial_map->elements_kind() == GetInitialFastElementsKind()); Map::EnsureDescriptorSlack(initial_map, 1); - Handle array_length(factory->NewForeign(&Accessors::ArrayLength)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE); + Handle array_length = + Accessors::ArrayLengthInfo(isolate, attribs); { // Add length. - CallbacksDescriptor d(factory->length_string(), array_length, attribs); + CallbacksDescriptor d( + Handle(Name::cast(array_length->name())), + array_length, attribs); array_function->initial_map()->AppendDescriptor(&d); } @@ -1614,14 +1617,14 @@ Handle Genesis::InstallInternalArray( // Make "length" magic on instances. Map::EnsureDescriptorSlack(initial_map, 1); - Handle array_length(factory()->NewForeign( - &Accessors::ArrayLength)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE); + Handle array_length = + Accessors::ArrayLengthInfo(isolate(), attribs); { // Add length. CallbacksDescriptor d( - factory()->length_string(), array_length, attribs); + Handle(Name::cast(array_length->name())), array_length, attribs); array_function->initial_map()->AppendDescriptor(&d); }