[turbolev] Escape analysis [v8/v8 : main]

0 views
Skip to first unread message

Darius Mercadier (Gerrit)

unread,
2:02 AM (19 hours ago) 2:02 AM
to Marco Vitale, Hannes Payer, chrom...@appspot.gserviceaccount.com, android-bu...@system.gserviceaccount.com, v8-s...@luci-project-accounts.iam.gserviceaccount.com, cbruni...@chromium.org, pthier...@chromium.org, mlippau...@chromium.org, jgrube...@chromium.org, marja...@chromium.org, was...@google.com, v8-risc...@chromium.org, v8-ppc...@googlegroups.com, v8-mip...@googlegroups.com, devtools-...@chromium.org, dmercadi...@chromium.org, leszek...@chromium.org, v8-flag...@chromium.org, v8-re...@googlegroups.com, verwaes...@chromium.org, victorgo...@chromium.org
Attention needed from Darius Mercadier

Message from Darius Mercadier

Set Ready For Review

Open in Gerrit

Related details

Attention is currently required from:
  • Darius Mercadier
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I65626ba75f86c3cdb28593b4ef245de79fbd01eb
Gerrit-Change-Number: 6297953
Gerrit-PatchSet: 65
Gerrit-Owner: Darius Mercadier <dmerc...@chromium.org>
Gerrit-Reviewer: Darius Mercadier <dmerc...@chromium.org>
Gerrit-CC: Hannes Payer <hpa...@chromium.org>
Gerrit-CC: Marco Vitale <mrc...@chromium.org>
Gerrit-Attention: Darius Mercadier <dmerc...@chromium.org>
Gerrit-Comment-Date: Wed, 01 Jul 2026 06:02:43 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Darius Mercadier (Gerrit)

unread,
5:58 AM (15 hours ago) 5:58 AM
to Victor Gomes, Marco Vitale, Hannes Payer, chrom...@appspot.gserviceaccount.com, android-bu...@system.gserviceaccount.com, v8-s...@luci-project-accounts.iam.gserviceaccount.com, cbruni...@chromium.org, pthier...@chromium.org, mlippau...@chromium.org, jgrube...@chromium.org, marja...@chromium.org, was...@google.com, v8-risc...@chromium.org, v8-ppc...@googlegroups.com, v8-mip...@googlegroups.com, devtools-...@chromium.org, dmercadi...@chromium.org, leszek...@chromium.org, v8-flag...@chromium.org, v8-re...@googlegroups.com, verwaes...@chromium.org, victorgo...@chromium.org
Attention needed from Victor Gomes

Darius Mercadier added 1 comment

Patchset-level comments
File-level comment, Patchset 68 (Latest):
Darius Mercadier . resolved

PTAL! :)

Open in Gerrit

Related details

Attention is currently required from:
  • Victor Gomes
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: v8/v8
Gerrit-Branch: main
Gerrit-Change-Id: I65626ba75f86c3cdb28593b4ef245de79fbd01eb
Gerrit-Change-Number: 6297953
Gerrit-PatchSet: 68
Gerrit-Owner: Darius Mercadier <dmerc...@chromium.org>
Gerrit-Reviewer: Darius Mercadier <dmerc...@chromium.org>
Gerrit-Reviewer: Victor Gomes <victo...@chromium.org>
Gerrit-Attention: Victor Gomes <victo...@chromium.org>
Gerrit-Comment-Date: Wed, 01 Jul 2026 09:58:20 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Victor Gomes (Gerrit)

unread,
10:57 AM (10 hours ago) 10:57 AM
to Darius Mercadier, Marco Vitale, Hannes Payer, chrom...@appspot.gserviceaccount.com, android-bu...@system.gserviceaccount.com, v8-s...@luci-project-accounts.iam.gserviceaccount.com, cbruni...@chromium.org, pthier...@chromium.org, mlippau...@chromium.org, jgrube...@chromium.org, marja...@chromium.org, was...@google.com, v8-risc...@chromium.org, v8-ppc...@googlegroups.com, v8-mip...@googlegroups.com, devtools-...@chromium.org, dmercadi...@chromium.org, leszek...@chromium.org, v8-flag...@chromium.org, v8-re...@googlegroups.com, verwaes...@chromium.org, victorgo...@chromium.org
Attention needed from Darius Mercadier

Victor Gomes added 21 comments

Patchset-level comments
Victor Gomes . resolved

First quick pass. I haven't looked at the main file yet...

File src/compiler/turboshaft/snapshot-table.h
Line 193, Patchset 68 (Latest): void ThisStartNewSnapshot(base::Vector<const Snapshot> predecessors,
Victor Gomes . unresolved

What's the difference from this and the StartNewSnapshot above?

File src/compiler/turboshaft/turbolev-graph-builder.cc
Line 698, Patchset 68 (Latest): if (maglev_block->has_phi()) {
DCHECK(!maglev_block->is_exception_handler_block());
ComputePredecessorPermutations(maglev_block, turboshaft_block, false,
false);
}
Victor Gomes . unresolved

This change seems unrelated to this CL, maybe do it in another?

Line 710, Patchset 68 (Latest): bool ignore_last_predecessor) {
predecessor_permutation_.clear();

// This function is only called for loops that need a "single block
// predecessor" (from EmitLoopSinglePredecessorBlock). The backedge should
// always be skipped in thus cases. Additionally, this means that when
// even when {maglev_block} is a loop, {turboshaft_block} shouldn't and
// should instead be the new single forward predecessor of the loop.
DCHECK_EQ(skip_backedge, maglev_block->is_loop());
DCHECK(!turboshaft_block->IsLoop());

if (maglev_block->predecessor_count() == 1) {
// This block has a single predecessor ==> trivial.
predecessor_permutation_.push_back(0);
return;
}

DCHECK(maglev_block->has_state());
Victor Gomes . unresolved

Is this related to the current CL?

Line 1240, Patchset 68 (Latest): void MakeLoopPhi(maglev::ValueNode* phi,
const maglev::ProcessingState& state) {
DCHECK(phi->Is<maglev::Phi>());
DCHECK(__ current_block()->IsLoop());
DCHECK(state.block()->is_loop());
OpIndex first_phi_input;
if (state.block()->predecessor_count() > 2 ||
generator_analyzer_.HeaderIsBypassed(state.block())) {
// This loop has multiple forward edges in Maglev, so we should have
// created an intermediate block in Turboshaft, which will be the only
// predecessor of the Turboshaft loop, and from which we'll find the
// first input for this loop phi.
DCHECK_EQ(loop_phis_first_input_.size(),
static_cast<size_t>(state.block()->phis()->LengthForTest()));
DCHECK_GE(loop_phis_first_input_index_, 0);
DCHECK_LT(loop_phis_first_input_index_, loop_phis_first_input_.size());
DCHECK(loop_single_edge_predecessors_.contains(state.block()));
DCHECK_EQ(loop_single_edge_predecessors_[state.block()],
__ current_block()->LastPredecessor());
first_phi_input = loop_phis_first_input_[loop_phis_first_input_index_];
loop_phis_first_input_index_++;
} else {
DCHECK_EQ(phi->input_count(), 2);
DCHECK_EQ(state.block()->predecessor_count(), 2);
DCHECK(loop_phis_first_input_.empty());
first_phi_input = Map(phi->input(0));
}
RegisterRepresentation rep =
RegisterRepresentationFor(phi->value_representation());
SetMap(phi, __ PendingLoopPhi(first_phi_input, rep));
}
Victor Gomes . unresolved

Unrelated refactoring.

Line 3027, Patchset 68 (Latest): if (!node->is_used()) {
// TODO(dmercadier): we could make DCE to remove such unused nodes
// earlier.
return maglev::ProcessResult::kContinue;
}
Victor Gomes . unresolved

You removed the code that removes it in DCE. I guess it should still be valid?

Line 3041, Patchset 68 (Latest): if (size == 0) {
// TODO(dmercadier): DCE could also remove these nodes.
return maglev::ProcessResult::kContinue;
}
Victor Gomes . unresolved

Same here.

Line 6796, Patchset 68 (Latest): if (loop->has_phi()) {
for (maglev::Phi* maglev_phi : *loop->phis()) {
// Note that we've already emitted the backedge Goto, which means that
// we're currently not in a block, which means that we need to pass
// can_be_invalid=false to `Map`, otherwise it will think that we're
// currently emitting unreachable operations and return
// OpIndex::Invalid().
constexpr bool kIndexCanBeInvalid = false;
OpIndex phi_index = Map(maglev_phi, kIndexCanBeInvalid);
PendingLoopPhiOp& pending_phi =
__ output_graph().Get(phi_index).Cast<PendingLoopPhiOp>();
__ output_graph().Replace<PhiOp>(
phi_index,
base::VectorOf(
{pending_phi.first(),
Map(maglev_phi -> backedge_input(), kIndexCanBeInvalid)}),
pending_phi.rep);
}
Victor Gomes . unresolved

Not need to do this here...

Line 7287, Patchset 68 (Latest): // TODO: re-enable this DCHECK (it requires running DCE to remove unused
// AllocationBlock)
// DCHECK_IMPLIES(result == maglev::ProcessResult::kContinue &&
// !GraphBuildingNodeProcessor::Asm()
// .generating_unreachable_operations() &&
// maglev::IsValueNode(node->opcode()),
// IsMapped(node));
Victor Gomes . unresolved

You removed the code in DCE, why?

File src/maglev/maglev-compiler.cc
Line 237, Patchset 68 (Latest): processor(AnyUseMarkingProcessor{true});
Victor Gomes . unresolved

nit: you could create a constructor with default arg.

Line 260, Patchset 68 (Latest): processor(DeadNodeSweepingProcessor{true},
LiveRangeAndNextUseProcessor{compilation_info, graph,
Victor Gomes . unresolved

Same nit here.

File src/maglev/maglev-graph-printer.h
Line 66, Patchset 68 (Latest): return !is_maglev_ || phase_ != MaglevPhase::kAnyUseMarking;
Victor Gomes . unresolved

Did you negate this? Was it wrong before?
So in turbolev we can print sweepable dead phis in any use marking, but not in maglev?

File src/maglev/maglev-graph-processor.h
Line 212, Patchset 68 (Latest): BlockPostProcessResult post_action =
node_processor_.PostProcessBasicBlock(block);
USE(post_action);
DCHECK_EQ(post_action, BlockPostProcessResult::kContinue);
return;
Victor Gomes . unresolved

We didn't need to do this post action before?

maybe we can have a "abort" hook instead? ProcessAbortedBasicBlock(...) or something? Wdyt?

Line 100, Patchset 68 (Latest): node_index_(node_index) {}
Victor Gomes . unresolved
Why do you removed
```
DCHECK_IMPLIES(node_index != kNoNodeIndex, node_index >= 0);
```
?
Line 52, Patchset 68 (Latest):enum class BlockPreProcessResult {
kContinue, // Process exited normally.
kSkip, // Skip processing this blockand and do not call the following
// processors.
};

enum class BlockPostProcessResult {
kContinue, // Process exited normally.
kRevisitLoop, // Revisit the current loop, assuming that the current block
// ends with a JumpLoop (no MultiProcessor support).
};
Victor Gomes . unresolved

Nit: I would prefer kRevisitLoop inside BlockProcessResult to avoid type polution.

We can DCHECK inside the processor. Similar to ProcessResult, not all return values are valid in all situation.

kRevisitLoop is even already special, since it must be the result from a block ending with JumpLoop.

File src/maglev/maglev-graph.h
Line 98, Patchset 68 (Latest): int block_id(const BasicBlock* target) {
Victor Gomes . unresolved

We should have a better name for this. We already have a block id.
blocks_offset? not great, idk...

File src/maglev/maglev-post-hoc-optimizations-processors.h
Line 514, Patchset 68 (Latest): // if (!run_escape_analysis_) return ProcessResult::kContinue;
Victor Gomes . unresolved

Delete.

Line 496, Patchset 68 (Latest): if (!run_escape_analysis_) return ProcessResult::kContinue;
Victor Gomes . unresolved

Do you need this? we could remove unused AllocationBlocks here.

File src/maglev/turbolev-escape-analysis.cc
Line 993, Patchset 68 (Latest): return BlockPostProcessResult::kRevisitLoop;
Victor Gomes . unresolved

Have you check the cost (in compilation in the entire JS3) by just running the processor twice?

Line 1279, Patchset 68 (Latest): // Constant for simplicity.
ValueNode* dummy_cst;
switch (node->value_representation()) {
case ValueRepresentation::kTagged:
dummy_cst = data_.graph->GetSmiConstant(0);
break;
case ValueRepresentation::kInt32:
dummy_cst = data_.graph->GetInt32Constant(0);
break;
case ValueRepresentation::kUint32:
dummy_cst = data_.graph->GetUint32Constant(0);
break;
case ValueRepresentation::kFloat64:
dummy_cst = data_.graph->GetFloat64Constant(0);
break;
case ValueRepresentation::kHoleyFloat64:
dummy_cst = data_.graph->GetFloat64Constant(0);
break;
case ValueRepresentation::kIntPtr:
dummy_cst = data_.graph->GetIntPtrConstant(0);
break;
case ValueRepresentation::kRawPtr:
case ValueRepresentation::kNone:
UNREACHABLE();
}
node->OverwriteWithIdentityTo(dummy_cst);
Victor Gomes . unresolved

Maybe we should have an Unreachable value node?

You can also return kTruncate (+ maybe some massages).

Line 1632, Patchset 68 (Latest): // This phase will update some deopt frames, thus rendering the recorded deopt
// frames in the graph stale. We thus clear them now.
// Note that we don't repopulate eager_deopt_top_frames_ and
// lazy_deopt_top_frames_ in the graph since the Turbolev pipeline with this
// escape analysis will never read this again. In particular,
// UnwrapDeoptFrames (which is the main place where those frames are read)
// doesn't handle recursive (and mutually recursive) objects, and adding
// support for this would add a significant cost with no obvious benefits, so
// we just avoid calling UnwrapDeoptFrames.
data_.graph->ClearRecordedFrames();
Victor Gomes . unresolved

The main idea of the frames were to unwrap identities and conversion nodes in the frames.
One could walk the graph and visit the frames in the graphs, but since nodes share frames, we would walk the frames too many times. The recorded frames avoided that.

I don't think the escape analysis solve the unwrapping issue, so we might still need these frames (or walk the entire graph which is more expensive).

Open in Gerrit

Related details

Attention is currently required from:
  • Darius Mercadier
Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: v8/v8
    Gerrit-Branch: main
    Gerrit-Change-Id: I65626ba75f86c3cdb28593b4ef245de79fbd01eb
    Gerrit-Change-Number: 6297953
    Gerrit-PatchSet: 68
    Gerrit-Owner: Darius Mercadier <dmerc...@chromium.org>
    Gerrit-Reviewer: Darius Mercadier <dmerc...@chromium.org>
    Gerrit-Reviewer: Victor Gomes <victo...@chromium.org>
    Gerrit-CC: Hannes Payer <hpa...@chromium.org>
    Gerrit-CC: Marco Vitale <mrc...@chromium.org>
    Gerrit-Attention: Darius Mercadier <dmerc...@chromium.org>
    Gerrit-Comment-Date: Wed, 01 Jul 2026 14:57:47 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Darius Mercadier (Gerrit)

    unread,
    2:23 PM (7 hours ago) 2:23 PM
    to Victor Gomes, Marco Vitale, Hannes Payer, chrom...@appspot.gserviceaccount.com, android-bu...@system.gserviceaccount.com, v8-s...@luci-project-accounts.iam.gserviceaccount.com, cbruni...@chromium.org, pthier...@chromium.org, mlippau...@chromium.org, jgrube...@chromium.org, marja...@chromium.org, was...@google.com, v8-risc...@chromium.org, v8-ppc...@googlegroups.com, v8-mip...@googlegroups.com, devtools-...@chromium.org, dmercadi...@chromium.org, leszek...@chromium.org, v8-flag...@chromium.org, v8-re...@googlegroups.com, verwaes...@chromium.org, victorgo...@chromium.org
    Attention needed from Victor Gomes

    Darius Mercadier added 21 comments

    Patchset-level comments
    File-level comment, Patchset 69 (Latest):
    Darius Mercadier . resolved

    Thanks for the initial comments; I cleaned up :)

    (I've also cleared the CCs, because of a wrong rebase a bunch of folks got auto-cced)

    File src/compiler/turboshaft/snapshot-table.h
    Line 193, Patchset 68: void ThisStartNewSnapshot(base::Vector<const Snapshot> predecessors,
    Victor Gomes . resolved

    What's the difference from this and the StartNewSnapshot above?

    Darius Mercadier

    Whups, left over from debugging, sorry.

    File src/compiler/turboshaft/turbolev-graph-builder.cc
    Line 698, Patchset 68: if (maglev_block->has_phi()) {

    DCHECK(!maglev_block->is_exception_handler_block());
    ComputePredecessorPermutations(maglev_block, turboshaft_block, false,
    false);
    }
    Victor Gomes . resolved

    This change seems unrelated to this CL, maybe do it in another?

    Darius Mercadier

    Done

    Line 710, Patchset 68: bool ignore_last_predecessor) {

    predecessor_permutation_.clear();

    // This function is only called for loops that need a "single block
    // predecessor" (from EmitLoopSinglePredecessorBlock). The backedge should
    // always be skipped in thus cases. Additionally, this means that when
    // even when {maglev_block} is a loop, {turboshaft_block} shouldn't and
    // should instead be the new single forward predecessor of the loop.
    DCHECK_EQ(skip_backedge, maglev_block->is_loop());
    DCHECK(!turboshaft_block->IsLoop());

    if (maglev_block->predecessor_count() == 1) {
    // This block has a single predecessor ==> trivial.
    predecessor_permutation_.push_back(0);
    return;
    }

    DCHECK(maglev_block->has_state());
    Victor Gomes . resolved

    Is this related to the current CL?

    Darius Mercadier

    Not in its current state; reverted.

    Line 1240, Patchset 68: void MakeLoopPhi(maglev::ValueNode* phi,
    Victor Gomes . resolved

    Unrelated refactoring.

    Darius Mercadier

    Whups sorry, again because of this other Phi kind I added at some point and them removed :/

    Line 3027, Patchset 68: if (!node->is_used()) {

    // TODO(dmercadier): we could make DCE to remove such unused nodes
    // earlier.
    return maglev::ProcessResult::kContinue;
    }
    Victor Gomes . resolved

    You removed the code that removes it in DCE. I guess it should still be valid?

    Darius Mercadier

    You're right, I guess that for some reason the DCE code didn't work in my early prototypes, but it works now. I've re-enabled it and removed the bailouts here.

    Line 3041, Patchset 68: if (size == 0) {

    // TODO(dmercadier): DCE could also remove these nodes.
    return maglev::ProcessResult::kContinue;
    }
    Victor Gomes . resolved

    Same here.

    Darius Mercadier

    Done

    Line 6796, Patchset 68: if (loop->has_phi()) {

    for (maglev::Phi* maglev_phi : *loop->phis()) {
    // Note that we've already emitted the backedge Goto, which means that
    // we're currently not in a block, which means that we need to pass
    // can_be_invalid=false to `Map`, otherwise it will think that we're
    // currently emitting unreachable operations and return
    // OpIndex::Invalid().
    constexpr bool kIndexCanBeInvalid = false;
    OpIndex phi_index = Map(maglev_phi, kIndexCanBeInvalid);
    PendingLoopPhiOp& pending_phi =
    __ output_graph().Get(phi_index).Cast<PendingLoopPhiOp>();
    __ output_graph().Replace<PhiOp>(
    phi_index,
    base::VectorOf(
    {pending_phi.first(),
    Map(maglev_phi -> backedge_input(), kIndexCanBeInvalid)}),
    pending_phi.rep);
    }
    Victor Gomes . resolved

    Not need to do this here...

    Darius Mercadier

    Yea sorry about that; leftovers from a previous version that was adding a new kind of Phis :/

    Line 7287, Patchset 68: // TODO: re-enable this DCHECK (it requires running DCE to remove unused

    // AllocationBlock)
    // DCHECK_IMPLIES(result == maglev::ProcessResult::kContinue &&
    // !GraphBuildingNodeProcessor::Asm()
    // .generating_unreachable_operations() &&
    // maglev::IsValueNode(node->opcode()),
    // IsMapped(node));
    Victor Gomes . resolved

    You removed the code in DCE, why?

    Darius Mercadier

    Done

    File src/maglev/maglev-compiler.cc
    Line 237, Patchset 68: processor(AnyUseMarkingProcessor{true});
    Victor Gomes . resolved

    nit: you could create a constructor with default arg.

    Darius Mercadier

    Done

    Line 260, Patchset 68: processor(DeadNodeSweepingProcessor{true},
    LiveRangeAndNextUseProcessor{compilation_info, graph,
    Victor Gomes . resolved

    Same nit here.

    Darius Mercadier

    Done

    File src/maglev/maglev-graph-printer.h
    Line 66, Patchset 68: return !is_maglev_ || phase_ != MaglevPhase::kAnyUseMarking;
    Victor Gomes . unresolved

    Did you negate this? Was it wrong before?
    So in turbolev we can print sweepable dead phis in any use marking, but not in maglev?

    Darius Mercadier

    Yes it was wrong before. I could also move this to another CL.

    So in turbolev we can print sweepable dead phis in any use marking, but not in maglev?

    Yes, because the issue in Maglev is that a dead phi can have regalloc data for some of its inputs but not the other ones, and the printer doesn't like that. In Turbolev, we never allocate regalloc data, so this isn't an issue.

    File src/maglev/maglev-graph-processor.h
    Line 212, Patchset 68: BlockPostProcessResult post_action =

    node_processor_.PostProcessBasicBlock(block);
    USE(post_action);
    DCHECK_EQ(post_action, BlockPostProcessResult::kContinue);
    return;
    Victor Gomes . resolved

    We didn't need to do this post action before?

    maybe we can have a "abort" hook instead? ProcessAbortedBasicBlock(...) or something? Wdyt?

    Darius Mercadier

    Ah actually I've double-checked and this isn't needed anymore.

    The reasoning behind this post action is that we needed it a some point to close the current SnapshotTable snapshot, but now the escape analysis never returns `kAbort`, so we don't need to bother here. I've reverted this (here and later in the file).

    Line 100, Patchset 68: node_index_(node_index) {}
    Victor Gomes . resolved
    Why do you removed
    ```
    DCHECK_IMPLIES(node_index != kNoNodeIndex, node_index >= 0);
    ```
    ?
    Darius Mercadier

    Good question; reverted.

    Line 52, Patchset 68:enum class BlockPreProcessResult {

    kContinue, // Process exited normally.
    kSkip, // Skip processing this blockand and do not call the following
    // processors.
    };

    enum class BlockPostProcessResult {
    kContinue, // Process exited normally.
    kRevisitLoop, // Revisit the current loop, assuming that the current block
    // ends with a JumpLoop (no MultiProcessor support).
    };
    Victor Gomes . resolved

    Nit: I would prefer kRevisitLoop inside BlockProcessResult to avoid type polution.

    We can DCHECK inside the processor. Similar to ProcessResult, not all return values are valid in all situation.

    kRevisitLoop is even already special, since it must be the result from a block ending with JumpLoop.

    Darius Mercadier

    Ok sounds good, done.

    File src/maglev/maglev-graph.h
    Line 98, Patchset 68: int block_id(const BasicBlock* target) {
    Victor Gomes . resolved

    We should have a better name for this. We already have a block id.
    blocks_offset? not great, idk...

    Darius Mercadier

    Good point. I went with block_offset...

    File src/maglev/maglev-post-hoc-optimizations-processors.h
    Line 514, Patchset 68: // if (!run_escape_analysis_) return ProcessResult::kContinue;
    Victor Gomes . resolved

    Delete.

    Darius Mercadier

    Done

    Line 496, Patchset 68: if (!run_escape_analysis_) return ProcessResult::kContinue;
    Victor Gomes . resolved

    Do you need this? we could remove unused AllocationBlocks here.

    Darius Mercadier

    Yea not sure why I disabled this; I'm guessing that this was breaking an earlier version of the CL; now it works.

    File src/maglev/turbolev-escape-analysis.cc
    Line 993, Patchset 68: return BlockPostProcessResult::kRevisitLoop;
    Victor Gomes . unresolved

    Have you check the cost (in compilation in the entire JS3) by just running the processor twice?

    Darius Mercadier

    Will do.

    Line 1279, Patchset 68: // Constant for simplicity.
    Darius Mercadier

    I was a bit afraid of the kTruncate, but maybe it could simply work. If that's ok I'll do this in a follow up; there is a TODO above already.

    And if kTruncate doesn't work, the Unreachable makes sense so that a subsequent processor can detect this and take care of the truncation indeed.

    Line 1632, Patchset 68: // This phase will update some deopt frames, thus rendering the recorded deopt

    // frames in the graph stale. We thus clear them now.
    // Note that we don't repopulate eager_deopt_top_frames_ and
    // lazy_deopt_top_frames_ in the graph since the Turbolev pipeline with this
    // escape analysis will never read this again. In particular,
    // UnwrapDeoptFrames (which is the main place where those frames are read)
    // doesn't handle recursive (and mutually recursive) objects, and adding
    // support for this would add a significant cost with no obvious benefits, so
    // we just avoid calling UnwrapDeoptFrames.
    data_.graph->ClearRecordedFrames();
    Victor Gomes . unresolved

    The main idea of the frames were to unwrap identities and conversion nodes in the frames.
    One could walk the graph and visit the frames in the graphs, but since nodes share frames, we would walk the frames too many times. The recorded frames avoided that.

    I don't think the escape analysis solve the unwrapping issue, so we might still need these frames (or walk the entire graph which is more expensive).

    Darius Mercadier

    Ok, I could re-add this, but then we'll need UnwrapDeoptFrames to handle recursive objects... Do you want me to add a TODO?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Victor Gomes
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: v8/v8
    Gerrit-Branch: main
    Gerrit-Change-Id: I65626ba75f86c3cdb28593b4ef245de79fbd01eb
    Gerrit-Change-Number: 6297953
    Gerrit-PatchSet: 69
    Gerrit-Attention: Victor Gomes <victo...@chromium.org>
    Gerrit-Comment-Date: Wed, 01 Jul 2026 18:23:30 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Victor Gomes <victo...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages