Convert function.length to API-style accessor.
authorulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Apr 2014 11:24:13 +0000 (11:24 +0000)
committerulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 24 Apr 2014 11:24:13 +0000 (11:24 +0000)
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
src/accessors.h
src/bootstrapper.cc
test/mjsunit/function-length-accessor.js [new file with mode: 0644]

index aa09e3b..a734096 100644 (file)
@@ -889,31 +889,57 @@ Handle<AccessorInfo> Accessors::FunctionPrototypeInfo(
 //
 
 
-Object* Accessors::FunctionGetLength(Isolate* isolate,
-                                     Object* object,
-                                     void*) {
-  JSFunction* function = FindInstanceOf<JSFunction>(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<v8::String> name,
+    const v8::PropertyCallbackInfo<v8::Value>& info) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
   HandleScope scope(isolate);
-  Handle<JSFunction> function_handle(function);
-  if (Compiler::EnsureCompiled(function_handle, KEEP_EXCEPTION)) {
-    return Smi::FromInt(function_handle->shared()->length());
+  Handle<Object> object = Utils::OpenHandle(*info.This());
+  MaybeHandle<JSFunction> maybe_function;
+
+  {
+    DisallowHeapAllocation no_allocation;
+    JSFunction* function = FindInstanceOf<JSFunction>(isolate, *object);
+    if (function != NULL) maybe_function = Handle<JSFunction>(function);
+  }
+
+  int length = 0;
+  Handle<JSFunction> 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<Object> result(Smi::FromInt(length), isolate);
+  info.GetReturnValue().Set(Utils::ToLocal(result));
 }
 
 
-const AccessorDescriptor Accessors::FunctionLength = {
-  FunctionGetLength,
-  ReadOnlySetAccessor,
-  0
-};
+void Accessors::FunctionLengthSetter(
+    v8::Local<v8::String> name,
+    v8::Local<v8::Value> val,
+    const v8::PropertyCallbackInfo<void>& info) {
+  // Do nothing.
+}
+
+
+Handle<AccessorInfo> Accessors::FunctionLengthInfo(
+      Isolate* isolate, PropertyAttributes attributes) {
+  return MakeAccessor(isolate,
+                      isolate->factory()->length_string(),
+                      &FunctionLengthGetter,
+                      &FunctionLengthSetter,
+                      attributes);
+}
 
 
 //
index fc9ccf4..226597a 100644 (file)
@@ -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)          \
index 5bfc3b7..94ad074 100644 (file)
@@ -388,15 +388,17 @@ void Genesis::SetFunctionInstanceDescriptor(
   int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
   Map::EnsureDescriptorSlack(map, size);
 
-  Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
   Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
   Handle<Foreign> args(factory()->NewForeign(&Accessors::FunctionArguments));
   Handle<Foreign> caller(factory()->NewForeign(&Accessors::FunctionCaller));
   PropertyAttributes attribs = static_cast<PropertyAttributes>(
       DONT_ENUM | DONT_DELETE | READ_ONLY);
 
+  Handle<AccessorInfo> length =
+      Accessors::FunctionLengthInfo(isolate(), attribs);
   {  // Add length.
-    CallbacksDescriptor d(factory()->length_string(), length, attribs);
+    CallbacksDescriptor d(Handle<Name>(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<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
   Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
   Handle<AccessorPair> arguments(factory()->NewAccessorPair());
   Handle<AccessorPair> caller(factory()->NewAccessorPair());
@@ -526,8 +527,11 @@ void Genesis::SetStrictFunctionInstanceDescriptor(
   PropertyAttributes ro_attribs =
       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
 
+  Handle<AccessorInfo> length =
+      Accessors::FunctionLengthInfo(isolate(), ro_attribs);
   {  // Add length.
-    CallbacksDescriptor d(factory()->length_string(), length, ro_attribs);
+    CallbacksDescriptor d(Handle<Name>(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 (file)
index 0000000..357ac3f
--- /dev/null
@@ -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()");