Commit 23868b41 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Optimize Function.prototype.call

BUG=
R=verwaest@chromium.org, jarin@chromium.org, jkummerow@chromium.org

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

Patch from Petka Antonov <p.antonov@partner.samsung.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24631 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 37f16450
This diff is collapsed.
......@@ -642,6 +642,7 @@ class HEnvironment FINAL : public ZoneObject {
}
void SetExpressionStackAt(int index_from_top, HValue* value);
HValue* RemoveExpressionStackAt(int index_from_top);
HEnvironment* Copy() const;
HEnvironment* CopyWithoutHistory() const;
......@@ -2311,8 +2312,13 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
void EnsureArgumentsArePushedForAccess();
bool TryArgumentsAccess(Property* expr);
// Try to optimize fun.apply(receiver, arguments) pattern.
bool TryCallApply(Call* 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);
bool TryHandleArrayCall(Call* expr, HValue* function);
bool TryHandleArrayCallNew(CallNew* expr, HValue* function);
......@@ -2348,12 +2354,11 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
BailoutId id,
BailoutId assignment_id,
HValue* implicit_return_value);
bool TryInlineApply(Handle<JSFunction> function,
Call* expr,
int arguments_count);
bool TryInlineBuiltinMethodCall(Call* expr,
HValue* receiver,
Handle<Map> receiver_map);
bool TryInlineIndirectCall(Handle<JSFunction> function, Call* expr,
int arguments_count);
bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
Handle<Map> receiver_map,
int args_count_no_receiver);
bool TryInlineBuiltinFunctionCall(Call* expr);
enum ApiCallType {
kCallApiFunction,
......
......@@ -6560,6 +6560,7 @@ class Script: public Struct {
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) \
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --noalways-opt
var global = this;
Array.prototype.f = function() {
return 0;
};
(function() {
var called = 0;
function g(x, y, called) {
return called + 1;
}
function f(deopt, called) {
return g([].f.call({}), deopt + 1, called);
}
called = f(0, called);
called = f(0, called);
%OptimizeFunctionOnNextCall(f);
called = f(0, called);
assertOptimized(f);
called = f({}, called);
assertUnoptimized(f);
assertEquals(4, called);
})();
(function() {
// The array built-ins are only inlined if the receiver is a
// HConstant, this seems to require a *unique* global identifier
// each time.
global.a1 = [1,2,3,4];
var obj = {value: 3};
function f(b) {
return [].pop.call(a1) + b.value;
}
assertEquals(7, f(obj));
assertEquals(6, f(obj));
%OptimizeFunctionOnNextCall(f);
assertEquals(5, f(obj));
assertOptimized(f);
assertEquals(4, f({d: 0, value: 3}));
assertUnoptimized(f);
assertEquals(0, a1.length);
})();
(function() {
global.a2 = [1,2,3,4];
var obj = {value: 3};
function f(b) {
return [].shift.call(a2) + b.value;
}
assertEquals(4, f(obj));
assertEquals(5, f(obj));
%OptimizeFunctionOnNextCall(f);
assertEquals(6, f(obj));
assertOptimized(f);
assertEquals(7, f({d: 0, value: 3}));
assertUnoptimized(f);
assertEquals(0, a2.length);
})();
(function() {
global.a3 = [1,2,3,4];
var obj = {value: 3};
function f(b) {
return [].push.call(a3, b.value);
}
assertEquals(5, f(obj));
assertEquals(6, f(obj));
%OptimizeFunctionOnNextCall(f);
assertEquals(7, f(obj));
assertOptimized(f);
assertEquals(8, f({d: 0, value: 3}));
assertUnoptimized(f);
assertEquals(8, a3.length);
assertEquals(3, a3[7]);
})();
(function() {
global.a4 = [1,2,3,4];
var obj = {value: 3};
function f(b) {
return [].indexOf.call(a4, b.value);
}
f(obj);
f(obj);
%OptimizeFunctionOnNextCall(f);
var index1 = f(obj);
assertOptimized(f);
var index2 = f({d: 0, value: 3});
assertUnoptimized(f);
assertEquals(2, index1);
assertEquals(index1, index2);
})();
(function() {
global.a5 = [1,2,3,4];
var obj = {value: 3};
function f(b) {
return [].lastIndexOf.call(a5, b.value);
}
f(obj);
f(obj);
%OptimizeFunctionOnNextCall(f);
var index1 = f(obj);
assertOptimized(f);
var index2 = f({d: 0, value: 3});
assertUnoptimized(f);
assertEquals(2, index1);
assertEquals(index1, index2);
})();
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --noalways-opt
(function() {
function f(x) {
for (i = 0; i < 1; i++) {
x.call(this);
}
}
function g() {}
f(g);
f(g);
%OptimizeFunctionOnNextCall(f);
assertThrows(function() { f('whatever') }, TypeError);
})();
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --noalways-opt
var global = this;
// For the HConstant
Array.prototype.fun = function() {
funRecv = this;
called++;
assertEquals(0, arguments.length);
};
Array.prototype.funStrict = function() {
"use strict";
funStrictRecv = this;
called++;
assertEquals(0, arguments.length);
};
Array.prototype.manyArgs = function() {
"use strict";
assertEquals(5, arguments.length);
assertEquals(0, this);
assertEquals(5, arguments[4]);
called++;
}
Array.prototype.manyArgsSloppy = function() {
assertEquals(global, this);
assertEquals(5, arguments.length);
assertEquals(5, arguments[4]);
called++;
}
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;
function callNoArgs() {
[].fun.call();
}
callNoArgs();
callNoArgs();
assertEquals(this, funRecv);
%OptimizeFunctionOnNextCall(callNoArgs);
callNoArgs();
assertEquals(this, funRecv);
assertEquals(3, called);
assertOptimized(callNoArgs);
var funStrictRecv;
called = 0;
function callStrictNoArgs() {
[].funStrict.call();
}
callStrictNoArgs();
callStrictNoArgs();
assertEquals(undefined, funStrictRecv);
%OptimizeFunctionOnNextCall(callStrictNoArgs);
callStrictNoArgs();
assertEquals(undefined, funStrictRecv);
assertEquals(3, called);
assertOptimized(callStrictNoArgs);
called = 0;
function callManyArgs() {
[].manyArgs.call(0, 1, 2, 3, 4, 5);
}
callManyArgs();
callManyArgs();
%OptimizeFunctionOnNextCall(callManyArgs);
callManyArgs();
assertOptimized(callManyArgs);
assertEquals(called, 3);
called = 0;
function callManyArgsSloppy() {
[].manyArgsSloppy.call(null, 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);
}
callInlineableBuiltinIndirectlyWhileInlined(1);
callInlineableBuiltinIndirectlyWhileInlined(2);
%OptimizeFunctionOnNextCall(callInlineableBuiltinIndirectlyWhileInlined);
callInlineableBuiltinIndirectlyWhileInlined(3);
assertOptimized(callInlineableBuiltinIndirectlyWhileInlined);
callInlined(1);
callInlined(2);
%OptimizeFunctionOnNextCall(callInlined);
callInlined(3);
copy.push(1, 2, 3, 1, 2, 3);
assertOptimized(callInlined);
assertArrayEquals(copy, this.array);
assertEquals(6, called);
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --noalways-opt
var calls = 0;
function callsFReceiver(o) {
return [].f.call(new Number(o.m), 1, 2, 3);
}
// For the HConstant
Array.prototype.f = function() {
calls++;
return +this;
};
var o1 = {m: 1};
var o2 = {a: 0, m:1};
var r1 = callsFReceiver(o1);
callsFReceiver(o1);
%OptimizeFunctionOnNextCall(callsFReceiver);
var r2 = callsFReceiver(o1);
assertOptimized(callsFReceiver);
callsFReceiver(o2);
assertUnoptimized(callsFReceiver);
var r3 = callsFReceiver(o1);
assertEquals(1, r1);
assertTrue(r1 === r2);
assertTrue(r2 === r3);
r1 = callsFReceiver(o1);
callsFReceiver(o1);
%OptimizeFunctionOnNextCall(callsFReceiver);
r2 = callsFReceiver(o1);
callsFReceiver(o2);
r3 = callsFReceiver(o1);
assertEquals(1, r1);
assertTrue(r1 === r2);
assertTrue(r2 === r3);
assertEquals(10, calls);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment