Commit 6ab0241d authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[turbofan] Handle exceptional edges in ReduceArrayMap.

This adds handling for exceptional control projections when lowering
calls to {Array.prototype.map} in the call reducer.

R=mvstanton@chromium.org
TEST=mjsunit/optimized-map
BUG=v8:1956

Change-Id: If39ee836bbc3406a7fca4bad0d2c9321130cae2a
Reviewed-on: https://chromium-review.googlesource.com/575928
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46755}
parent 79bcb454
......@@ -683,9 +683,6 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
return NoChange();
}
// TODO(danno): map can throw. Hook up exceptional edges.
if (NodeProperties::IsExceptionalCall(node)) return NoChange();
// We want the input to be a generic Array.
const int map_index = Context::ArrayMapIndex(kind);
Handle<JSFunction> handle_constructor(
......@@ -722,6 +719,8 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
receiver, effect, control);
// This array should be HOLEY_SMI_ELEMENTS because of the non-zero length.
// Even though {JSCreateArray} is not marked as {kNoThrow}, we can elide the
// exceptional projections because it cannot throw with the given parameters.
Node* a = control = effect = graph()->NewNode(
javascript()->CreateArray(1, Handle<AllocationSite>::null()),
array_constructor, array_constructor, original_length, context,
......@@ -799,6 +798,16 @@ Reduction JSCallReducer::ReduceArrayMap(Handle<JSFunction> function,
javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k,
receiver, context, frame_state, effect, control);
// Update potential {IfException} uses of {node} to point to the above
// JavaScript call node within the loop instead.
Node* on_exception = nullptr;
if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
NodeProperties::ReplaceControlInput(on_exception, control);
NodeProperties::ReplaceEffectInput(on_exception, effect);
control = graph()->NewNode(common()->IfSuccess(), control);
Revisit(on_exception);
}
Handle<Map> double_map(Map::cast(
native_context()->get(Context::ArrayMapIndex(HOLEY_DOUBLE_ELEMENTS))));
Handle<Map> fast_map(
......
......@@ -5,7 +5,7 @@
// Flags: --allow-natives-syntax --expose-gc --turbo-inline-array-builtins
// Flags: --opt --no-always-opt --no-stress-fullcodegen
var a = [0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0];
var a = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,0,0];
var b = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
......@@ -227,6 +227,37 @@ var c = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
lazyDeopt();
})();
// Call to a.map is done inside a try-catch block and the callback function
// being called throws into a deoptimized caller function.
(function TestThrowIntoDeoptimizedOuter() {
var a = [1,2,3,4];
var lazyDeopt = function(deopt) {
var callback = function(v,i,o) {
if (i == 1 && deopt) {
%DeoptimizeFunction(lazyDeopt);
throw "some exception";
}
return 2 * v;
};
%NeverOptimizeFunction(callback);
var result = 0;
try {
result = a.map(callback);
} catch (e) {
assertEquals("some exception", e)
result = "nope";
}
return result;
}
assertEquals([2,4,6,8], lazyDeopt(false));
assertEquals([2,4,6,8], lazyDeopt(false));
assertEquals("nope", lazyDeopt(true));
assertEquals("nope", lazyDeopt(true));
%OptimizeFunctionOnNextCall(lazyDeopt);
assertEquals([2,4,6,8], lazyDeopt(false));
assertEquals("nope", lazyDeopt(true));
})();
(function() {
var re = /Array\.map/;
var lazyDeopt = function(deopt) {
......
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