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.