1// Copyright 2015 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_JS_INLINING_HEURISTIC_H_
6#define V8_COMPILER_JS_INLINING_HEURISTIC_H_
7
8#include "src/compiler/js-inlining.h"
9
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14class JSInliningHeuristic final : public AdvancedReducer {
15 public:
16  enum Mode { kJSOnly, kWasmOnly };
17
18  JSInliningHeuristic(Editor* editor, Zone* local_zone,
19                      OptimizedCompilationInfo* info, JSGraph* jsgraph,
20                      JSHeapBroker* broker,
21                      SourcePositionTable* source_positions, Mode mode)
22      : AdvancedReducer(editor),
23        inliner_(editor, local_zone, info, jsgraph, broker, source_positions),
24        candidates_(local_zone),
25        seen_(local_zone),
26        source_positions_(source_positions),
27        jsgraph_(jsgraph),
28        broker_(broker),
29        mode_(mode),
30        max_inlined_bytecode_size_cumulative_(
31            FLAG_max_inlined_bytecode_size_cumulative),
32        max_inlined_bytecode_size_absolute_(
33            FLAG_max_inlined_bytecode_size_absolute) {}
34
35  const char* reducer_name() const override { return "JSInliningHeuristic"; }
36
37  Reduction Reduce(Node* node) final;
38
39  // Processes the list of candidates gathered while the reducer was running,
40  // and inlines call sites that the heuristic determines to be important.
41  void Finalize() final;
42
43  int total_inlined_bytecode_size() const {
44    return total_inlined_bytecode_size_;
45  }
46
47 private:
48  // This limit currently matches what the old compiler did. We may want to
49  // re-evaluate and come up with a proper limit for TurboFan.
50  static const int kMaxCallPolymorphism = 4;
51
52  struct Candidate {
53    base::Optional<JSFunctionRef> functions[kMaxCallPolymorphism];
54    // In the case of polymorphic inlining, this tells if each of the
55    // functions could be inlined.
56    bool can_inline_function[kMaxCallPolymorphism];
57    // Strong references to bytecode to ensure it is not flushed from SFI
58    // while choosing inlining candidates.
59    base::Optional<BytecodeArrayRef> bytecode[kMaxCallPolymorphism];
60    // TODO(2206): For now polymorphic inlining is treated orthogonally to
61    // inlining based on SharedFunctionInfo. This should be unified and the
62    // above array should be switched to SharedFunctionInfo instead. Currently
63    // we use {num_functions == 1 && functions[0].is_null()} as an indicator.
64    base::Optional<SharedFunctionInfoRef> shared_info;
65    int num_functions;
66    Node* node = nullptr;     // The call site at which to inline.
67    CallFrequency frequency;  // Relative frequency of this call site.
68    int total_size = 0;
69  };
70
71  // Comparator for candidates.
72  struct CandidateCompare {
73    bool operator()(const Candidate& left, const Candidate& right) const;
74  };
75
76  // Candidates are kept in a sorted set of unique candidates.
77  using Candidates = ZoneSet<Candidate, CandidateCompare>;
78
79  // Dumps candidates to console.
80  void PrintCandidates();
81  Reduction InlineCandidate(Candidate const& candidate, bool small_function);
82  void CreateOrReuseDispatch(Node* node, Node* callee,
83                             Candidate const& candidate, Node** if_successes,
84                             Node** calls, Node** inputs, int input_count);
85  bool TryReuseDispatch(Node* node, Node* callee, Node** if_successes,
86                        Node** calls, Node** inputs, int input_count);
87  enum StateCloneMode { kCloneState, kChangeInPlace };
88  FrameState DuplicateFrameStateAndRename(FrameState frame_state, Node* from,
89                                          Node* to, StateCloneMode mode);
90  Node* DuplicateStateValuesAndRename(Node* state_values, Node* from, Node* to,
91                                      StateCloneMode mode);
92  Candidate CollectFunctions(Node* node, int functions_size);
93
94  CommonOperatorBuilder* common() const;
95  Graph* graph() const;
96  JSGraph* jsgraph() const { return jsgraph_; }
97  // TODO(neis): Make heap broker a component of JSGraph?
98  JSHeapBroker* broker() const { return broker_; }
99  CompilationDependencies* dependencies() const;
100  Isolate* isolate() const { return jsgraph_->isolate(); }
101  SimplifiedOperatorBuilder* simplified() const;
102  Mode mode() const { return mode_; }
103
104  JSInliner inliner_;
105  Candidates candidates_;
106  ZoneSet<NodeId> seen_;
107  SourcePositionTable* source_positions_;
108  JSGraph* const jsgraph_;
109  JSHeapBroker* const broker_;
110  int total_inlined_bytecode_size_ = 0;
111  const Mode mode_;
112  const int max_inlined_bytecode_size_cumulative_;
113  const int max_inlined_bytecode_size_absolute_;
114};
115
116}  // namespace compiler
117}  // namespace internal
118}  // namespace v8
119
120#endif  // V8_COMPILER_JS_INLINING_HEURISTIC_H_
121