[turbofan] Handle exceptional edges in ReduceArrayForEach.
This adds handling for exceptional control projections when lowering calls to {Array.prototype.forEach} in the call reducer. R=jarin@chromium.org TEST=mjsunit/optimized-foreach BUG=v8:1956 Change-Id: I282048b203814cbc1c90df983879578b210f92fb Reviewed-on: https://chromium-review.googlesource.com/574542 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#46834}
This commit is contained in:
parent
f4867154c4
commit
d07365f9de
@ -524,9 +524,6 @@ Reduction JSCallReducer::ReduceArrayForEach(Handle<JSFunction> function,
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
// TODO(danno): forEach can throw. Hook up exceptional edges.
|
||||
if (NodeProperties::IsExceptionalCall(node)) return NoChange();
|
||||
|
||||
// Install code dependencies on the {receiver} prototype maps and the
|
||||
// global array protector cell.
|
||||
dependencies()->AssumePropertyCell(factory()->array_protector());
|
||||
@ -625,6 +622,16 @@ Reduction JSCallReducer::ReduceArrayForEach(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);
|
||||
}
|
||||
|
||||
if (IsHoleyElementsKind(kind)) {
|
||||
Node* after_call_control = control;
|
||||
Node* after_call_effect = effect;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
// Flags: --allow-natives-syntax --expose-gc --turbo-inline-array-builtins
|
||||
|
||||
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];
|
||||
|
||||
@ -217,6 +217,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.forEach 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 sum = function(v,i,o) {
|
||||
result += v;
|
||||
if (i == 1 && deopt) {
|
||||
%DeoptimizeFunction(lazyDeopt);
|
||||
throw "some exception";
|
||||
}
|
||||
};
|
||||
%NeverOptimizeFunction(sum);
|
||||
var result = 0;
|
||||
try {
|
||||
a.forEach(sum);
|
||||
} catch (e) {
|
||||
assertEquals("some exception", e)
|
||||
result += 100;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
assertEquals(10, lazyDeopt(false));
|
||||
assertEquals(10, lazyDeopt(false));
|
||||
assertEquals(103, lazyDeopt(true));
|
||||
assertEquals(103, lazyDeopt(true));
|
||||
%OptimizeFunctionOnNextCall(lazyDeopt);
|
||||
assertEquals(10, lazyDeopt(false));
|
||||
assertEquals(103, lazyDeopt(true));
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var re = /Array\.forEach/;
|
||||
var lazyDeopt = function(deopt) {
|
||||
|
Loading…
Reference in New Issue
Block a user