11cb0ef41Sopenharmony_ci// Copyright 2015 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_COMPILER_JS_INLINING_HEURISTIC_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_JS_INLINING_HEURISTIC_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/compiler/js-inlining.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_cinamespace compiler {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciclass JSInliningHeuristic final : public AdvancedReducer {
151cb0ef41Sopenharmony_ci public:
161cb0ef41Sopenharmony_ci  enum Mode { kJSOnly, kWasmOnly };
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci  JSInliningHeuristic(Editor* editor, Zone* local_zone,
191cb0ef41Sopenharmony_ci                      OptimizedCompilationInfo* info, JSGraph* jsgraph,
201cb0ef41Sopenharmony_ci                      JSHeapBroker* broker,
211cb0ef41Sopenharmony_ci                      SourcePositionTable* source_positions, Mode mode)
221cb0ef41Sopenharmony_ci      : AdvancedReducer(editor),
231cb0ef41Sopenharmony_ci        inliner_(editor, local_zone, info, jsgraph, broker, source_positions),
241cb0ef41Sopenharmony_ci        candidates_(local_zone),
251cb0ef41Sopenharmony_ci        seen_(local_zone),
261cb0ef41Sopenharmony_ci        source_positions_(source_positions),
271cb0ef41Sopenharmony_ci        jsgraph_(jsgraph),
281cb0ef41Sopenharmony_ci        broker_(broker),
291cb0ef41Sopenharmony_ci        mode_(mode),
301cb0ef41Sopenharmony_ci        max_inlined_bytecode_size_cumulative_(
311cb0ef41Sopenharmony_ci            FLAG_max_inlined_bytecode_size_cumulative),
321cb0ef41Sopenharmony_ci        max_inlined_bytecode_size_absolute_(
331cb0ef41Sopenharmony_ci            FLAG_max_inlined_bytecode_size_absolute) {}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  const char* reducer_name() const override { return "JSInliningHeuristic"; }
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ci  Reduction Reduce(Node* node) final;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  // Processes the list of candidates gathered while the reducer was running,
401cb0ef41Sopenharmony_ci  // and inlines call sites that the heuristic determines to be important.
411cb0ef41Sopenharmony_ci  void Finalize() final;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  int total_inlined_bytecode_size() const {
441cb0ef41Sopenharmony_ci    return total_inlined_bytecode_size_;
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci private:
481cb0ef41Sopenharmony_ci  // This limit currently matches what the old compiler did. We may want to
491cb0ef41Sopenharmony_ci  // re-evaluate and come up with a proper limit for TurboFan.
501cb0ef41Sopenharmony_ci  static const int kMaxCallPolymorphism = 4;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  struct Candidate {
531cb0ef41Sopenharmony_ci    base::Optional<JSFunctionRef> functions[kMaxCallPolymorphism];
541cb0ef41Sopenharmony_ci    // In the case of polymorphic inlining, this tells if each of the
551cb0ef41Sopenharmony_ci    // functions could be inlined.
561cb0ef41Sopenharmony_ci    bool can_inline_function[kMaxCallPolymorphism];
571cb0ef41Sopenharmony_ci    // Strong references to bytecode to ensure it is not flushed from SFI
581cb0ef41Sopenharmony_ci    // while choosing inlining candidates.
591cb0ef41Sopenharmony_ci    base::Optional<BytecodeArrayRef> bytecode[kMaxCallPolymorphism];
601cb0ef41Sopenharmony_ci    // TODO(2206): For now polymorphic inlining is treated orthogonally to
611cb0ef41Sopenharmony_ci    // inlining based on SharedFunctionInfo. This should be unified and the
621cb0ef41Sopenharmony_ci    // above array should be switched to SharedFunctionInfo instead. Currently
631cb0ef41Sopenharmony_ci    // we use {num_functions == 1 && functions[0].is_null()} as an indicator.
641cb0ef41Sopenharmony_ci    base::Optional<SharedFunctionInfoRef> shared_info;
651cb0ef41Sopenharmony_ci    int num_functions;
661cb0ef41Sopenharmony_ci    Node* node = nullptr;     // The call site at which to inline.
671cb0ef41Sopenharmony_ci    CallFrequency frequency;  // Relative frequency of this call site.
681cb0ef41Sopenharmony_ci    int total_size = 0;
691cb0ef41Sopenharmony_ci  };
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // Comparator for candidates.
721cb0ef41Sopenharmony_ci  struct CandidateCompare {
731cb0ef41Sopenharmony_ci    bool operator()(const Candidate& left, const Candidate& right) const;
741cb0ef41Sopenharmony_ci  };
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  // Candidates are kept in a sorted set of unique candidates.
771cb0ef41Sopenharmony_ci  using Candidates = ZoneSet<Candidate, CandidateCompare>;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Dumps candidates to console.
801cb0ef41Sopenharmony_ci  void PrintCandidates();
811cb0ef41Sopenharmony_ci  Reduction InlineCandidate(Candidate const& candidate, bool small_function);
821cb0ef41Sopenharmony_ci  void CreateOrReuseDispatch(Node* node, Node* callee,
831cb0ef41Sopenharmony_ci                             Candidate const& candidate, Node** if_successes,
841cb0ef41Sopenharmony_ci                             Node** calls, Node** inputs, int input_count);
851cb0ef41Sopenharmony_ci  bool TryReuseDispatch(Node* node, Node* callee, Node** if_successes,
861cb0ef41Sopenharmony_ci                        Node** calls, Node** inputs, int input_count);
871cb0ef41Sopenharmony_ci  enum StateCloneMode { kCloneState, kChangeInPlace };
881cb0ef41Sopenharmony_ci  FrameState DuplicateFrameStateAndRename(FrameState frame_state, Node* from,
891cb0ef41Sopenharmony_ci                                          Node* to, StateCloneMode mode);
901cb0ef41Sopenharmony_ci  Node* DuplicateStateValuesAndRename(Node* state_values, Node* from, Node* to,
911cb0ef41Sopenharmony_ci                                      StateCloneMode mode);
921cb0ef41Sopenharmony_ci  Candidate CollectFunctions(Node* node, int functions_size);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  CommonOperatorBuilder* common() const;
951cb0ef41Sopenharmony_ci  Graph* graph() const;
961cb0ef41Sopenharmony_ci  JSGraph* jsgraph() const { return jsgraph_; }
971cb0ef41Sopenharmony_ci  // TODO(neis): Make heap broker a component of JSGraph?
981cb0ef41Sopenharmony_ci  JSHeapBroker* broker() const { return broker_; }
991cb0ef41Sopenharmony_ci  CompilationDependencies* dependencies() const;
1001cb0ef41Sopenharmony_ci  Isolate* isolate() const { return jsgraph_->isolate(); }
1011cb0ef41Sopenharmony_ci  SimplifiedOperatorBuilder* simplified() const;
1021cb0ef41Sopenharmony_ci  Mode mode() const { return mode_; }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  JSInliner inliner_;
1051cb0ef41Sopenharmony_ci  Candidates candidates_;
1061cb0ef41Sopenharmony_ci  ZoneSet<NodeId> seen_;
1071cb0ef41Sopenharmony_ci  SourcePositionTable* source_positions_;
1081cb0ef41Sopenharmony_ci  JSGraph* const jsgraph_;
1091cb0ef41Sopenharmony_ci  JSHeapBroker* const broker_;
1101cb0ef41Sopenharmony_ci  int total_inlined_bytecode_size_ = 0;
1111cb0ef41Sopenharmony_ci  const Mode mode_;
1121cb0ef41Sopenharmony_ci  const int max_inlined_bytecode_size_cumulative_;
1131cb0ef41Sopenharmony_ci  const int max_inlined_bytecode_size_absolute_;
1141cb0ef41Sopenharmony_ci};
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci}  // namespace compiler
1171cb0ef41Sopenharmony_ci}  // namespace internal
1181cb0ef41Sopenharmony_ci}  // namespace v8
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_JS_INLINING_HEURISTIC_H_
121