Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 53891afeffac045a1467308e598ce3fc8b758647 Mon Sep 17 00:00:00 2001
- From: Petka Antonov <p.antonov@partner.samsung.com>
- Date: Tue, 28 Oct 2014 14:44:40 +0200
- Subject: [PATCH] The patch 2
- ---
- src/hydrogen.cc | 76 ++++++++++--
- src/hydrogen.h | 2 +
- src/objects.h | 1 +
- test/mjsunit/compiler/slice-call-arguments.js | 163 +++++++++++++++++++++++++
- test/mjsunit/compiler/slice-call-arguments2.js | 61 +++++++++
- 5 files changed, 295 insertions(+), 8 deletions(-)
- create mode 100644 test/mjsunit/compiler/slice-call-arguments.js
- create mode 100644 test/mjsunit/compiler/slice-call-arguments2.js
- diff --git a/src/hydrogen.cc b/src/hydrogen.cc
- index 7b1e5b1..30b8e29 100644
- --- a/src/hydrogen.cc
- +++ b/src/hydrogen.cc
- @@ -8571,6 +8571,41 @@ bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
- }
- +
- +bool HOptimizedGraphBuilder::TryInlineBuiltinArgumentsMethod(
- + Handle<JSFunction> function, int args_count_no_receiver) {
- + if (!function->shared()->HasBuiltinFunctionId()) return false;
- +
- + HValue* arguments_object_length = NULL;
- + HInstruction* arguments_object_elements = NULL;
- + {
- + NoObservableSideEffectsScope no_effects(this);
- + if (function_state()->outer() == NULL) {
- + arguments_object_elements = Add<HArgumentsElements>(false);
- + arguments_object_length =
- + AddUncasted<HArgumentsLength>(arguments_object_elements);
- + } else {
- + EnsureArgumentsArePushedForAccess();
- + arguments_object_elements = function_state()->arguments_elements();
- + arguments_object_length =
- + AddUncasted<HConstant>(static_cast<int32_t>(
- + environment()->arguments_environment()->parameter_count() - 1));
- + }
- + }
- +
- + BuiltinFunctionId id = function->shared()->builtin_function_id();
- + switch (id) {
- + case kArraySlice: {
- + return false;
- + }
- +
- + default:
- + break;
- + }
- + return false;
- +}
- +
- +
- bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
- HValue* receiver) {
- Handle<JSFunction> function = expr->target();
- @@ -8747,9 +8782,26 @@ void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
- int arguments_count) {
- Handle<JSFunction> known_function;
- int args_count_no_receiver = arguments_count - 1;
- + HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
- +
- if (function->IsConstant() &&
- HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
- - HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
- + known_function =
- + Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
- + if (receiver->CheckFlag(HValue::kIsArguments)) {
- + if (TryInlineBuiltinArgumentsMethod(known_function,
- + args_count_no_receiver)) {
- + if (FLAG_trace_inlining) {
- + PrintF("Inlining builtin ");
- + known_function->ShortPrint();
- + PrintF("\n");
- + }
- + } else {
- + Bailout(kBadValueContextForArgumentsValue);
- + }
- + return;
- + }
- +
- Handle<Map> receiver_map;
- if (receiver->IsConstant() &&
- HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
- @@ -8758,8 +8810,6 @@ void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
- HConstant::cast(receiver)->handle(isolate()))->map());
- }
- - known_function =
- - Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
- if (TryInlineBuiltinMethodCall(expr, known_function, receiver_map,
- args_count_no_receiver)) {
- if (FLAG_trace_inlining) {
- @@ -8775,6 +8825,10 @@ void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
- }
- }
- + if (receiver->CheckFlag(HValue::kIsArguments)) {
- + return Bailout(kBadValueContextForArgumentsValue);
- + }
- +
- PushArgumentsFromEnvironment(arguments_count);
- HInvokeFunction* call =
- New<HInvokeFunction>(function, known_function, arguments_count);
- @@ -8865,21 +8919,27 @@ void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
- Handle<Map> function_map = expr->GetReceiverTypes()->first();
- HValue* checked_function = AddCheckMap(function, function_map);
- + DCHECK(expr->arguments()->length() > 0);
- // f and call are on the stack in the unoptimized code
- // during evaluation of the arguments.
- - CHECK_ALIVE(VisitExpressions(expr->arguments()));
- + // Allow 'arguments' reference as receiver for now, it will be checked later.
- + CHECK_ALIVE(VisitForValue(expr->arguments()->at(0), ARGUMENTS_ALLOWED));
- + for (int i = 1; i < expr->arguments()->length(); ++i) {
- + CHECK_ALIVE(VisitForValue(expr->arguments()->at(i)));
- + }
- int args_length = expr->arguments()->length();
- int receiver_index = args_length - 1;
- + HValue* receiver = environment()->ExpressionStackAt(receiver_index);
- // Patch the receiver.
- - HValue* receiver = BuildWrapReceiver(
- - environment()->ExpressionStackAt(receiver_index), checked_function);
- - environment()->SetExpressionStackAt(receiver_index, receiver);
- + if (!receiver->CheckFlag(HValue::kIsArguments)) {
- + receiver = BuildWrapReceiver(receiver, checked_function);
- + environment()->SetExpressionStackAt(receiver_index, receiver);
- + }
- // Call must not be on the stack from now on.
- int call_index = args_length + 1;
- environment()->RemoveExpressionStackAt(call_index);
- -
- HandleIndirectCall(expr, function, args_length);
- }
- diff --git a/src/hydrogen.h b/src/hydrogen.h
- index 9e3601a..15a78a1 100644
- --- a/src/hydrogen.h
- +++ b/src/hydrogen.h
- @@ -2359,6 +2359,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
- bool TryInlineBuiltinMethodCall(Call* expr, Handle<JSFunction> function,
- Handle<Map> receiver_map,
- int args_count_no_receiver);
- + bool TryInlineBuiltinArgumentsMethod(Handle<JSFunction> function,
- + int args_count_no_receiver);
- bool TryInlineBuiltinFunctionCall(Call* expr);
- enum ApiCallType {
- kCallApiFunction,
- diff --git a/src/objects.h b/src/objects.h
- index 0dc5e3a..f137575 100644
- --- a/src/objects.h
- +++ b/src/objects.h
- @@ -6570,6 +6570,7 @@ class Script: public Struct {
- V(Array.prototype, push, ArrayPush) \
- V(Array.prototype, pop, ArrayPop) \
- V(Array.prototype, shift, ArrayShift) \
- + V(Array.prototype, slice, ArraySlice) \
- V(Function.prototype, apply, FunctionApply) \
- V(Function.prototype, call, FunctionCall) \
- V(String.prototype, charCodeAt, StringCharCodeAt) \
- diff --git a/test/mjsunit/compiler/slice-call-arguments.js b/test/mjsunit/compiler/slice-call-arguments.js
- new file mode 100644
- index 0000000..708b689
- --- /dev/null
- +++ b/test/mjsunit/compiler/slice-call-arguments.js
- @@ -0,0 +1,163 @@
- +// 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 makeCopier(lower, upper) {
- + switch (arguments.length) {
- + case 2:
- + var ret = new Function(
- + "return [].slice.call(arguments, lower, upper);"
- + .replace("lower", lower)
- + .replace("upper", upper));
- + ret.lower = lower;
- + ret.upper = upper;
- + return ret;
- + case 1:
- + var ret = new Function(
- + "return [].slice.call(arguments, lower);"
- + .replace("lower", lower));
- + ret.lower = lower;
- + return ret;
- + }
- +}
- +
- +function verify(fn, args) {
- + fn(); fn();
- + %OptimizeFunctionOnNextCall(fn);
- + fn();
- + fn();
- + assertOptimized(fn);
- + assertArrayEquals(fn(), []);
- + var returned_value = fn.apply(void 0, args);
- + var lower = fn.lower;
- + var upper = fn.upper;
- + var expected = args.slice(lower, upper);
- + assertOptimized(fn);
- + assertTrue(Array.isArray(returned_value));
- + assertArrayEquals(expected, returned_value);
- +}
- +
- +function plainCopy() {
- + return Array.prototype.slice.call(arguments);
- +}
- +
- +verify(plainCopy, [1,2,3]);
- +verify(plainCopy, []);
- +
- +var arr = [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3];
- +verify(makeCopier(-1), arr);
- +verify(makeCopier(1), arr);
- +verify(makeCopier(-4, -10), arr);
- +verify(makeCopier(3, -2), arr);
- +verify(makeCopier(-5), arr);
- +verify(makeCopier(3, -1), arr);
- +verify(makeCopier(0, 0), arr);
- +verify(makeCopier(1, 0), arr);
- +verify(makeCopier(0, 1), arr);
- +verify(makeCopier(-1, 1), arr);
- +verify(makeCopier(-100), arr);
- +verify(makeCopier(-100, -100), arr);
- +verify(makeCopier(-10, -5), arr);
- +verify(makeCopier(10, -5), arr);
- +verify(makeCopier(-123, 72), arr);
- +verify(makeCopier(-1, -1), arr);
- +verify(makeCopier(3, -1), arr);
- +
- +var arr = [1, 2, 3];
- +
- +verify(makeCopier(-1), arr);
- +verify(makeCopier(1), arr);
- +verify(makeCopier(-4, -10), arr);
- +verify(makeCopier(3, -2), arr);
- +verify(makeCopier(-5), arr);
- +verify(makeCopier(3, -1), arr);
- +verify(makeCopier(0, 0), arr);
- +verify(makeCopier(1, 0), arr);
- +verify(makeCopier(0, 1), arr);
- +verify(makeCopier(-1, 1), arr);
- +verify(makeCopier(-100), arr);
- +verify(makeCopier(-100, -100), arr);
- +verify(makeCopier(-10, -5), arr);
- +verify(makeCopier(10, -5), arr);
- +verify(makeCopier(-123, 72), arr);
- +verify(makeCopier(-1, -1), arr);
- +verify(makeCopier(3, -1), arr);
- +
- +var arr = [];
- +
- +verify(makeCopier(-1), arr);
- +verify(makeCopier(1), arr);
- +verify(makeCopier(-4, -10), arr);
- +verify(makeCopier(3, -2), arr);
- +verify(makeCopier(-5), arr);
- +verify(makeCopier(3, -1), arr);
- +verify(makeCopier(0, 0), arr);
- +verify(makeCopier(1, 0), arr);
- +verify(makeCopier(0, 1), arr);
- +verify(makeCopier(-1, 1), arr);
- +verify(makeCopier(-100), arr);
- +verify(makeCopier(-100, -100), arr);
- +verify(makeCopier(-10, -5), arr);
- +verify(makeCopier(10, -5), arr);
- +verify(makeCopier(-123, 72), arr);
- +verify(makeCopier(-1, -1), arr);
- +verify(makeCopier(3, -1), arr);
- +
- +function calls_not_slice() {
- + return Array.prototype.shift.call(arguments);
- +}
- +
- +calls_not_slice();
- +calls_not_slice();
- +%OptimizeFunctionOnNextCall(calls_not_slice);
- +calls_not_slice();
- +assertUnoptimized(calls_not_slice);
- +calls_not_slice();
- +calls_not_slice();
- +%OptimizeFunctionOnNextCall(calls_not_slice);
- +calls_not_slice();
- +assertUnoptimized(calls_not_slice);
- +
- +function calls_slice_that_changes() {
- + return Array.prototype.slice.call(arguments);
- +}
- +
- +calls_slice_that_changes();
- +calls_slice_that_changes();
- +%OptimizeFunctionOnNextCall(calls_slice_that_changes);
- +calls_slice_that_changes();
- +assertOptimized(calls_slice_that_changes);
- +
- +Array.prototype.slice = function() {};
- +calls_slice_that_changes();
- +assertUnoptimized(calls_slice_that_changes);
- +calls_slice_that_changes();
- +calls_slice_that_changes();
- +%OptimizeFunctionOnNextCall(calls_slice_that_changes);
- +calls_slice_that_changes();
- +assertUnoptimized(calls_slice_that_changes);
- diff --git a/test/mjsunit/compiler/slice-call-arguments2.js b/test/mjsunit/compiler/slice-call-arguments2.js
- new file mode 100644
- index 0000000..b670554
- --- /dev/null
- +++ b/test/mjsunit/compiler/slice-call-arguments2.js
- @@ -0,0 +1,61 @@
- +// 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 lotsOfArguments() {
- + return Array.prototype.slice.call(arguments);
- +}
- +
- +var arr = new Array(100000);
- +for (var i = 0; i < arr.length; ++i) arr[i] = i;
- +
- +assertArrayEquals([1,2,3], lotsOfArguments(1,2,3));
- +assertArrayEquals([1,2,3], lotsOfArguments(1,2,3));
- +%OptimizeFunctionOnNextCall(lotsOfArguments);
- +assertArrayEquals([1,2,3], lotsOfArguments(1,2,3));
- +assertOptimized(lotsOfArguments);
- +var result = lotsOfArguments.apply(void 0, arr);
- +assertArrayEquals(arr, result);
- +assertUnoptimized(lotsOfArguments);
- +
- +
- +var o = {
- + callsInline: function caller() {
- + return this.toBeInlined(1, 2, 3, 4, 5);
- + },
- + toBeInlined: function callee() {
- + return Array.prototype.slice.call(arguments);
- + }
- +};
- +
- +assertArrayEquals([1,2,3,4,5], o.callsInline());
- +assertArrayEquals([1,2,3,4,5], o.callsInline());
- +%OptimizeFunctionOnNextCall(o.callsInline);
- +assertArrayEquals([1,2,3,4,5], o.callsInline());
- +assertOptimized(o.callsInline);
- +assertArrayEquals([1,2,3,4,5], o.callsInline());
- --
- 1.9.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement