1// Copyright 2021 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#if !V8_ENABLE_WEBASSEMBLY
6#error This header should only be included if WebAssembly is enabled.
7#endif  // !V8_ENABLE_WEBASSEMBLY
8
9#ifndef V8_COMPILER_WASM_INLINING_H_
10#define V8_COMPILER_WASM_INLINING_H_
11
12#include "src/compiler/graph-reducer.h"
13#include "src/compiler/js-graph.h"
14
15namespace v8 {
16namespace internal {
17
18namespace wasm {
19struct CompilationEnv;
20struct WasmModule;
21struct WasmFunction;
22class WireBytesStorage;
23}  // namespace wasm
24
25class BytecodeOffset;
26class OptimizedCompilationInfo;
27
28namespace compiler {
29
30class NodeOriginTable;
31class SourcePositionTable;
32struct WasmLoopInfo;
33
34// The WasmInliner provides the core graph inlining machinery for Webassembly
35// graphs.
36class WasmInliner final : public AdvancedReducer {
37 public:
38  WasmInliner(Editor* editor, wasm::CompilationEnv* env,
39              uint32_t function_index, SourcePositionTable* source_positions,
40              NodeOriginTable* node_origins, MachineGraph* mcgraph,
41              const wasm::WireBytesStorage* wire_bytes,
42              std::vector<WasmLoopInfo>* loop_infos, const char* debug_name)
43      : AdvancedReducer(editor),
44        env_(env),
45        function_index_(function_index),
46        source_positions_(source_positions),
47        node_origins_(node_origins),
48        mcgraph_(mcgraph),
49        wire_bytes_(wire_bytes),
50        loop_infos_(loop_infos),
51        debug_name_(debug_name),
52        initial_graph_size_(mcgraph->graph()->NodeCount()),
53        current_graph_size_(initial_graph_size_),
54        inlining_candidates_() {}
55
56  const char* reducer_name() const override { return "WasmInliner"; }
57
58  Reduction Reduce(Node* node) final;
59  void Finalize() final;
60
61  static bool graph_size_allows_inlining(size_t initial_graph_size) {
62    return initial_graph_size < 5000;
63  }
64
65 private:
66  struct CandidateInfo {
67    Node* node;
68    uint32_t inlinee_index;
69    int call_count;
70    int wire_byte_size;
71  };
72
73  struct LexicographicOrdering {
74    // Returns if c1 should be prioritized less than c2.
75    bool operator()(CandidateInfo& c1, CandidateInfo& c2) {
76      if (c1.call_count > c2.call_count) return false;
77      if (c2.call_count > c1.call_count) return true;
78      return c1.wire_byte_size > c2.wire_byte_size;
79    }
80  };
81
82  uint32_t FindOriginatingFunction(Node* call);
83
84  Zone* zone() const { return mcgraph_->zone(); }
85  CommonOperatorBuilder* common() const { return mcgraph_->common(); }
86  Graph* graph() const { return mcgraph_->graph(); }
87  MachineGraph* mcgraph() const { return mcgraph_; }
88  const wasm::WasmModule* module() const;
89
90  Reduction ReduceCall(Node* call);
91  void InlineCall(Node* call, Node* callee_start, Node* callee_end,
92                  const wasm::FunctionSig* inlinee_sig,
93                  size_t subgraph_min_node_id);
94  void InlineTailCall(Node* call, Node* callee_start, Node* callee_end);
95  void RewireFunctionEntry(Node* call, Node* callee_start);
96
97  int GetCallCount(Node* call);
98
99  void Trace(Node* call, int inlinee, const char* decision);
100  void Trace(const CandidateInfo& candidate, const char* decision);
101
102  wasm::CompilationEnv* const env_;
103  uint32_t function_index_;
104  SourcePositionTable* const source_positions_;
105  NodeOriginTable* const node_origins_;
106  MachineGraph* const mcgraph_;
107  const wasm::WireBytesStorage* const wire_bytes_;
108  std::vector<WasmLoopInfo>* const loop_infos_;
109  const char* debug_name_;
110  const size_t initial_graph_size_;
111  size_t current_graph_size_;
112  std::priority_queue<CandidateInfo, std::vector<CandidateInfo>,
113                      LexicographicOrdering>
114      inlining_candidates_;
115  std::unordered_set<Node*> seen_;
116  std::vector<uint32_t> inlined_functions_;
117  // Stores the graph size before an inlining was performed, to make it
118  // possible to map back from nodes to the function they came from.
119  // Guaranteed to have the same length as {inlined_functions_}.
120  std::vector<uint32_t> first_node_id_;
121};
122
123}  // namespace compiler
124}  // namespace internal
125}  // namespace v8
126
127#endif  // V8_COMPILER_WASM_INLINING_H_
128