Reviewers: Sven Panne,

Description:
Allow inlining of functions containing %_Arguments.

[email protected]
TEST=mjsunit/compiler/inline-arguments

Please review this at https://codereview.chromium.org/356773002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+52, -23 lines):
  M src/ast.cc
  M src/hydrogen.cc
  M test/mjsunit/compiler/inline-arguments.js


Index: src/ast.cc
diff --git a/src/ast.cc b/src/ast.cc
index bf16b9c076b8786ce1cb4a2eecf4963f79d70fe9..8d25bacfa6dda99b2ea7decf71e582c2bc6c1caa 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -1116,11 +1116,6 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { // Don't try to inline JS runtime calls because we don't (currently) even
     // optimize them.
     add_flag(kDontInline);
-  } else if (node->function()->intrinsic_type == Runtime::INLINE &&
-             node->raw_name()->IsOneByteEqualTo("_Arguments")) {
- // Don't inline the %_Arguments because it's implementation will not work.
-    // There is no stack frame to get them from.
-    add_flag(kDontInline);
   }
 }

Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index d447bbc9f76cbcb6d16990ed22233d11b154e1d1..89f61decba5c833f9bafc5e94a829fc3b2216ee1 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7738,19 +7738,19 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
   inner_env->BindContext(context);

-  HArgumentsObject* arguments_object = NULL;
-
-  // If the function uses arguments object create and bind one, also copy
+ // Create a dematerialized arguments object for the function, also copy the
   // current arguments values to use them for materialization.
+  HEnvironment* arguments_env = inner_env->arguments_environment();
+  int parameter_count = arguments_env->parameter_count();
+ HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
+  for (int i = 0; i < parameter_count; i++) {
+    arguments_object->AddArgument(arguments_env->Lookup(i), zone());
+  }
+
+  // If the function uses arguments object then bind bind one.
   if (function->scope()->arguments() != NULL) {
     ASSERT(function->scope()->arguments()->IsStackAllocated());
-    HEnvironment* arguments_env = inner_env->arguments_environment();
-    int arguments_count = arguments_env->parameter_count();
-    arguments_object = Add<HArgumentsObject>(arguments_count);
     inner_env->Bind(function->scope()->arguments(), arguments_object);
-    for (int i = 0; i < arguments_count; i++) {
-      arguments_object->AddArgument(arguments_env->Lookup(i), zone());
-    }
   }

// Capture the state before invoking the inlined function for deopt in the @@ -11326,18 +11326,26 @@ void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {


 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
-  // Our implementation of arguments (based on this stack frame or an
-  // adapter below it) does not work for inlined functions.  This runtime
-  // function is blacklisted by AstNode::IsInlineable.
-  ASSERT(function_state()->outer() == NULL);
   ASSERT(call->arguments()->length() == 1);
   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   HValue* index = Pop();
-  HInstruction* elements = Add<HArgumentsElements>(false);
-  HInstruction* length = Add<HArgumentsLength>(elements);
-  HInstruction* checked_index = Add<HBoundsCheck>(index, length);
-  HAccessArgumentsAt* result = New<HAccessArgumentsAt>(
-      elements, length, checked_index);
+  HInstruction* result = NULL;
+  if (function_state()->outer() == NULL) {
+    HInstruction* elements = Add<HArgumentsElements>(false);
+    HInstruction* length = Add<HArgumentsLength>(elements);
+    HInstruction* checked_index = Add<HBoundsCheck>(index, length);
+    result = New<HAccessArgumentsAt>(elements, length, checked_index);
+  } else {
+    EnsureArgumentsArePushedForAccess();
+
+    // Number of arguments without receiver.
+    HInstruction* elements = function_state()->arguments_elements();
+    int argument_count = environment()->
+        arguments_environment()->parameter_count() - 1;
+    HInstruction* length = Add<HConstant>(argument_count);
+    HInstruction* checked_key = Add<HBoundsCheck>(index, length);
+    result = New<HAccessArgumentsAt>(elements, length, checked_key);
+  }
   return ast_context()->ReturnInstruction(result, call->id());
 }

Index: test/mjsunit/compiler/inline-arguments.js
diff --git a/test/mjsunit/compiler/inline-arguments.js b/test/mjsunit/compiler/inline-arguments.js index 1337ab237a4cadd8a053e6e95d0d58ffff717ccb..d52f31b5e9171fa22e248720e8d36c6bc976072c 100644
--- a/test/mjsunit/compiler/inline-arguments.js
+++ b/test/mjsunit/compiler/inline-arguments.js
@@ -309,3 +309,29 @@ test_toarr(toarr2);
   delete forceDeopt.deopt;
   outer();
 })();
+
+
+// Test inlining of functions with %_Arguments and %_ArgumentsLength intrinsic.
+(function () {
+  function inner(len,a,b,c) {
+    assertSame(len, %_ArgumentsLength());
+    for (var i = 1; i < len; ++i) {
+      var c = String.fromCharCode(96 + i);
+      assertSame(c, %_Arguments(i));
+    }
+  }
+
+  function outer() {
+    inner(1);
+    inner(2, 'a');
+    inner(3, 'a', 'b');
+    inner(4, 'a', 'b', 'c');
+    inner(5, 'a', 'b', 'c', 'd');
+    inner(6, 'a', 'b', 'c', 'd', 'e');
+  }
+
+  outer();
+  outer();
+  %OptimizeFunctionOnNextCall(outer);
+  outer();
+})();


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to