• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
6 #define V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
7 
8 #include "src/compiler/bytecode-analysis.h"
9 #include "src/maglev/maglev-basic-block.h"
10 #include "src/maglev/maglev-graph.h"
11 #include "src/maglev/maglev-interpreter-frame-state.h"
12 #include "src/maglev/maglev-ir.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace maglev {
17 
18 // The GraphProcessor takes a NodeProcessor, and applies it to each Node in the
19 // Graph by calling NodeProcessor::Process on each Node.
20 //
21 // The GraphProcessor also keeps track of the current ProcessingState, including
22 // the inferred corresponding InterpreterFrameState and (optionally) the state
23 // at the most recent Checkpoint, and passes this to the Process method.
24 //
25 // It expects a NodeProcessor class with:
26 //
27 //   // A function that processes the graph before the nodes are walked.
28 //   void PreProcessGraph(MaglevCompilationUnit*, Graph* graph);
29 //
30 //   // A function that processes the graph after the nodes are walked.
31 //   void PostProcessGraph(MaglevCompilationUnit*, Graph* graph);
32 //
33 //   // A function that processes each basic block before its nodes are walked.
34 //   void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block);
35 //
36 //   // Process methods for each Node type. The GraphProcessor switches over
37 //   // the Node's opcode, casts it to the appropriate FooNode, and dispatches
38 //   // to NodeProcessor::Process. It's then up to the NodeProcessor to provide
39 //   // either distinct Process methods per Node type, or using templates or
40 //   // overloading as appropriate to group node processing.
41 //   void Process(FooNode* node, const ProcessingState& state) {}
42 //
43 template <typename NodeProcessor>
44 class GraphProcessor;
45 
46 class ProcessingState {
47  public:
ProcessingState(MaglevCompilationUnit * compilation_unit,BlockConstIterator block_it)48   explicit ProcessingState(MaglevCompilationUnit* compilation_unit,
49                            BlockConstIterator block_it)
50       : compilation_unit_(compilation_unit), block_it_(block_it) {}
51 
52   // Disallow copies, since the underlying frame states stay mutable.
53   ProcessingState(const ProcessingState&) = delete;
54   ProcessingState& operator=(const ProcessingState&) = delete;
55 
block()56   BasicBlock* block() const { return *block_it_; }
next_block()57   BasicBlock* next_block() const { return *(block_it_ + 1); }
58 
compilation_unit()59   MaglevCompilationUnit* compilation_unit() const { return compilation_unit_; }
60 
register_count()61   int register_count() const { return compilation_unit_->register_count(); }
parameter_count()62   int parameter_count() const { return compilation_unit_->parameter_count(); }
63 
graph_labeller()64   MaglevGraphLabeller* graph_labeller() const {
65     return compilation_unit_->graph_labeller();
66   }
67 
68  private:
69   MaglevCompilationUnit* compilation_unit_;
70   BlockConstIterator block_it_;
71 };
72 
73 template <typename NodeProcessor>
74 class GraphProcessor {
75  public:
76   template <typename... Args>
GraphProcessor(MaglevCompilationUnit * compilation_unit,Args &&...args)77   explicit GraphProcessor(MaglevCompilationUnit* compilation_unit,
78                           Args&&... args)
79       : compilation_unit_(compilation_unit),
80         node_processor_(std::forward<Args>(args)...) {}
81 
ProcessGraph(Graph * graph)82   void ProcessGraph(Graph* graph) {
83     graph_ = graph;
84 
85     node_processor_.PreProcessGraph(compilation_unit_, graph);
86 
87     for (block_it_ = graph->begin(); block_it_ != graph->end(); ++block_it_) {
88       BasicBlock* block = *block_it_;
89 
90       node_processor_.PreProcessBasicBlock(compilation_unit_, block);
91 
92       if (block->has_phi()) {
93         for (Phi* phi : *block->phis()) {
94           node_processor_.Process(phi, GetCurrentState());
95         }
96       }
97 
98       for (node_it_ = block->nodes().begin(); node_it_ != block->nodes().end();
99            ++node_it_) {
100         Node* node = *node_it_;
101         ProcessNodeBase(node, GetCurrentState());
102       }
103 
104       ProcessNodeBase(block->control_node(), GetCurrentState());
105     }
106 
107     node_processor_.PostProcessGraph(compilation_unit_, graph);
108   }
109 
node_processor()110   NodeProcessor& node_processor() { return node_processor_; }
node_processor()111   const NodeProcessor& node_processor() const { return node_processor_; }
112 
113  private:
GetCurrentState()114   ProcessingState GetCurrentState() {
115     return ProcessingState(compilation_unit_, block_it_);
116   }
117 
ProcessNodeBase(NodeBase * node,const ProcessingState & state)118   void ProcessNodeBase(NodeBase* node, const ProcessingState& state) {
119     switch (node->opcode()) {
120 #define CASE(OPCODE)                                      \
121   case Opcode::k##OPCODE:                                 \
122     PreProcess(node->Cast<OPCODE>(), state);              \
123     node_processor_.Process(node->Cast<OPCODE>(), state); \
124     break;
125       NODE_BASE_LIST(CASE)
126 #undef CASE
127     }
128   }
129 
PreProcess(NodeBase * node,const ProcessingState & state)130   void PreProcess(NodeBase* node, const ProcessingState& state) {}
131 
register_count()132   int register_count() const { return compilation_unit_->register_count(); }
bytecode_analysis()133   const compiler::BytecodeAnalysis& bytecode_analysis() const {
134     return compilation_unit_->bytecode_analysis();
135   }
136 
137   MaglevCompilationUnit* const compilation_unit_;
138   NodeProcessor node_processor_;
139   Graph* graph_;
140   BlockConstIterator block_it_;
141   NodeConstIterator node_it_;
142 };
143 
144 // A NodeProcessor that wraps multiple NodeProcessors, and forwards to each of
145 // them iteratively.
146 template <typename... Processors>
147 class NodeMultiProcessor;
148 
149 template <>
150 class NodeMultiProcessor<> {
151  public:
PreProcessGraph(MaglevCompilationUnit *,Graph * graph)152   void PreProcessGraph(MaglevCompilationUnit*, Graph* graph) {}
PostProcessGraph(MaglevCompilationUnit *,Graph * graph)153   void PostProcessGraph(MaglevCompilationUnit*, Graph* graph) {}
PreProcessBasicBlock(MaglevCompilationUnit *,BasicBlock * block)154   void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block) {}
Process(NodeBase * node,const ProcessingState & state)155   void Process(NodeBase* node, const ProcessingState& state) {}
156 };
157 
158 template <typename Processor, typename... Processors>
159 class NodeMultiProcessor<Processor, Processors...>
160     : NodeMultiProcessor<Processors...> {
161   using Base = NodeMultiProcessor<Processors...>;
162 
163  public:
164   template <typename Node>
Process(Node * node,const ProcessingState & state)165   void Process(Node* node, const ProcessingState& state) {
166     processor_.Process(node, state);
167     Base::Process(node, state);
168   }
PreProcessGraph(MaglevCompilationUnit * unit,Graph * graph)169   void PreProcessGraph(MaglevCompilationUnit* unit, Graph* graph) {
170     processor_.PreProcessGraph(unit, graph);
171     Base::PreProcessGraph(unit, graph);
172   }
PostProcessGraph(MaglevCompilationUnit * unit,Graph * graph)173   void PostProcessGraph(MaglevCompilationUnit* unit, Graph* graph) {
174     // Post process in reverse order because that kind of makes sense.
175     Base::PostProcessGraph(unit, graph);
176     processor_.PostProcessGraph(unit, graph);
177   }
PreProcessBasicBlock(MaglevCompilationUnit * unit,BasicBlock * block)178   void PreProcessBasicBlock(MaglevCompilationUnit* unit, BasicBlock* block) {
179     processor_.PreProcessBasicBlock(unit, block);
180     Base::PreProcessBasicBlock(unit, block);
181   }
182 
183  private:
184   Processor processor_;
185 };
186 
187 template <typename... Processors>
188 using GraphMultiProcessor = GraphProcessor<NodeMultiProcessor<Processors...>>;
189 
190 }  // namespace maglev
191 }  // namespace internal
192 }  // namespace v8
193 
194 #endif  // V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
195