Commit 3e90eee9 authored by Mythri A's avatar Mythri A Committed by Commit Bot

[turbofan] Allow polymorphic inlining for Array push / pop / shift

Array push / pop / shift were inlined if the elements kind of the
receiver maps is the same. This cl extends it by inlining these
builtins even when the receiver maps have different elements kinds.
It still limits it to only fast elements kinds. This is required to
prevent regressions in deltablue when lazy feedback allocation is
enabled. With lazy feedback allocation we may see polymorphic
feedback more often, since we don't have allocation site feedback
till the feedback vectors are allocated.

Bug: v8:9078
Change-Id: Id4a7b84be6305b125913b6ce0fb4f3eb3e3b15ec
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1632239
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61949}
parent 40c68926
This diff is collapsed.
......@@ -231,6 +231,10 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
const SharedFunctionInfoRef& shared,
Node* context = nullptr);
void CheckIfElementsKind(Node* receiver_elements_kind, ElementsKind kind,
Node* control, Node** if_true, Node** if_false);
Node* LoadReceiverElementsKind(Node* receiver, Node** effect, Node** control);
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
JSHeapBroker* broker() const { return broker_; }
......
......@@ -7,8 +7,8 @@
let id = 0;
function runTest(f, message, mkICTraining, deoptArg) {
function test(f, message, ictraining, deoptArg) {
function runTest(f, message, mkICTraining, deoptArg, speculationCheck) {
function test(f, message, ictraining, deoptArg, speculationCheck) {
// Train the call ic to the maps.
let t = ictraining;
......@@ -41,15 +41,22 @@ function runTest(f, message, mkICTraining, deoptArg) {
// Trigger deopt, causing no-speculation bit to be set.
let a1 = deoptArg;
let a2 = deoptArg;
let a3 = deoptArg;
message += " for args " + JSON.stringify(a1);
message_unoptimized = message + " should have been unoptimized"
message_optimized = message + " should have been unoptimized"
f(a1.arr, () => a1.el);
message_optimized = message + " should have been optimized"
f(a1.darr, () => a1.del);
assertUnoptimized(f, undefined, message_unoptimized);
if (speculationCheck) {
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
f(a2.darr, () => a2.del);
assertUnoptimized(f, undefined, message_unoptimized);
}
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
// No speculation should protect against further deopts.
f(a2.arr, () => a2.el);
f(a3.darr, () => a3.del);
assertOptimized(f, undefined, message_optimized);
}
}
......@@ -64,6 +71,8 @@ function runTest(f, message, mkICTraining, deoptArg) {
testString = testString.replace(new RegExp("ictraining", 'g'), mkICTraining.toString());
testString = testString.replace(new RegExp("deoptArg", 'g'),
deoptArg ? JSON.stringify(deoptArg).replace(/"/g,'') : "undefined");
testString = testString.replace(new RegExp("speculationCheck", 'g'),
speculationCheck ? JSON.stringify(deoptArg).replace(/"/g,'') : "undefined");
// Make field names unique to avoid learning of types.
id = id + 1;
......@@ -71,16 +80,17 @@ function runTest(f, message, mkICTraining, deoptArg) {
testString = testString.replace(/el:/g, 'el' + id + ':');
testString = testString.replace(/[.]arr/g, '.arr' + id);
testString = testString.replace(/arr:/g, 'arr' + id + ':');
testString = testString.replace(/[.]del/g, '.del' + id);
testString = testString.replace(/[.]darr/g, '.darr' + id);
var modTest = new Function("message", testString);
//print(modTest);
modTest(message);
}
let checks = {
smiReceiver:
{ mkTrainingArguments : () => [{arr:[1], el:3}],
deoptingArguments : [{arr:[0.1], el:1}, {arr:[{}], el:1}]
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
objectReceiver:
{ mkTrainingArguments : () => [{arr:[{}], el:0.1}],
......@@ -88,30 +98,53 @@ let checks = {
},
multipleSmiReceivers:
{ mkTrainingArguments : () => { let b = [1]; b.x=3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{arr:[0.1], el:1}, {arr:[{}], el:1}]
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
multipleSmiReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [1]; b[100] = 3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{arr:[0.1], el:1}, {arr:[{}], el:1}]
deoptingArguments : [{darr:[0.1], del:1}, {darr:[{}], del:1}]
},
multipleDoubleReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{arr:[{}], el:true}, {arr:[1], el:true}]
deoptingArguments : [{darr:[{}], del:true}, {darr:[1], del: 1}]
},
multipleDoubleReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{arr:[{}], el:true}, {arr:[1], el:true}]
deoptingArguments : [{darr:[{}], del:true}, {darr:[1], del: 1}]
},
multipleMixedReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[1], el:0.3}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[1], el:1}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
deoptingArguments : []
},
multipleMixedReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[1], el:0.3}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[1], el:1}, {arr:[{}], el:true}, {arr:b, el:0.3}] },
deoptingArguments : []
},
};
let no_speculation_checks = {
smiReceiver:
{ mkTrainingArguments : () => [{arr:[1], el:3}],
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleSmiReceivers:
{ mkTrainingArguments : () => { let b = [1]; b.x=3; return [{arr:[1], el:3}, {arr:[1], el:3}] },
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleSmiReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [1]; b[100] = 3; return [{arr:[1], el:3}, {arr:b, el:3}] },
deoptingArguments : [{darr:[0.1], del:true}]
},
multipleDoubleReceivers:
{ mkTrainingArguments : () => { let b = [0.1]; b.x=0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[1], del:true}]
},
multipleDoubleReceiversPackedUnpacked:
{ mkTrainingArguments : () => { let b = [0.1]; b[100] = 0.3; return [{arr:[0.1], el:0.3}, {arr:b, el:0.3}] },
deoptingArguments : [{darr:[1], del:true}]
},
};
const functions = {
push_reliable: (a,g) => { let b = g(); return a.push(2, b); },
push_unreliable: (a,g) => { return a.push(2, g()); },
......@@ -121,6 +154,11 @@ const functions = {
shift_unreliable: (a,g) => { return a.shift(2, g()); }
}
const push_functions = {
push_reliable: (a,g) => { let b = g(); return a.push(2, b); },
push_unreliable: (a,g) => { return a.push(2, g()); },
}
Object.keys(checks).forEach(
key => {
let check = checks[key];
......@@ -134,3 +172,17 @@ Object.keys(checks).forEach(
}
}
);
Object.keys(no_speculation_checks).forEach(
key => {
let check = no_speculation_checks[key];
for (fnc in push_functions) {
runTest(functions[fnc], "test-spec-check-" + fnc + "-" + key, check.mkTrainingArguments);
// Test each deopting arg separately.
for (let deoptArg of check.deoptingArguments) {
runTest(functions[fnc], "testDeopt-spec-check-" + fnc + "-" + key, check.mkTrainingArguments, deoptArg, true);
}
}
}
);
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