[turbofan] Make %Arguments composable with inlining.
authormstarzinger <mstarzinger@chromium.org>
Wed, 9 Sep 2015 14:14:01 +0000 (07:14 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 9 Sep 2015 14:14:18 +0000 (14:14 +0000)
This makes the C++ fallback implementations for the two intrinsics,
%Arguments and %ArgumentsLength composable with respect to inlining.
Using deoptimization information gives us accurate data here.

R=bmeurer@chromium.org
TEST=mjsunit/regress/regress-4374
BUG=v8:4374
LOG=n

Review URL: https://codereview.chromium.org/1328363002

Cr-Commit-Position: refs/heads/master@{#30654}

src/compiler/linkage.cc
src/runtime/runtime-classes.cc
src/runtime/runtime-function.cc
src/runtime/runtime-scopes.cc
src/runtime/runtime.h
test/mjsunit/regress/regress-4374.js [new file with mode: 0644]

index e384e82..6b3c077 100644 (file)
@@ -238,6 +238,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
     case Runtime::kTraceExit:
       return 0;
     case Runtime::kInlineArguments:
+    case Runtime::kInlineArgumentsLength:
     case Runtime::kInlineCall:
     case Runtime::kInlineCallFunction:
     case Runtime::kInlineDefaultConstructorCallSuper:
index a66fe39..6678cdd 100644 (file)
@@ -527,23 +527,23 @@ RUNTIME_FUNCTION(Runtime_DefaultConstructorCallSuper) {
       isolate, super_constructor,
       Runtime::GetPrototype(isolate, actual_constructor));
 
-  // Find the frame that holds the actual arguments passed to the function.
-  it.AdvanceToArgumentsFrame();
-  JavaScriptFrame* frame = it.frame();
+  // Determine the actual arguments passed to the function.
+  int argument_count = 0;
+  base::SmartArrayPointer<Handle<Object>> arguments =
+      Runtime::GetCallerArguments(isolate, 0, &argument_count);
 
   // Prepare the array containing all passed arguments.
-  int argument_count = frame->GetArgumentsLength();
   Handle<FixedArray> elements =
       isolate->factory()->NewUninitializedFixedArray(argument_count);
   for (int i = 0; i < argument_count; ++i) {
-    elements->set(i, frame->GetParameter(i));
+    elements->set(i, *arguments[i]);
   }
-  Handle<JSArray> arguments = isolate->factory()->NewJSArrayWithElements(
+  Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(
       elements, FAST_ELEMENTS, argument_count);
 
   // Call %reflect_construct(<super>, <args>, <new.target>) now.
   Handle<JSFunction> reflect = isolate->reflect_construct();
-  Handle<Object> argv[] = {super_constructor, arguments, original_constructor};
+  Handle<Object> argv[] = {super_constructor, array, original_constructor};
   Handle<Object> result;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, result,
index 9b33544..6666ba4 100644 (file)
@@ -313,7 +313,7 @@ RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) {
 // Find the arguments of the JavaScript function invocation that called
 // into C++ code. Collect these in a newly allocated array of handles (possibly
 // prefixed by a number of empty handles).
-static base::SmartArrayPointer<Handle<Object> > GetCallerArguments(
+base::SmartArrayPointer<Handle<Object>> Runtime::GetCallerArguments(
     Isolate* isolate, int prefix_argc, int* total_argc) {
   // Find frame containing arguments passed to the caller.
   JavaScriptFrameIterator it(isolate);
@@ -385,8 +385,8 @@ RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
   bound_function->shared()->set_inferred_name(isolate->heap()->empty_string());
   // Get all arguments of calling function (Function.prototype.bind).
   int argc = 0;
-  base::SmartArrayPointer<Handle<Object> > arguments =
-      GetCallerArguments(isolate, 0, &argc);
+  base::SmartArrayPointer<Handle<Object>> arguments =
+      Runtime::GetCallerArguments(isolate, 0, &argc);
   // Don't count the this-arg.
   if (argc > 0) {
     RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
@@ -487,8 +487,8 @@ RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
 
   int total_argc = 0;
-  base::SmartArrayPointer<Handle<Object> > param_data =
-      GetCallerArguments(isolate, bound_argc, &total_argc);
+  base::SmartArrayPointer<Handle<Object>> param_data =
+      Runtime::GetCallerArguments(isolate, bound_argc, &total_argc);
   for (int i = 0; i < bound_argc; i++) {
     param_data[i] = Handle<Object>(
         bound_args->get(JSFunction::kBoundArgumentsStartIndex + i), isolate);
index 3d9b149..6b7db02 100644 (file)
@@ -1046,35 +1046,32 @@ RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
 
 
 RUNTIME_FUNCTION(Runtime_ArgumentsLength) {
-  SealHandleScope shs(isolate);
+  HandleScope scope(isolate);
   DCHECK(args.length() == 0);
-  JavaScriptFrameIterator it(isolate);
-  JavaScriptFrame* frame = it.frame();
-  return Smi::FromInt(frame->GetArgumentsLength());
+  int argument_count = 0;
+  Runtime::GetCallerArguments(isolate, 0, &argument_count);
+  return Smi::FromInt(argument_count);
 }
 
 
 RUNTIME_FUNCTION(Runtime_Arguments) {
-  SealHandleScope shs(isolate);
+  HandleScope scope(isolate);
   DCHECK(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
 
-  // Compute the frame holding the arguments.
-  JavaScriptFrameIterator it(isolate);
-  it.AdvanceToArgumentsFrame();
-  JavaScriptFrame* frame = it.frame();
-
-  // Get the actual number of provided arguments.
-  const uint32_t n = frame->ComputeParametersCount();
+  // Determine the actual arguments passed to the function.
+  int argument_count_signed = 0;
+  base::SmartArrayPointer<Handle<Object>> arguments =
+      Runtime::GetCallerArguments(isolate, 0, &argument_count_signed);
+  const uint32_t argument_count = argument_count_signed;
 
   // Try to convert the key to an index. If successful and within
   // index return the the argument from the frame.
   uint32_t index = 0;
-  if (raw_key->ToArrayIndex(&index) && index < n) {
-    return frame->GetParameter(index);
+  if (raw_key->ToArrayIndex(&index) && index < argument_count) {
+    return *arguments[index];
   }
 
-  HandleScope scope(isolate);
   if (raw_key->IsSymbol()) {
     Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
     if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) {
@@ -1097,8 +1094,8 @@ RUNTIME_FUNCTION(Runtime_Arguments) {
 
   // Try to convert the string key into an array index.
   if (key->AsArrayIndex(&index)) {
-    if (index < n) {
-      return frame->GetParameter(index);
+    if (index < argument_count) {
+      return *arguments[index];
     } else {
       Handle<Object> initial_prototype(isolate->initial_object_prototype());
       Handle<Object> result;
@@ -1111,10 +1108,11 @@ RUNTIME_FUNCTION(Runtime_Arguments) {
 
   // Handle special arguments properties.
   if (String::Equals(isolate->factory()->length_string(), key)) {
-    return Smi::FromInt(n);
+    return Smi::FromInt(argument_count);
   }
   if (String::Equals(isolate->factory()->callee_string(), key)) {
-    JSFunction* function = frame->function();
+    JavaScriptFrameIterator it(isolate);
+    JSFunction* function = it.frame()->function();
     if (is_strict(function->shared()->language_mode())) {
       THROW_NEW_ERROR_RETURN_FAILURE(
           isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
index 990fb64..aff18f6 100644 (file)
@@ -1176,6 +1176,7 @@ class Runtime : public AllStatic {
       Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
       LanguageMode language_mode);
 
+  // TODO(mstarzinger): Remove this once %DefaultConstructorCallSuper is gone.
   MUST_USE_RESULT static MaybeHandle<Object> GetPrototype(
       Isolate* isolate, Handle<Object> object);
 
@@ -1206,6 +1207,15 @@ class Runtime : public AllStatic {
   static MaybeHandle<JSArray> GetInternalProperties(Isolate* isolate,
                                                     Handle<Object>);
 
+  // Find the arguments of the JavaScript function invocation that called
+  // into C++ code. Collect these in a newly allocated array of handles
+  // (possibly prefixed by a number of empty handles).
+  // TODO(mstarzinger): Temporary workaround until this is only used by the
+  // %_Arguments and %_ArgumentsLength intrinsics. Make this function local to
+  // runtime-scopes.cc then.
+  static base::SmartArrayPointer<Handle<Object>> GetCallerArguments(
+      Isolate* isolate, int prefix_argc, int* total_argc);
+
   static bool AtomicIsLockFree(uint32_t size);
 };
 
diff --git a/test/mjsunit/regress/regress-4374.js b/test/mjsunit/regress/regress-4374.js
new file mode 100644 (file)
index 0000000..bbdcfb9
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 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: --allow-natives-syntax --context-specialization
+// Flags: --turbo-filter=f --turbo-inlining
+
+var f = (function() {
+  var max = Math.max;
+  return function f() { return max(0, -1); };
+})();
+
+assertEquals(0, f());
+%OptimizeFunctionOnNextCall(f);
+assertEquals(0, f());