From 72358c7fed41da735c811ec9d6a1d21d04dc6c20 Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Thu, 24 Apr 2014 11:24:13 +0000 Subject: [PATCH] Convert function.length to API-style accessor. TEST=mjsunit/function-length-accessor R=yangguo@chromium.org Review URL: https://codereview.chromium.org/257423009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20937 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/accessors.cc | 66 ++++++++++++++++++++++---------- src/accessors.h | 2 +- src/bootstrapper.cc | 12 ++++-- test/mjsunit/function-length-accessor.js | 35 +++++++++++++++++ 4 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 test/mjsunit/function-length-accessor.js diff --git a/src/accessors.cc b/src/accessors.cc index aa09e3b..a734096 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -889,31 +889,57 @@ Handle Accessors::FunctionPrototypeInfo( // -Object* Accessors::FunctionGetLength(Isolate* isolate, - Object* object, - void*) { - JSFunction* function = FindInstanceOf(isolate, object); - if (function == NULL) return Smi::FromInt(0); - // Check if already compiled. - if (function->shared()->is_compiled()) { - return Smi::FromInt(function->shared()->length()); - } - // If the function isn't compiled yet, the length is not computed correctly - // yet. Compile it now and return the right length. +void Accessors::FunctionLengthGetter( + v8::Local name, + const v8::PropertyCallbackInfo& info) { + i::Isolate* isolate = reinterpret_cast(info.GetIsolate()); HandleScope scope(isolate); - Handle function_handle(function); - if (Compiler::EnsureCompiled(function_handle, KEEP_EXCEPTION)) { - return Smi::FromInt(function_handle->shared()->length()); + Handle object = Utils::OpenHandle(*info.This()); + MaybeHandle maybe_function; + + { + DisallowHeapAllocation no_allocation; + JSFunction* function = FindInstanceOf(isolate, *object); + if (function != NULL) maybe_function = Handle(function); + } + + int length = 0; + Handle function; + if (maybe_function.ToHandle(&function)) { + if (function->shared()->is_compiled()) { + length = function->shared()->length(); + } else { + // If the function isn't compiled yet, the length is not computed + // correctly yet. Compile it now and return the right length. + if (Compiler::EnsureCompiled(function, KEEP_EXCEPTION)) { + length = function->shared()->length(); + } + if (isolate->has_pending_exception()) { + isolate->OptionalRescheduleException(false); + } + } } - return isolate->heap()->exception(); + Handle result(Smi::FromInt(length), isolate); + info.GetReturnValue().Set(Utils::ToLocal(result)); } -const AccessorDescriptor Accessors::FunctionLength = { - FunctionGetLength, - ReadOnlySetAccessor, - 0 -}; +void Accessors::FunctionLengthSetter( + v8::Local name, + v8::Local val, + const v8::PropertyCallbackInfo& info) { + // Do nothing. +} + + +Handle Accessors::FunctionLengthInfo( + Isolate* isolate, PropertyAttributes attributes) { + return MakeAccessor(isolate, + isolate->factory()->length_string(), + &FunctionLengthGetter, + &FunctionLengthSetter, + attributes); +} // diff --git a/src/accessors.h b/src/accessors.h index fc9ccf4..226597a 100644 --- a/src/accessors.h +++ b/src/accessors.h @@ -37,13 +37,13 @@ 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(FunctionLength) \ V(FunctionName) \ V(FunctionArguments) \ V(FunctionCaller) \ V(ArrayLength) #define ACCESSOR_INFO_LIST(V) \ + V(FunctionLength) \ V(FunctionPrototype) \ V(ScriptColumnOffset) \ V(ScriptCompilationType) \ diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 5bfc3b7..94ad074 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -388,15 +388,17 @@ void Genesis::SetFunctionInstanceDescriptor( int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; Map::EnsureDescriptorSlack(map, size); - Handle length(factory()->NewForeign(&Accessors::FunctionLength)); Handle name(factory()->NewForeign(&Accessors::FunctionName)); Handle args(factory()->NewForeign(&Accessors::FunctionArguments)); Handle caller(factory()->NewForeign(&Accessors::FunctionCaller)); PropertyAttributes attribs = static_cast( DONT_ENUM | DONT_DELETE | READ_ONLY); + Handle length = + Accessors::FunctionLengthInfo(isolate(), attribs); { // Add length. - CallbacksDescriptor d(factory()->length_string(), length, attribs); + CallbacksDescriptor d(Handle(Name::cast(length->name())), + length, attribs); map->AppendDescriptor(&d); } { // Add name. @@ -517,7 +519,6 @@ void Genesis::SetStrictFunctionInstanceDescriptor( int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5; Map::EnsureDescriptorSlack(map, size); - Handle length(factory()->NewForeign(&Accessors::FunctionLength)); Handle name(factory()->NewForeign(&Accessors::FunctionName)); Handle arguments(factory()->NewAccessorPair()); Handle caller(factory()->NewAccessorPair()); @@ -526,8 +527,11 @@ void Genesis::SetStrictFunctionInstanceDescriptor( PropertyAttributes ro_attribs = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); + Handle length = + Accessors::FunctionLengthInfo(isolate(), ro_attribs); { // Add length. - CallbacksDescriptor d(factory()->length_string(), length, ro_attribs); + CallbacksDescriptor d(Handle(Name::cast(length->name())), + length, ro_attribs); map->AppendDescriptor(&d); } { // Add name. diff --git a/test/mjsunit/function-length-accessor.js b/test/mjsunit/function-length-accessor.js new file mode 100644 index 0000000..357ac3f --- /dev/null +++ b/test/mjsunit/function-length-accessor.js @@ -0,0 +1,35 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony-scoping + +function foo(a, b, c, d) { + "use strict" + const x = 10; + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + // long comment to trigger lazy compilation. + x = 20; // This will trigger compile error with harmony scoping. +} + +assertThrows("foo.length()"); -- 2.7.4