Revision: 21887
Author:   [email protected]
Date:     Wed Jun 18 14:04:41 2014 UTC
Log:      Revert "Optimize Function.prototype.call"

This reverts commit r21840.

[email protected]
LOG=y
BUG=chromium:385565

Review URL: https://codereview.chromium.org/347573002
http://code.google.com/p/v8/source/detail?r=21887

Deleted:
 /branches/bleeding_edge/test/mjsunit/compiler/inlined-call.js
Modified:
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/objects.h

=======================================
--- /branches/bleeding_edge/test/mjsunit/compiler/inlined-call.js Fri Jun 13 12:52:23 2014 UTC
+++ /dev/null
@@ -1,156 +0,0 @@
-// 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: --allow-natives-syntax --noalways-opt
-
-var array = [];
-for (var i = 0; i < 100; ++i) {
-  array[i] = i;
-}
-
-var copy = array.slice();
-
-function unshiftsArray(num) {
-  [].unshift.call(array, num);
-}
-
-unshiftsArray(50);
-unshiftsArray(60);
-%OptimizeFunctionOnNextCall(unshiftsArray);
-unshiftsArray(80);
-unshiftsArray(50);
-unshiftsArray(60);
-
-copy.unshift(50);
-copy.unshift(60);
-copy.unshift(80);
-copy.unshift(50);
-copy.unshift(60);
-
-assertOptimized(unshiftsArray);
-assertArrayEquals(array, copy);
-
-
-var called = 0;
-var funRecv;
-// For the HConstant
-Array.prototype.fun = function() {
-  funRecv = this;
-  called++;
-  assertEquals(0, arguments.length);
-};
-
-function callNoArgs() {
-  [].fun.call();
-}
-
-callNoArgs();
-callNoArgs();
-assertEquals(this, funRecv);
-%OptimizeFunctionOnNextCall(callNoArgs);
-callNoArgs();
-assertEquals(this, funRecv);
-assertEquals(3, called);
-assertOptimized(callNoArgs);
-
-var funStrictRecv;
-called = 0;
-Array.prototype.funStrict = function() {
-  "use strict";
-  funStrictRecv = this;
-  called++;
-  assertEquals(0, arguments.length);
-};
-
-function callStrictNoArgs() {
-  [].funStrict.call();
-}
-
-callStrictNoArgs();
-callStrictNoArgs();
-assertEquals(undefined, funStrictRecv);
-%OptimizeFunctionOnNextCall(callStrictNoArgs);
-callStrictNoArgs();
-assertEquals(undefined, funStrictRecv);
-assertEquals(3, called);
-assertOptimized(callStrictNoArgs);
-
-called = 0;
-Array.prototype.manyArgs = function() {
-  "use strict";
-  assertEquals(5, arguments.length);
-  assertEquals(0, this);
-  assertEquals(5, arguments[4]);
-  called++;
-}
-
-function callManyArgs() {
-  [].manyArgs.call(0, 1, 2, 3, 4, 5);
-}
-
-callManyArgs();
-callManyArgs();
-%OptimizeFunctionOnNextCall(callManyArgs);
-callManyArgs();
-assertOptimized(callManyArgs);
-assertEquals(called, 3);
-
-called = 0;
-Array.prototype.manyArgsSloppy = function() {
-  assertTrue(this instanceof Number);
-  assertEquals(5, arguments.length);
-  assertEquals(0, this.valueOf());
-  assertEquals(5, arguments[4]);
-  called++;
-}
-
-function callManyArgsSloppy() {
-  [].manyArgsSloppy.call(0, 1, 2, 3, 4, 5);
-}
-
-callManyArgsSloppy();
-callManyArgsSloppy();
-%OptimizeFunctionOnNextCall(callManyArgsSloppy);
-callManyArgsSloppy();
-assertOptimized(callManyArgsSloppy);
-assertEquals(called, 3);
-
-var str = "hello";
-var code = str.charCodeAt(3);
-called = 0;
-function callBuiltinIndirectly() {
-  called++;
-  return "".charCodeAt.call(str, 3);
-}
-
-callBuiltinIndirectly();
-callBuiltinIndirectly();
-%OptimizeFunctionOnNextCall(callBuiltinIndirectly);
-assertEquals(code, callBuiltinIndirectly());
-assertOptimized(callBuiltinIndirectly);
-assertEquals(3, called);
-
-this.array = [1,2,3,4,5,6,7,8,9];
-var copy = this.array.slice();
-called = 0;
-
-function callInlineableBuiltinIndirectlyWhileInlined() {
-    called++;
-    return [].push.apply(array, arguments);
-}
-
-function callInlined(num) {
-    return callInlineableBuiltinIndirectlyWhileInlined(num);
-}
-
-callInlined(1);
-callInlined(2);
-%OptimizeFunctionOnNextCall(callInlineableBuiltinIndirectlyWhileInlined);
-%OptimizeFunctionOnNextCall(callInlined);
-callInlined(3);
-copy.push(1, 2, 3);
-assertOptimized(callInlined);
-assertOptimized(callInlineableBuiltinIndirectlyWhileInlined);
-assertArrayEquals(copy, this.array);
-assertEquals(3, called);
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Wed Jun 18 07:30:56 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Wed Jun 18 14:04:41 2014 UTC
@@ -7923,9 +7923,9 @@
 }


-bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
-                                                   Call* expr,
-                                                   int arguments_count) {
+bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
+                                            Call* expr,
+                                            int arguments_count) {
   return TryInline(function,
                    arguments_count,
                    NULL,
@@ -7977,22 +7977,12 @@

 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
     Call* expr,
-    Handle<JSFunction> function,
-    Handle<Map> receiver_map,
-    int args_count_no_receiver) {
-  if (!function->shared()->HasBuiltinFunctionId()) return false;
-  BuiltinFunctionId id = function->shared()->builtin_function_id();
-  int argument_count = args_count_no_receiver + 1;  // Plus receiver.
-
-  if (receiver_map.is_null()) {
- HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
-    if (receiver->IsConstant() &&
-        HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
-      receiver_map = handle(Handle<HeapObject>::cast(
-          HConstant::cast(receiver)->handle(isolate()))->map());
-    }
-  }
+    HValue* receiver,
+    Handle<Map> receiver_map) {
   // Try to inline calls like Math.* as operations in the calling function.
+  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
+  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
+  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   switch (id) {
     case kStringCharCodeAt:
     case kStringCharAt:
@@ -8100,7 +8090,7 @@
       if (receiver_map->is_observed()) return false;
       ASSERT(receiver_map->is_extensible());

-      Drop(args_count_no_receiver);
+      Drop(expr->arguments()->length());
       HValue* result;
       HValue* reduced_length;
       HValue* receiver = Pop();
@@ -8176,7 +8166,7 @@
Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());

-      const int argc = args_count_no_receiver;
+      const int argc = expr->arguments()->length();
       if (argc != 1) return false;

       HValue* value_to_push = Pop();
@@ -8233,7 +8223,7 @@
       // Threshold for fast inlined Array.shift().
HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));

-      Drop(args_count_no_receiver);
+      Drop(expr->arguments()->length());
       HValue* receiver = Pop();
       HValue* function = Pop();
       HValue* result;
@@ -8544,83 +8534,31 @@
 }


-void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr,
-                                                HValue* function,
-                                                int arguments_count) {
-  Handle<JSFunction> known_function;
-  int args_count_no_receiver = arguments_count - 1;
-  if (function->IsConstant() &&
-      HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
-    known_function = Handle<JSFunction>::cast(
-        HConstant::cast(function)->handle(isolate()));
- if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
-      return;
-    }
-
-    Handle<Map> map;
-    if (TryInlineBuiltinMethodCall(expr, known_function, map,
-                                   args_count_no_receiver)) {
-      if (FLAG_trace_inlining) {
-        PrintF("Inlining builtin ");
-        known_function->ShortPrint();
-        PrintF("\n");
-      }
-      return;
-    }
-  }
-
-  PushArgumentsFromEnvironment(arguments_count);
-  HInvokeFunction* call = New<HInvokeFunction>(
-      function, known_function, arguments_count);
-  Drop(1);  // Function
-  ast_context()->ReturnInstruction(call, expr->id());
-}
-
-
-bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
+bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
   ASSERT(expr->expression()->IsProperty());

   if (!expr->IsMonomorphic()) {
     return false;
   }
-
   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
-      !expr->target()->shared()->HasBuiltinFunctionId()) {
+      !expr->target()->shared()->HasBuiltinFunctionId() ||
+      expr->target()->shared()->builtin_function_id() != kFunctionApply) {
     return false;
   }

-  switch (expr->target()->shared()->builtin_function_id()) {
-    case kFunctionCall: {
-      BuildFunctionCall(expr);
-      return true;
-    }
-    case kFunctionApply: {
-      // For .apply, only the pattern f.apply(receiver, arguments)
-      // is supported.
-      if (current_info()->scope()->arguments() == NULL) return false;
+  if (current_info()->scope()->arguments() == NULL) return false;

-      ZoneList<Expression*>* args = expr->arguments();
-      if (args->length() != 2) return false;
+  ZoneList<Expression*>* args = expr->arguments();
+  if (args->length() != 2) return false;

-      VariableProxy* arg_two = args->at(1)->AsVariableProxy();
- if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
-      HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
-      if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
-      BuildFunctionApply(expr);
-      return true;
-    }
-    default: {
-      return false;
-    }
-  }
-  UNREACHABLE();
-}
+  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
+  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
+  HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
+  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;

-
-void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
-  ZoneList<Expression*>* args = expr->arguments();
-  CHECK_ALIVE(VisitForValue(args->at(0)));
+  // Found pattern f.apply(receiver, arguments).
+  CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
   HValue* receiver = Pop();  // receiver
   HValue* function = Pop();  // f
   Drop(1);  // apply
@@ -8634,6 +8572,7 @@
                                                 length,
                                                 elements);
     ast_context()->ReturnInstruction(result, expr->id());
+    return true;
   } else {
     // We are inside inlined function and we know exactly what is inside
     // arguments object. But we need to be able to materialize at deopt.
@@ -8647,34 +8586,23 @@
     for (int i = 1; i < arguments_count; i++) {
       Push(arguments_values->at(i));
     }
-    HandleIndirectCall(expr, function, arguments_count);
-  }
-}

-
-// f.call(...)
-void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
-  HValue* function = Pop();  // f
-  HValue* receiver;
-  ZoneList<Expression*>* args = expr->arguments();
-  int args_length = args->length();
-  Drop(1);  // call
-
-  if (args_length == 0) {
-    receiver = graph()->GetConstantUndefined();
-    args_length = 1;
-  } else {
-    CHECK_ALIVE(VisitForValue(args->at(0)));
-    receiver = Pop();
-  }
-  receiver = BuildWrapReceiver(receiver, function);
+    Handle<JSFunction> known_function;
+    if (function->IsConstant() &&
+        HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
+      known_function = Handle<JSFunction>::cast(
+          HConstant::cast(function)->handle(isolate()));
+      int args_count = arguments_count - 1;  // Excluding receiver.
+      if (TryInlineApply(known_function, expr, args_count)) return true;
+    }

-  Push(function);
-  Push(receiver);
-  for (int i = 1; i < args_length; i++) {
-    CHECK_ALIVE(VisitForValue(args->at(i)));
+    PushArgumentsFromEnvironment(arguments_count);
+    HInvokeFunction* call = New<HInvokeFunction>(
+        function, known_function, arguments_count);
+    Drop(1);  // Function.
+    ast_context()->ReturnInstruction(call, expr->id());
+    return true;
   }
-  HandleIndirectCall(expr, function, args_length);
 }


@@ -8939,12 +8867,11 @@
           HConstant::cast(function)->handle(isolate()));
       expr->set_target(known_function);

-      if (TryIndirectCall(expr)) return;
+      if (TryCallApply(expr)) return;
       CHECK_ALIVE(VisitExpressions(expr->arguments()));

Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
-      if (TryInlineBuiltinMethodCall(expr, known_function, map,
-                                     expr->arguments()->length())) {
+      if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
         if (FLAG_trace_inlining) {
           PrintF("Inlining builtin ");
           known_function->ShortPrint();
=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Fri Jun 13 16:43:27 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.h      Wed Jun 18 14:04:41 2014 UTC
@@ -2321,13 +2321,8 @@
   void EnsureArgumentsArePushedForAccess();
   bool TryArgumentsAccess(Property* expr);

-  // Shared code for .call and .apply optimizations.
- void HandleIndirectCall(Call* expr, HValue* function, int arguments_count);
-  // Try to optimize indirect calls such as fun.apply(receiver, arguments)
-  // or fun.call(...).
-  bool TryIndirectCall(Call* expr);
-  void BuildFunctionApply(Call* expr);
-  void BuildFunctionCall(Call* expr);
+  // Try to optimize fun.apply(receiver, arguments) pattern.
+  bool TryCallApply(Call* expr);

   bool TryHandleArrayCall(Call* expr, HValue* function);
   bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
@@ -2363,13 +2358,12 @@
                        BailoutId id,
                        BailoutId assignment_id,
                        HValue* implicit_return_value);
-  bool TryInlineIndirectCall(Handle<JSFunction> function,
-                             Call* expr,
-                             int arguments_count);
+  bool TryInlineApply(Handle<JSFunction> function,
+                      Call* expr,
+                      int arguments_count);
   bool TryInlineBuiltinMethodCall(Call* expr,
-                                  Handle<JSFunction> function,
-                                  Handle<Map> receiver_map,
-                                  int args_count_no_receiver);
+                                  HValue* receiver,
+                                  Handle<Map> receiver_map);
   bool TryInlineBuiltinFunctionCall(Call* expr);
   enum ApiCallType {
     kCallApiFunction,
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Jun 13 12:52:23 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Wed Jun 18 14:04:41 2014 UTC
@@ -7013,7 +7013,6 @@
   V(Array.prototype, pop, ArrayPop)                   \
   V(Array.prototype, shift, ArrayShift)               \
   V(Function.prototype, apply, FunctionApply)         \
-  V(Function.prototype, call, FunctionCall)           \
   V(String.prototype, charCodeAt, StringCharCodeAt)   \
   V(String.prototype, charAt, StringCharAt)           \
   V(String, fromCharCode, StringFromCharCode)         \

--
--
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