v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
analyzer-iterator.h
Go to the documentation of this file.
1
// Copyright 2023 the V8 project authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef V8_COMPILER_TURBOSHAFT_ANALYZER_ITERATOR_H_
6
#define V8_COMPILER_TURBOSHAFT_ANALYZER_ITERATOR_H_
7
8
#include "
src/base/logging.h
"
9
#include "
src/compiler/turboshaft/graph.h
"
10
#include "
src/compiler/turboshaft/index.h
"
11
#include "
src/compiler/turboshaft/loop-finder.h
"
12
#include "
src/compiler/turboshaft/operations.h
"
13
#include "
src/compiler/turboshaft/sidetable.h
"
14
15
namespace
v8::internal::compiler::turboshaft
{
16
17
// AnalyzerIterator provides methods to iterate forward a Graph in a way that is
18
// efficient for the SnapshotTable: blocks that are close in the graphs will be
19
// visited somewhat consecutively (which means that the SnapshotTable shouldn't
20
// have to travel far).
21
//
22
// To understand why this is important, consider the following graph:
23
//
24
// B1 <------
25
// |\ |
26
// | \ |
27
// | v |
28
// | B27---
29
// v
30
// B2 <------
31
// |\ |
32
// | \ |
33
// | v |
34
// | B26---
35
// v
36
// B3 <------
37
// |\ |
38
// | \ |
39
// | v |
40
// | B25---
41
// v
42
// ...
43
//
44
// If we iterate its blocks in increasing ID order, then we'll visit B1, B2,
45
// B3... and only afterwards will we visit the Backedges. If said backedges can
46
// update the loop headers snapshots, then when visiting B25, we'll decide to
47
// revisit starting from B3, and will revisit everything after, then same thing
48
// for B26 after which we'll start over from B2 (and thus even revisit B3 and
49
// B25), etc, leading to a quadratic (in the number of blocks) analysis.
50
//
51
// Instead, the visitation order offered by AnalyzerIterator is a BFS in the
52
// dominator tree (ie, after visiting a node, AnalyzerIterator visit the nodes
53
// it dominates), with an subtlety for loops: when a node dominates multiple
54
// nodes, successors that are in the same loop as the current node are visited
55
// before nodes that are in outer loops.
56
// In the example above, the visitation order would thus be B1, B27, B2, B26,
57
// B3, B25.
58
//
59
// The MarkLoopForRevisit method can be used when visiting a backedge to
60
// instruct AnalyzerIterator that the loop to which this backedge belongs should
61
// be revisited. All of the blocks of this loop will then be revisited.
62
//
63
// Implementation details for revisitation of loops:
64
//
65
// In order to avoid visiting loop exits (= blocks whose dominator is in a loop
66
// but which aren't themselves in the loop) multiple times, the stack of Blocks
67
// to visit contains pairs of "block, generation". Additionally, we have a
68
// global {current_generation_} counter, which is incremented when we revisit a
69
// loop. When visiting a block, we record in {visited_} that it has been visited
70
// at {current_generation_}. When we pop a block from the stack and its
71
// "generation" field is less than what is recorded in {visited_}, then we skip
72
// it. On the other hand, if its "generation" field is greater than the one
73
// recorded in {visited_}, it means that we've revisited a loop since the last
74
// time we visited this block, so we should revisit it as well.
75
76
class
V8_EXPORT_PRIVATE
AnalyzerIterator
{
77
public
:
78
AnalyzerIterator
(
Zone
*
phase_zone
,
const
Graph
& graph,
79
const
LoopFinder
& loop_finder)
80
:
graph_
(graph),
81
loop_finder_(loop_finder),
82
visited_
(graph.block_count(), kNotVisitedGeneration,
phase_zone
),
83
stack_(
phase_zone
) {
84
stack_.push_back({&graph.StartBlock(), kGenerationForFirstVisit});
85
}
86
87
bool
HasNext
()
const
{
88
DCHECK_IMPLIES
(!stack_.empty(), !IsOutdated(stack_.back()));
89
return
!stack_.empty();
90
}
91
const
Block
* Next();
92
// Schedule the loop pointed to by the current block (as a backedge)
93
// to be revisited on the next iteration.
94
void
MarkLoopForRevisit();
95
// Schedule the loop pointed to by the current block (as a backedge) to be
96
// revisited on the next iteration but skip the loop header.
97
void
MarkLoopForRevisitSkipHeader();
98
99
private
:
100
struct
StackNode
{
101
const
Block
*
block
;
102
uint64_t
generation
;
103
};
104
static
constexpr
uint64_t kNotVisitedGeneration = 0;
105
static
constexpr
uint64_t kGenerationForFirstVisit = 1;
106
107
void
PopOutdated();
108
bool
IsOutdated
(
StackNode
node)
const
{
109
return
visited_
[node.block->index()] >= node.generation;
110
}
111
112
const
Graph
&
graph_
;
113
const
LoopFinder
&
loop_finder_
;
114
115
uint64_t current_generation_ = kGenerationForFirstVisit;
116
117
// The last block returned by Next.
118
StackNode
curr_ = {
nullptr
, 0};
119
120
// {visited_} maps BlockIndex to the generation they were visited with. If a
121
// Block has been visited with a generation `n`, then we never want to revisit
122
// it with a generation `k` when `k <= n`.
123
FixedBlockSidetable<uint64_t>
visited_
;
124
125
// The stack of blocks that are left to visit. We maintain the invariant that
126
// the .back() of {stack_} is never out-dated (ie, its generation is always
127
// greater than the generation for its node recorded in {visited_}), so that
128
// "Next" can simply check whether {stack_} is empty or not.
129
ZoneVector<StackNode>
stack_
;
130
};
131
132
}
// namespace v8::internal::compiler::turboshaft
133
134
#endif
// V8_COMPILER_TURBOSHAFT_ANALYZER_ITERATOR_H_
phase_zone
Zone * phase_zone
Definition
add-type-assertions-reducer.cc:18
v8::internal::ZoneVector
Definition
zone-containers.h:53
v8::internal::Zone
Definition
zone.h:43
v8::internal::compiler::turboshaft::AnalyzerIterator
Definition
analyzer-iterator.h:76
v8::internal::compiler::turboshaft::AnalyzerIterator::loop_finder_
const LoopFinder & loop_finder_
Definition
analyzer-iterator.h:113
v8::internal::compiler::turboshaft::AnalyzerIterator::visited_
FixedBlockSidetable< uint64_t > visited_
Definition
analyzer-iterator.h:123
v8::internal::compiler::turboshaft::AnalyzerIterator::graph_
const Graph & graph_
Definition
analyzer-iterator.h:112
v8::internal::compiler::turboshaft::AnalyzerIterator::stack_
ZoneVector< StackNode > stack_
Definition
analyzer-iterator.h:129
v8::internal::compiler::turboshaft::AnalyzerIterator::HasNext
bool HasNext() const
Definition
analyzer-iterator.h:87
v8::internal::compiler::turboshaft::AnalyzerIterator::AnalyzerIterator
AnalyzerIterator(Zone *phase_zone, const Graph &graph, const LoopFinder &loop_finder)
Definition
analyzer-iterator.h:78
v8::internal::compiler::turboshaft::AnalyzerIterator::IsOutdated
bool IsOutdated(StackNode node) const
Definition
analyzer-iterator.h:108
v8::internal::compiler::turboshaft::Block
Definition
graph.h:306
v8::internal::compiler::turboshaft::FixedBlockSidetable
Definition
sidetable.h:121
v8::internal::compiler::turboshaft::Graph
Definition
graph.h:578
v8::internal::compiler::turboshaft::LoopFinder
Definition
loop-finder.h:15
graph.h
index.h
loop-finder.h
v8::internal::compiler::turboshaft
Definition
builtins.h:33
operations.h
visited_
HeapObjectSet *const visited_
Definition
read-only-promotion.cc:295
sidetable.h
logging.h
DCHECK_IMPLIES
#define DCHECK_IMPLIES(v1, v2)
Definition
logging.h:493
V8_EXPORT_PRIVATE
#define V8_EXPORT_PRIVATE
Definition
macros.h:460
v8::internal::compiler::turboshaft::AnalyzerIterator::StackNode
Definition
analyzer-iterator.h:100
v8::internal::compiler::turboshaft::AnalyzerIterator::StackNode::generation
uint64_t generation
Definition
analyzer-iterator.h:102
v8::internal::compiler::turboshaft::AnalyzerIterator::StackNode::block
const Block * block
Definition
analyzer-iterator.h:101
graph_
TFGraph * graph_
Definition
wasm-inlining-into-js.cc:372
src
compiler
turboshaft
analyzer-iterator.h
Generated on Sun Apr 6 2025 21:08:52 for v8 by
1.12.0