11cb0ef41Sopenharmony_ci// Copyright 2021 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#if !V8_ENABLE_WEBASSEMBLY
61cb0ef41Sopenharmony_ci#error This header should only be included if WebAssembly is enabled.
71cb0ef41Sopenharmony_ci#endif  // !V8_ENABLE_WEBASSEMBLY
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_WASM_INLINING_H_
101cb0ef41Sopenharmony_ci#define V8_COMPILER_WASM_INLINING_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "src/compiler/graph-reducer.h"
131cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace v8 {
161cb0ef41Sopenharmony_cinamespace internal {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace wasm {
191cb0ef41Sopenharmony_cistruct CompilationEnv;
201cb0ef41Sopenharmony_cistruct WasmModule;
211cb0ef41Sopenharmony_cistruct WasmFunction;
221cb0ef41Sopenharmony_ciclass WireBytesStorage;
231cb0ef41Sopenharmony_ci}  // namespace wasm
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciclass BytecodeOffset;
261cb0ef41Sopenharmony_ciclass OptimizedCompilationInfo;
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cinamespace compiler {
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciclass NodeOriginTable;
311cb0ef41Sopenharmony_ciclass SourcePositionTable;
321cb0ef41Sopenharmony_cistruct WasmLoopInfo;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci// The WasmInliner provides the core graph inlining machinery for Webassembly
351cb0ef41Sopenharmony_ci// graphs.
361cb0ef41Sopenharmony_ciclass WasmInliner final : public AdvancedReducer {
371cb0ef41Sopenharmony_ci public:
381cb0ef41Sopenharmony_ci  WasmInliner(Editor* editor, wasm::CompilationEnv* env,
391cb0ef41Sopenharmony_ci              uint32_t function_index, SourcePositionTable* source_positions,
401cb0ef41Sopenharmony_ci              NodeOriginTable* node_origins, MachineGraph* mcgraph,
411cb0ef41Sopenharmony_ci              const wasm::WireBytesStorage* wire_bytes,
421cb0ef41Sopenharmony_ci              std::vector<WasmLoopInfo>* loop_infos, const char* debug_name)
431cb0ef41Sopenharmony_ci      : AdvancedReducer(editor),
441cb0ef41Sopenharmony_ci        env_(env),
451cb0ef41Sopenharmony_ci        function_index_(function_index),
461cb0ef41Sopenharmony_ci        source_positions_(source_positions),
471cb0ef41Sopenharmony_ci        node_origins_(node_origins),
481cb0ef41Sopenharmony_ci        mcgraph_(mcgraph),
491cb0ef41Sopenharmony_ci        wire_bytes_(wire_bytes),
501cb0ef41Sopenharmony_ci        loop_infos_(loop_infos),
511cb0ef41Sopenharmony_ci        debug_name_(debug_name),
521cb0ef41Sopenharmony_ci        initial_graph_size_(mcgraph->graph()->NodeCount()),
531cb0ef41Sopenharmony_ci        current_graph_size_(initial_graph_size_),
541cb0ef41Sopenharmony_ci        inlining_candidates_() {}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  const char* reducer_name() const override { return "WasmInliner"; }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  Reduction Reduce(Node* node) final;
591cb0ef41Sopenharmony_ci  void Finalize() final;
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  static bool graph_size_allows_inlining(size_t initial_graph_size) {
621cb0ef41Sopenharmony_ci    return initial_graph_size < 5000;
631cb0ef41Sopenharmony_ci  }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci private:
661cb0ef41Sopenharmony_ci  struct CandidateInfo {
671cb0ef41Sopenharmony_ci    Node* node;
681cb0ef41Sopenharmony_ci    uint32_t inlinee_index;
691cb0ef41Sopenharmony_ci    int call_count;
701cb0ef41Sopenharmony_ci    int wire_byte_size;
711cb0ef41Sopenharmony_ci  };
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  struct LexicographicOrdering {
741cb0ef41Sopenharmony_ci    // Returns if c1 should be prioritized less than c2.
751cb0ef41Sopenharmony_ci    bool operator()(CandidateInfo& c1, CandidateInfo& c2) {
761cb0ef41Sopenharmony_ci      if (c1.call_count > c2.call_count) return false;
771cb0ef41Sopenharmony_ci      if (c2.call_count > c1.call_count) return true;
781cb0ef41Sopenharmony_ci      return c1.wire_byte_size > c2.wire_byte_size;
791cb0ef41Sopenharmony_ci    }
801cb0ef41Sopenharmony_ci  };
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  uint32_t FindOriginatingFunction(Node* call);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  Zone* zone() const { return mcgraph_->zone(); }
851cb0ef41Sopenharmony_ci  CommonOperatorBuilder* common() const { return mcgraph_->common(); }
861cb0ef41Sopenharmony_ci  Graph* graph() const { return mcgraph_->graph(); }
871cb0ef41Sopenharmony_ci  MachineGraph* mcgraph() const { return mcgraph_; }
881cb0ef41Sopenharmony_ci  const wasm::WasmModule* module() const;
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  Reduction ReduceCall(Node* call);
911cb0ef41Sopenharmony_ci  void InlineCall(Node* call, Node* callee_start, Node* callee_end,
921cb0ef41Sopenharmony_ci                  const wasm::FunctionSig* inlinee_sig,
931cb0ef41Sopenharmony_ci                  size_t subgraph_min_node_id);
941cb0ef41Sopenharmony_ci  void InlineTailCall(Node* call, Node* callee_start, Node* callee_end);
951cb0ef41Sopenharmony_ci  void RewireFunctionEntry(Node* call, Node* callee_start);
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  int GetCallCount(Node* call);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  void Trace(Node* call, int inlinee, const char* decision);
1001cb0ef41Sopenharmony_ci  void Trace(const CandidateInfo& candidate, const char* decision);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  wasm::CompilationEnv* const env_;
1031cb0ef41Sopenharmony_ci  uint32_t function_index_;
1041cb0ef41Sopenharmony_ci  SourcePositionTable* const source_positions_;
1051cb0ef41Sopenharmony_ci  NodeOriginTable* const node_origins_;
1061cb0ef41Sopenharmony_ci  MachineGraph* const mcgraph_;
1071cb0ef41Sopenharmony_ci  const wasm::WireBytesStorage* const wire_bytes_;
1081cb0ef41Sopenharmony_ci  std::vector<WasmLoopInfo>* const loop_infos_;
1091cb0ef41Sopenharmony_ci  const char* debug_name_;
1101cb0ef41Sopenharmony_ci  const size_t initial_graph_size_;
1111cb0ef41Sopenharmony_ci  size_t current_graph_size_;
1121cb0ef41Sopenharmony_ci  std::priority_queue<CandidateInfo, std::vector<CandidateInfo>,
1131cb0ef41Sopenharmony_ci                      LexicographicOrdering>
1141cb0ef41Sopenharmony_ci      inlining_candidates_;
1151cb0ef41Sopenharmony_ci  std::unordered_set<Node*> seen_;
1161cb0ef41Sopenharmony_ci  std::vector<uint32_t> inlined_functions_;
1171cb0ef41Sopenharmony_ci  // Stores the graph size before an inlining was performed, to make it
1181cb0ef41Sopenharmony_ci  // possible to map back from nodes to the function they came from.
1191cb0ef41Sopenharmony_ci  // Guaranteed to have the same length as {inlined_functions_}.
1201cb0ef41Sopenharmony_ci  std::vector<uint32_t> first_node_id_;
1211cb0ef41Sopenharmony_ci};
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci}  // namespace compiler
1241cb0ef41Sopenharmony_ci}  // namespace internal
1251cb0ef41Sopenharmony_ci}  // namespace v8
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_WASM_INLINING_H_
128