11cb0ef41Sopenharmony_ci// Copyright 2022 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_ 61cb0ef41Sopenharmony_ci#define V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/compiler/bytecode-analysis.h" 91cb0ef41Sopenharmony_ci#include "src/maglev/maglev-basic-block.h" 101cb0ef41Sopenharmony_ci#include "src/maglev/maglev-graph.h" 111cb0ef41Sopenharmony_ci#include "src/maglev/maglev-interpreter-frame-state.h" 121cb0ef41Sopenharmony_ci#include "src/maglev/maglev-ir.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace v8 { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_cinamespace maglev { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci// The GraphProcessor takes a NodeProcessor, and applies it to each Node in the 191cb0ef41Sopenharmony_ci// Graph by calling NodeProcessor::Process on each Node. 201cb0ef41Sopenharmony_ci// 211cb0ef41Sopenharmony_ci// The GraphProcessor also keeps track of the current ProcessingState, including 221cb0ef41Sopenharmony_ci// the inferred corresponding InterpreterFrameState and (optionally) the state 231cb0ef41Sopenharmony_ci// at the most recent Checkpoint, and passes this to the Process method. 241cb0ef41Sopenharmony_ci// 251cb0ef41Sopenharmony_ci// It expects a NodeProcessor class with: 261cb0ef41Sopenharmony_ci// 271cb0ef41Sopenharmony_ci// // A function that processes the graph before the nodes are walked. 281cb0ef41Sopenharmony_ci// void PreProcessGraph(MaglevCompilationUnit*, Graph* graph); 291cb0ef41Sopenharmony_ci// 301cb0ef41Sopenharmony_ci// // A function that processes the graph after the nodes are walked. 311cb0ef41Sopenharmony_ci// void PostProcessGraph(MaglevCompilationUnit*, Graph* graph); 321cb0ef41Sopenharmony_ci// 331cb0ef41Sopenharmony_ci// // A function that processes each basic block before its nodes are walked. 341cb0ef41Sopenharmony_ci// void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block); 351cb0ef41Sopenharmony_ci// 361cb0ef41Sopenharmony_ci// // Process methods for each Node type. The GraphProcessor switches over 371cb0ef41Sopenharmony_ci// // the Node's opcode, casts it to the appropriate FooNode, and dispatches 381cb0ef41Sopenharmony_ci// // to NodeProcessor::Process. It's then up to the NodeProcessor to provide 391cb0ef41Sopenharmony_ci// // either distinct Process methods per Node type, or using templates or 401cb0ef41Sopenharmony_ci// // overloading as appropriate to group node processing. 411cb0ef41Sopenharmony_ci// void Process(FooNode* node, const ProcessingState& state) {} 421cb0ef41Sopenharmony_ci// 431cb0ef41Sopenharmony_citemplate <typename NodeProcessor> 441cb0ef41Sopenharmony_ciclass GraphProcessor; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciclass ProcessingState { 471cb0ef41Sopenharmony_ci public: 481cb0ef41Sopenharmony_ci explicit ProcessingState(MaglevCompilationUnit* compilation_unit, 491cb0ef41Sopenharmony_ci BlockConstIterator block_it) 501cb0ef41Sopenharmony_ci : compilation_unit_(compilation_unit), block_it_(block_it) {} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci // Disallow copies, since the underlying frame states stay mutable. 531cb0ef41Sopenharmony_ci ProcessingState(const ProcessingState&) = delete; 541cb0ef41Sopenharmony_ci ProcessingState& operator=(const ProcessingState&) = delete; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci BasicBlock* block() const { return *block_it_; } 571cb0ef41Sopenharmony_ci BasicBlock* next_block() const { return *(block_it_ + 1); } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci MaglevCompilationUnit* compilation_unit() const { return compilation_unit_; } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci int register_count() const { return compilation_unit_->register_count(); } 621cb0ef41Sopenharmony_ci int parameter_count() const { return compilation_unit_->parameter_count(); } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci MaglevGraphLabeller* graph_labeller() const { 651cb0ef41Sopenharmony_ci return compilation_unit_->graph_labeller(); 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci private: 691cb0ef41Sopenharmony_ci MaglevCompilationUnit* compilation_unit_; 701cb0ef41Sopenharmony_ci BlockConstIterator block_it_; 711cb0ef41Sopenharmony_ci}; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_citemplate <typename NodeProcessor> 741cb0ef41Sopenharmony_ciclass GraphProcessor { 751cb0ef41Sopenharmony_ci public: 761cb0ef41Sopenharmony_ci template <typename... Args> 771cb0ef41Sopenharmony_ci explicit GraphProcessor(MaglevCompilationUnit* compilation_unit, 781cb0ef41Sopenharmony_ci Args&&... args) 791cb0ef41Sopenharmony_ci : compilation_unit_(compilation_unit), 801cb0ef41Sopenharmony_ci node_processor_(std::forward<Args>(args)...) {} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci void ProcessGraph(Graph* graph) { 831cb0ef41Sopenharmony_ci graph_ = graph; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci node_processor_.PreProcessGraph(compilation_unit_, graph); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci for (block_it_ = graph->begin(); block_it_ != graph->end(); ++block_it_) { 881cb0ef41Sopenharmony_ci BasicBlock* block = *block_it_; 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci node_processor_.PreProcessBasicBlock(compilation_unit_, block); 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci if (block->has_phi()) { 931cb0ef41Sopenharmony_ci for (Phi* phi : *block->phis()) { 941cb0ef41Sopenharmony_ci node_processor_.Process(phi, GetCurrentState()); 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci for (node_it_ = block->nodes().begin(); node_it_ != block->nodes().end(); 991cb0ef41Sopenharmony_ci ++node_it_) { 1001cb0ef41Sopenharmony_ci Node* node = *node_it_; 1011cb0ef41Sopenharmony_ci ProcessNodeBase(node, GetCurrentState()); 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci ProcessNodeBase(block->control_node(), GetCurrentState()); 1051cb0ef41Sopenharmony_ci } 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci node_processor_.PostProcessGraph(compilation_unit_, graph); 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci NodeProcessor& node_processor() { return node_processor_; } 1111cb0ef41Sopenharmony_ci const NodeProcessor& node_processor() const { return node_processor_; } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci private: 1141cb0ef41Sopenharmony_ci ProcessingState GetCurrentState() { 1151cb0ef41Sopenharmony_ci return ProcessingState(compilation_unit_, block_it_); 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci void ProcessNodeBase(NodeBase* node, const ProcessingState& state) { 1191cb0ef41Sopenharmony_ci switch (node->opcode()) { 1201cb0ef41Sopenharmony_ci#define CASE(OPCODE) \ 1211cb0ef41Sopenharmony_ci case Opcode::k##OPCODE: \ 1221cb0ef41Sopenharmony_ci PreProcess(node->Cast<OPCODE>(), state); \ 1231cb0ef41Sopenharmony_ci node_processor_.Process(node->Cast<OPCODE>(), state); \ 1241cb0ef41Sopenharmony_ci break; 1251cb0ef41Sopenharmony_ci NODE_BASE_LIST(CASE) 1261cb0ef41Sopenharmony_ci#undef CASE 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci void PreProcess(NodeBase* node, const ProcessingState& state) {} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci int register_count() const { return compilation_unit_->register_count(); } 1331cb0ef41Sopenharmony_ci const compiler::BytecodeAnalysis& bytecode_analysis() const { 1341cb0ef41Sopenharmony_ci return compilation_unit_->bytecode_analysis(); 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci MaglevCompilationUnit* const compilation_unit_; 1381cb0ef41Sopenharmony_ci NodeProcessor node_processor_; 1391cb0ef41Sopenharmony_ci Graph* graph_; 1401cb0ef41Sopenharmony_ci BlockConstIterator block_it_; 1411cb0ef41Sopenharmony_ci NodeConstIterator node_it_; 1421cb0ef41Sopenharmony_ci}; 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci// A NodeProcessor that wraps multiple NodeProcessors, and forwards to each of 1451cb0ef41Sopenharmony_ci// them iteratively. 1461cb0ef41Sopenharmony_citemplate <typename... Processors> 1471cb0ef41Sopenharmony_ciclass NodeMultiProcessor; 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_citemplate <> 1501cb0ef41Sopenharmony_ciclass NodeMultiProcessor<> { 1511cb0ef41Sopenharmony_ci public: 1521cb0ef41Sopenharmony_ci void PreProcessGraph(MaglevCompilationUnit*, Graph* graph) {} 1531cb0ef41Sopenharmony_ci void PostProcessGraph(MaglevCompilationUnit*, Graph* graph) {} 1541cb0ef41Sopenharmony_ci void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block) {} 1551cb0ef41Sopenharmony_ci void Process(NodeBase* node, const ProcessingState& state) {} 1561cb0ef41Sopenharmony_ci}; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_citemplate <typename Processor, typename... Processors> 1591cb0ef41Sopenharmony_ciclass NodeMultiProcessor<Processor, Processors...> 1601cb0ef41Sopenharmony_ci : NodeMultiProcessor<Processors...> { 1611cb0ef41Sopenharmony_ci using Base = NodeMultiProcessor<Processors...>; 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci public: 1641cb0ef41Sopenharmony_ci template <typename Node> 1651cb0ef41Sopenharmony_ci void Process(Node* node, const ProcessingState& state) { 1661cb0ef41Sopenharmony_ci processor_.Process(node, state); 1671cb0ef41Sopenharmony_ci Base::Process(node, state); 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci void PreProcessGraph(MaglevCompilationUnit* unit, Graph* graph) { 1701cb0ef41Sopenharmony_ci processor_.PreProcessGraph(unit, graph); 1711cb0ef41Sopenharmony_ci Base::PreProcessGraph(unit, graph); 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci void PostProcessGraph(MaglevCompilationUnit* unit, Graph* graph) { 1741cb0ef41Sopenharmony_ci // Post process in reverse order because that kind of makes sense. 1751cb0ef41Sopenharmony_ci Base::PostProcessGraph(unit, graph); 1761cb0ef41Sopenharmony_ci processor_.PostProcessGraph(unit, graph); 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci void PreProcessBasicBlock(MaglevCompilationUnit* unit, BasicBlock* block) { 1791cb0ef41Sopenharmony_ci processor_.PreProcessBasicBlock(unit, block); 1801cb0ef41Sopenharmony_ci Base::PreProcessBasicBlock(unit, block); 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci private: 1841cb0ef41Sopenharmony_ci Processor processor_; 1851cb0ef41Sopenharmony_ci}; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_citemplate <typename... Processors> 1881cb0ef41Sopenharmony_ciusing GraphMultiProcessor = GraphProcessor<NodeMultiProcessor<Processors...>>; 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci} // namespace maglev 1911cb0ef41Sopenharmony_ci} // namespace internal 1921cb0ef41Sopenharmony_ci} // namespace v8 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci#endif // V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_ 195