[maglev] Restore the correct context for exception handlers

Ignition remembers the correct context to restore when entering an
exception handler by moving the context to an interpreter register
when entering a try block, and restoring it from there when unwinding
the frame and entering the catch block.

Maglev code has to do the same by taking the context from the
appropriate register for the handler's frame state.

Bug: v8:7700
Change-Id: I294fcccc845c660b2289b6d7b40f49f1aa46283d
Fixed: chromium:1359928
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3892352
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Jakob Linke <jgruber@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83181}
This commit is contained in:
Jakob Linke 2022-09-14 10:48:04 +02:00 committed by V8 LUCI CQ
parent c894fee0c7
commit 33e90400d0
4 changed files with 37 additions and 7 deletions

View File

@ -144,17 +144,19 @@ void MaglevGraphBuilder::BuildMergeStates() {
if (bytecode().handler_table_size() > 0) {
HandlerTable table(*bytecode().object());
for (int i = 0; i < table.NumberOfRangeEntries(); i++) {
int offset = table.GetRangeHandler(i);
const int offset = table.GetRangeHandler(i);
const interpreter::Register context_reg(table.GetRangeData(i));
const compiler::BytecodeLivenessState* liveness =
GetInLivenessFor(offset);
DCHECK_EQ(NumPredecessors(offset), 0);
DCHECK_NULL(merge_states_[offset]);
if (FLAG_trace_maglev_graph_building) {
std::cout << "- Creating exception merge state at @" << offset
<< std::endl;
<< ", context register r" << context_reg.index() << std::endl;
}
merge_states_[offset] = MergePointInterpreterFrameState::NewForCatchBlock(
*compilation_unit_, liveness, offset, graph_, is_inline());
*compilation_unit_, liveness, offset, context_reg, graph_,
is_inline());
}
}
}

View File

@ -16,7 +16,7 @@ MergePointInterpreterFrameState*
MergePointInterpreterFrameState::NewForCatchBlock(
const MaglevCompilationUnit& unit,
const compiler::BytecodeLivenessState* liveness, int handler_offset,
Graph* graph, bool is_inline) {
interpreter::Register context_register, Graph* graph, bool is_inline) {
Zone* const zone = unit.zone();
MergePointInterpreterFrameState* state =
zone->New<MergePointInterpreterFrameState>(
@ -49,8 +49,8 @@ MergePointInterpreterFrameState::NewForCatchBlock(
entry = state->NewExceptionPhi(zone, reg, handler_offset);
}
});
frame_state.context(unit) = state->NewExceptionPhi(
zone, interpreter::Register::current_context(), handler_offset);
frame_state.context(unit) =
state->NewExceptionPhi(zone, context_register, handler_offset);
frame_state.ForEachLocal(
unit, [&](ValueNode*& entry, interpreter::Register reg) {
entry = state->NewExceptionPhi(zone, reg, handler_offset);

View File

@ -483,7 +483,7 @@ class MergePointInterpreterFrameState {
static MergePointInterpreterFrameState* NewForCatchBlock(
const MaglevCompilationUnit& unit,
const compiler::BytecodeLivenessState* liveness, int handler_offset,
Graph* graph, bool is_inline);
interpreter::Register context_register, Graph* graph, bool is_inline);
// Merges an unmerged framestate with a possibly merged framestate into |this|
// framestate.

View File

@ -0,0 +1,28 @@
// 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: --allow-natives-syntax --no-concurrent-recompilation
function __f_0() {
var __v_1;
try {
class __c_0 extends (__v_4) {}
} catch {
console.log("soozie");
}
try {
Object.defineProperty(__v_2, 'x');
} catch {}
try {
console.log("foozie");
class __c_2 extends (eval('delete obj.x'), class {}) {}
} catch (__v_7) {
console.log("boozie");
__v_1 = __v_7;
}
}
%PrepareFunctionForOptimization(__f_0);
__f_0();
%OptimizeMaglevOnNextCall(__f_0);
__f_0();