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#ifndef V8_BASELINE_BASELINE_COMPILER_H_
61cb0ef41Sopenharmony_ci#define V8_BASELINE_BASELINE_COMPILER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// TODO(v8:11421): Remove #if once baseline compiler is ported to other
91cb0ef41Sopenharmony_ci// architectures.
101cb0ef41Sopenharmony_ci#include "src/flags/flags.h"
111cb0ef41Sopenharmony_ci#if ENABLE_SPARKPLUG
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci#include "src/base/logging.h"
141cb0ef41Sopenharmony_ci#include "src/base/threaded-list.h"
151cb0ef41Sopenharmony_ci#include "src/base/vlq.h"
161cb0ef41Sopenharmony_ci#include "src/baseline/baseline-assembler.h"
171cb0ef41Sopenharmony_ci#include "src/execution/local-isolate.h"
181cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
191cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-array-iterator.h"
201cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-register.h"
211cb0ef41Sopenharmony_ci#include "src/interpreter/interpreter-intrinsics.h"
221cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
231cb0ef41Sopenharmony_ci#include "src/objects/map.h"
241cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h"
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace v8 {
271cb0ef41Sopenharmony_cinamespace internal {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciclass BytecodeArray;
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cinamespace baseline {
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ciclass BytecodeOffsetTableBuilder {
341cb0ef41Sopenharmony_ci public:
351cb0ef41Sopenharmony_ci  void AddPosition(size_t pc_offset) {
361cb0ef41Sopenharmony_ci    size_t pc_diff = pc_offset - previous_pc_;
371cb0ef41Sopenharmony_ci    DCHECK_GE(pc_diff, 0);
381cb0ef41Sopenharmony_ci    DCHECK_LE(pc_diff, std::numeric_limits<uint32_t>::max());
391cb0ef41Sopenharmony_ci    base::VLQEncodeUnsigned(&bytes_, static_cast<uint32_t>(pc_diff));
401cb0ef41Sopenharmony_ci    previous_pc_ = pc_offset;
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  template <typename IsolateT>
441cb0ef41Sopenharmony_ci  Handle<ByteArray> ToBytecodeOffsetTable(IsolateT* isolate);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  void Reserve(size_t size) { bytes_.reserve(size); }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci private:
491cb0ef41Sopenharmony_ci  size_t previous_pc_ = 0;
501cb0ef41Sopenharmony_ci  std::vector<byte> bytes_;
511cb0ef41Sopenharmony_ci};
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciclass BaselineCompiler {
541cb0ef41Sopenharmony_ci public:
551cb0ef41Sopenharmony_ci  explicit BaselineCompiler(LocalIsolate* local_isolate,
561cb0ef41Sopenharmony_ci                            Handle<SharedFunctionInfo> shared_function_info,
571cb0ef41Sopenharmony_ci                            Handle<BytecodeArray> bytecode);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  void GenerateCode();
601cb0ef41Sopenharmony_ci  MaybeHandle<Code> Build(LocalIsolate* local_isolate);
611cb0ef41Sopenharmony_ci  static int EstimateInstructionSize(BytecodeArray bytecode);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci private:
641cb0ef41Sopenharmony_ci  void Prologue();
651cb0ef41Sopenharmony_ci  void PrologueFillFrame();
661cb0ef41Sopenharmony_ci  void PrologueHandleOptimizationState(Register feedback_vector);
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  void PreVisitSingleBytecode();
691cb0ef41Sopenharmony_ci  void VisitSingleBytecode();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  void VerifyFrame();
721cb0ef41Sopenharmony_ci  void VerifyFrameSize();
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  // Register operands.
751cb0ef41Sopenharmony_ci  interpreter::Register RegisterOperand(int operand_index);
761cb0ef41Sopenharmony_ci  void LoadRegister(Register output, int operand_index);
771cb0ef41Sopenharmony_ci  void StoreRegister(int operand_index, Register value);
781cb0ef41Sopenharmony_ci  void StoreRegisterPair(int operand_index, Register val0, Register val1);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  // Constant pool operands.
811cb0ef41Sopenharmony_ci  template <typename Type>
821cb0ef41Sopenharmony_ci  Handle<Type> Constant(int operand_index);
831cb0ef41Sopenharmony_ci  Smi ConstantSmi(int operand_index);
841cb0ef41Sopenharmony_ci  template <typename Type>
851cb0ef41Sopenharmony_ci  void LoadConstant(Register output, int operand_index);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // Immediate value operands.
881cb0ef41Sopenharmony_ci  uint32_t Uint(int operand_index);
891cb0ef41Sopenharmony_ci  int32_t Int(int operand_index);
901cb0ef41Sopenharmony_ci  uint32_t Index(int operand_index);
911cb0ef41Sopenharmony_ci  uint32_t Flag(int operand_index);
921cb0ef41Sopenharmony_ci  uint32_t RegisterCount(int operand_index);
931cb0ef41Sopenharmony_ci  TaggedIndex IndexAsTagged(int operand_index);
941cb0ef41Sopenharmony_ci  TaggedIndex UintAsTagged(int operand_index);
951cb0ef41Sopenharmony_ci  Smi IndexAsSmi(int operand_index);
961cb0ef41Sopenharmony_ci  Smi IntAsSmi(int operand_index);
971cb0ef41Sopenharmony_ci  Smi FlagAsSmi(int operand_index);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // Jump helpers.
1001cb0ef41Sopenharmony_ci  Label* NewLabel();
1011cb0ef41Sopenharmony_ci  Label* BuildForwardJumpLabel();
1021cb0ef41Sopenharmony_ci  void UpdateInterruptBudgetAndJumpToLabel(int weight, Label* label,
1031cb0ef41Sopenharmony_ci                                           Label* skip_interrupt_label);
1041cb0ef41Sopenharmony_ci  void UpdateInterruptBudgetAndDoInterpreterJump();
1051cb0ef41Sopenharmony_ci  void UpdateInterruptBudgetAndDoInterpreterJumpIfRoot(RootIndex root);
1061cb0ef41Sopenharmony_ci  void UpdateInterruptBudgetAndDoInterpreterJumpIfNotRoot(RootIndex root);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  // Feedback vector.
1091cb0ef41Sopenharmony_ci  MemOperand FeedbackVector();
1101cb0ef41Sopenharmony_ci  void LoadFeedbackVector(Register output);
1111cb0ef41Sopenharmony_ci  void LoadClosureFeedbackArray(Register output);
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  // Position mapping.
1141cb0ef41Sopenharmony_ci  void AddPosition();
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  // Misc. helpers.
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  void UpdateMaxCallArgs(int max_call_args) {
1191cb0ef41Sopenharmony_ci    max_call_args_ = std::max(max_call_args_, max_call_args);
1201cb0ef41Sopenharmony_ci  }
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  // Select the root boolean constant based on the jump in the given
1231cb0ef41Sopenharmony_ci  // `jump_func` -- the function should jump to the given label if we want to
1241cb0ef41Sopenharmony_ci  // select "true", otherwise it should fall through.
1251cb0ef41Sopenharmony_ci  void SelectBooleanConstant(
1261cb0ef41Sopenharmony_ci      Register output, std::function<void(Label*, Label::Distance)> jump_func);
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  // Jumps based on calling ToBoolean on kInterpreterAccumulatorRegister.
1291cb0ef41Sopenharmony_ci  void JumpIfToBoolean(bool do_jump_if_true, Label* label,
1301cb0ef41Sopenharmony_ci                       Label::Distance distance = Label::kFar);
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  // Call helpers.
1331cb0ef41Sopenharmony_ci  template <Builtin kBuiltin, typename... Args>
1341cb0ef41Sopenharmony_ci  void CallBuiltin(Args... args);
1351cb0ef41Sopenharmony_ci  template <typename... Args>
1361cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId function, Args... args);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  template <Builtin kBuiltin, typename... Args>
1391cb0ef41Sopenharmony_ci  void TailCallBuiltin(Args... args);
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  template <ConvertReceiverMode kMode, typename... Args>
1421cb0ef41Sopenharmony_ci  void BuildCall(uint32_t slot, uint32_t arg_count, Args... args);
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci#ifdef V8_TRACE_UNOPTIMIZED
1451cb0ef41Sopenharmony_ci  void TraceBytecode(Runtime::FunctionId function_id);
1461cb0ef41Sopenharmony_ci#endif
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  // Single bytecode visitors.
1491cb0ef41Sopenharmony_ci#define DECLARE_VISITOR(name, ...) void Visit##name();
1501cb0ef41Sopenharmony_ci  BYTECODE_LIST(DECLARE_VISITOR)
1511cb0ef41Sopenharmony_ci#undef DECLARE_VISITOR
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  // Intrinsic call visitors.
1541cb0ef41Sopenharmony_ci#define DECLARE_VISITOR(name, ...) \
1551cb0ef41Sopenharmony_ci  void VisitIntrinsic##name(interpreter::RegisterList args);
1561cb0ef41Sopenharmony_ci  INTRINSICS_LIST(DECLARE_VISITOR)
1571cb0ef41Sopenharmony_ci#undef DECLARE_VISITOR
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  const interpreter::BytecodeArrayIterator& iterator() { return iterator_; }
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  LocalIsolate* local_isolate_;
1621cb0ef41Sopenharmony_ci  RuntimeCallStats* stats_;
1631cb0ef41Sopenharmony_ci  Handle<SharedFunctionInfo> shared_function_info_;
1641cb0ef41Sopenharmony_ci  Handle<HeapObject> interpreter_data_;
1651cb0ef41Sopenharmony_ci  Handle<BytecodeArray> bytecode_;
1661cb0ef41Sopenharmony_ci  MacroAssembler masm_;
1671cb0ef41Sopenharmony_ci  BaselineAssembler basm_;
1681cb0ef41Sopenharmony_ci  interpreter::BytecodeArrayIterator iterator_;
1691cb0ef41Sopenharmony_ci  BytecodeOffsetTableBuilder bytecode_offset_table_builder_;
1701cb0ef41Sopenharmony_ci  Zone zone_;
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  int max_call_args_ = 0;
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  struct ThreadedLabel {
1751cb0ef41Sopenharmony_ci    Label label;
1761cb0ef41Sopenharmony_ci    ThreadedLabel* ptr;
1771cb0ef41Sopenharmony_ci    ThreadedLabel** next() { return &ptr; }
1781cb0ef41Sopenharmony_ci  };
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  struct BaselineLabels {
1811cb0ef41Sopenharmony_ci    base::ThreadedList<ThreadedLabel> linked;
1821cb0ef41Sopenharmony_ci    Label unlinked;
1831cb0ef41Sopenharmony_ci  };
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  BaselineLabels* EnsureLabels(int i) {
1861cb0ef41Sopenharmony_ci    if (labels_[i] == nullptr) {
1871cb0ef41Sopenharmony_ci      labels_[i] = zone_.New<BaselineLabels>();
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci    return labels_[i];
1901cb0ef41Sopenharmony_ci  }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  BaselineLabels** labels_;
1931cb0ef41Sopenharmony_ci};
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci}  // namespace baseline
1961cb0ef41Sopenharmony_ci}  // namespace internal
1971cb0ef41Sopenharmony_ci}  // namespace v8
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci#endif  // ENABLE_SPARKPLUG
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci#endif  // V8_BASELINE_BASELINE_COMPILER_H_
202