[maglev] Also drop existing merges in a liveness hole

It's possible that various branches merged already with a value that's
in a liveness hole, but we only figure out later. If so, drop the merge
as well.

Bug: v8:7700, chromium:1403399

Change-Id: Ifd97e0c1959ffe51017e400fb028041047885a9c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4111932
Auto-Submit: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85013}
This commit is contained in:
Toon Verwaest 2022-12-23 14:52:22 +01:00 committed by V8 LUCI CQ
parent 0c7da9f0ee
commit b42d19ed11
2 changed files with 56 additions and 20 deletions

View File

@ -1894,6 +1894,25 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
return;
}
if (node != nullptr && !node->is_loadable() && !node->has_register()) {
// If we have a node already, but can't load it here, we must be in a
// liveness hole for it, so nuke the merge state.
// This can only happen for conversion nodes, as they can split and take
// over the liveness of the node they are converting.
// TODO(v8:7700): Overeager DCHECK.
// DCHECK(node->properties().is_conversion());
if (v8_flags.trace_maglev_regalloc) {
printing_visitor_->os() << " " << reg << " - can't load "
<< PrintNodeLabel(graph_labeller(), node)
<< ", dropping the merge\n";
}
// We always need to be able to restore values on JumpLoop since the value
// is definitely live at the loop header.
CHECK(!control->Is<JumpLoop>());
state = {nullptr, initialized_node};
return;
}
if (merge) {
// The register is already occupied with a different node. Figure out
// where that node is allocated on the incoming branch.
@ -1926,30 +1945,11 @@ void StraightForwardRegisterAllocator::MergeRegisterValues(ControlNode* control,
if (v8_flags.trace_maglev_regalloc) {
printing_visitor_->os()
<< " " << reg << " - can't load incoming "
<< PrintNodeLabel(graph_labeller(), node) << ", bailing out\n";
<< PrintNodeLabel(graph_labeller(), incoming) << ", bailing out\n";
}
return;
}
if (node != nullptr && !node->is_loadable() && !node->has_register()) {
// If we have a node already, but can't load it here, we must be in a
// liveness hole for it, so nuke the merge state.
// This can only happen for conversion nodes, as they can split and take
// over the liveness of the node they are converting.
// TODO(v8:7700): Overeager DCHECK.
// DCHECK(node->properties().is_conversion());
if (v8_flags.trace_maglev_regalloc) {
printing_visitor_->os() << " " << reg << " - can't load "
<< PrintNodeLabel(graph_labeller(), node)
<< ", dropping the merge\n";
}
// We always need to be able to restore values on JumpLoop since the value
// is definitely live at the loop header.
CHECK(!control->Is<JumpLoop>());
state = {nullptr, initialized_node};
return;
}
const size_t size = sizeof(RegisterMerge) +
predecessor_count * sizeof(compiler::AllocatedOperand);
void* buffer = compilation_info_->zone()->Allocate<void*>(size);

View File

@ -0,0 +1,36 @@
// Copyright 2022 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: --maglev --allow-natives-syntax
function __f_0() {
for (let __v_3 = 0; __v_3 < 52; ++__v_3) {
let __v_4 = __v_3 | 0;
switch (__v_4) {
case 28:
if (__v_3 != null && typeof __v_3 == "object") {
try {
Object.defineProperty( {
get: function () {
({get: function () {
return __v_4;
}})
}
});
} catch (e) {}
}
case 29:
case 31:
case 32:
case 33:
__v_4 += 1;
case 34:
}
}
}
%PrepareFunctionForOptimization(__f_0);
__f_0();
%OptimizeMaglevOnNextCall(__f_0);
__f_0();