[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: Michael Stanton <mvstanton@chromium.org> Cr-Commit-Position: refs/heads/master@{#46755}
This commit is contained in:
parent
79bcb45447
commit
6ab0241d70
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user