[turbofan] Properly handle IfException projections on JSForInNext.

Don't ignore IfException (and IfSuccess) projections on JSForInNext
nodes during JSTypedLowering::ReduceJSForInNext, but instead rewrire
the IfException projection to the ForInFilter stub call, which can
throw exceptions in case of proxies.

R=yangguo@chromium.org
BUG=v8:6121

Review-Url: https://codereview.chromium.org/2761703002
Cr-Commit-Position: refs/heads/master@{#43925}
This commit is contained in:
bmeurer 2017-03-19 23:32:28 -07:00 committed by Commit bot
parent a2588a5ada
commit a93e5221d8
2 changed files with 35 additions and 0 deletions

View File

@ -2199,11 +2199,23 @@ Reduction JSTypedLowering::ReduceJSForInNext(Node* node) {
vfalse0 = efalse0 = if_false0 = graph()->NewNode(
common()->Call(desc), jsgraph()->HeapConstant(callable.code()), key,
receiver, context, frame_state, effect, if_false0);
// Update potential {IfException} uses of {node} to point to the ahove
// ForInFilter stub call node instead.
Node* if_exception = nullptr;
if (NodeProperties::IsExceptionalCall(node, &if_exception)) {
if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
NodeProperties::ReplaceControlInput(if_exception, vfalse0);
NodeProperties::ReplaceEffectInput(if_exception, efalse0);
Revisit(if_exception);
}
}
control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
ReplaceWithValue(node, node, effect, control);
// Morph the {node} into a Phi.
node->ReplaceInput(0, vtrue0);
node->ReplaceInput(1, vfalse0);
node->ReplaceInput(2, control);

View File

@ -0,0 +1,23 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
function foo(o) {
try {
for (var x in o) {}
return false;
} catch (e) {
return true;
}
}
var o = new Proxy({a:1},{
getOwnPropertyDescriptor(target, property) { throw target; }
});
assertTrue(foo(o));
assertTrue(foo(o));
%OptimizeFunctionOnNextCall(foo);
assertTrue(foo(o));