tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

PerfSpewer.h (8144B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef jit_PerfSpewer_h
      8 #define jit_PerfSpewer_h
      9 
     10 #ifdef JS_ION_PERF
     11 #  include <stdio.h>
     12 #endif
     13 #include "js/AllocPolicy.h"
     14 #include "js/Vector.h"
     15 
     16 #ifdef JS_JITSPEW
     17 #  include "jit/GraphSpewer.h"
     18 #endif
     19 
     20 class JSScript;
     21 enum class JSOp : uint8_t;
     22 
     23 namespace js {
     24 
     25 namespace wasm {
     26 struct OpBytes;
     27 struct CodeMetadata;
     28 }  // namespace wasm
     29 
     30 namespace jit {
     31 
     32 class JitCode;
     33 class BacktrackingAllocator;
     34 class CompilerFrameInfo;
     35 class MacroAssembler;
     36 class MBasicBlock;
     37 class MIRGraph;
     38 class LInstruction;
     39 enum class CacheOp : uint16_t;
     40 
     41 struct AutoLockPerfSpewer {
     42  AutoLockPerfSpewer();
     43  ~AutoLockPerfSpewer();
     44 };
     45 
     46 bool PerfEnabled();
     47 
     48 class PerfSpewer {
     49 protected:
     50  // An entry to insert into the DEBUG_INFO jitdump record. It maps from a code
     51  // offset (relative to startOffset_) to a line number and column number.
     52  struct DebugEntry {
     53    constexpr DebugEntry() : offset(0), line(0), column(0) {}
     54    constexpr DebugEntry(uint32_t offset_, uint32_t line_, uint32_t column_ = 0)
     55        : offset(offset_), line(line_), column(column_) {}
     56 
     57    uint32_t offset;
     58    uint32_t line;
     59    uint32_t column;
     60  };
     61 
     62  // The debug records for this perf spewer.
     63  Vector<DebugEntry, 0, SystemAllocPolicy> debugInfo_;
     64 
     65  // The start offset that debugInfo_ is relative to.
     66  uint32_t startOffset_ = 0;
     67 
     68  // The generated IR file that we write into for IONPERF=ir. The move
     69  // constructors assert that this file has been closed/finished.
     70  FILE* irFile_ = nullptr;
     71  uint32_t irFileLines_ = 0;
     72 
     73  // The filename of irFile_.
     74  JS::UniqueChars irFileName_;
     75 
     76  virtual const char* CodeName(uint32_t op) = 0;
     77  virtual const char* IRFileExtension() { return ".txt"; }
     78 
     79  // Append an opcode to opcodes_ and the implicit debugInfo_ entry referencing
     80  // it.
     81  void recordOpcode(uint32_t offset, uint32_t opcode);
     82  void recordOpcode(uint32_t offset, uint32_t opcode, JS::UniqueChars&& str);
     83  void recordOpcode(uint32_t offset, JS::UniqueChars&& str);
     84 
     85  // Save the debugInfo_ vector to the JIT dump file.
     86  void saveDebugInfo(const char* filename, uintptr_t base,
     87                     AutoLockPerfSpewer& lock);
     88 
     89  // Save the generated IR file, if any, and the debug info to the JIT dump
     90  // file.
     91  void saveJitCodeDebugInfo(JSScript* script, JitCode* code,
     92                            AutoLockPerfSpewer& lock);
     93 
     94  // Save the generated IR file, if any, and the debug info to the JIT dump
     95  // file.
     96  void saveWasmCodeDebugInfo(uintptr_t codeBase, AutoLockPerfSpewer& lock);
     97 
     98  void saveJSProfile(JitCode* code, JS::UniqueChars& desc, JSScript* script);
     99  void saveWasmProfile(uintptr_t codeBase, size_t codeSize,
    100                       JS::UniqueChars& desc);
    101 
    102  virtual void disable(AutoLockPerfSpewer& lock);
    103  virtual void disable();
    104 
    105 public:
    106  PerfSpewer() = default;
    107  ~PerfSpewer();
    108  PerfSpewer(PerfSpewer&&);
    109  PerfSpewer& operator=(PerfSpewer&&);
    110 
    111  // Mark the start code offset that this perf spewer is relative to.
    112  void markStartOffset(uint32_t offset) { startOffset_ = offset; }
    113 
    114  // Start recording. This may create a temp file if we're recording IR.
    115  virtual void startRecording(const wasm::CodeMetadata* wasmCodeMeta = nullptr);
    116 
    117  // Finish recording and get ready for saving to jitdump, but do not yet
    118  // write the debug info.
    119  virtual void endRecording();
    120 
    121  void recordOffset(MacroAssembler& masm, const char*);
    122 
    123  static void Init();
    124 
    125  static void CollectJitCodeInfo(JS::UniqueChars& function_name, JitCode* code,
    126                                 AutoLockPerfSpewer& lock);
    127  static void CollectJitCodeInfo(JS::UniqueChars& function_name,
    128                                 void* code_addr, uint64_t code_size,
    129                                 AutoLockPerfSpewer& lock);
    130 };
    131 
    132 void CollectPerfSpewerJitCodeProfile(JitCode* code, const char* msg);
    133 void CollectPerfSpewerJitCodeProfile(uintptr_t base, uint64_t size,
    134                                     const char* msg);
    135 
    136 void CollectPerfSpewerWasmMap(uintptr_t base, uintptr_t size,
    137                              JS::UniqueChars&& desc);
    138 
    139 class IonPerfSpewer : public PerfSpewer {
    140  const char* CodeName(uint32_t op) override;
    141  const char* IRFileExtension() override;
    142 
    143  void disable() override;
    144 
    145 #ifdef JS_JITSPEW
    146  Fprinter graphPrinter_;
    147  UniqueGraphSpewer graphSpewer_ = nullptr;
    148 #endif
    149 
    150 public:
    151  IonPerfSpewer() = default;
    152  IonPerfSpewer(IonPerfSpewer&&) = default;
    153  IonPerfSpewer& operator=(IonPerfSpewer&&) = default;
    154 
    155  void startRecording(
    156      const wasm::CodeMetadata* wasmCodeMeta = nullptr) override;
    157  void endRecording() override;
    158 
    159  void recordPass(const char* pass, MIRGraph* graph,
    160                  BacktrackingAllocator* ra = nullptr);
    161  void recordInstruction(MacroAssembler& masm, LInstruction* ins);
    162 
    163  void saveJSProfile(JSContext* cx, JSScript* script, JitCode* code);
    164  void saveWasmProfile(uintptr_t codeBase, size_t codeSize,
    165                       JS::UniqueChars& desc);
    166 };
    167 
    168 class WasmBaselinePerfSpewer : public PerfSpewer {
    169  const char* CodeName(uint32_t op) override;
    170 
    171 public:
    172  WasmBaselinePerfSpewer() = default;
    173  WasmBaselinePerfSpewer(WasmBaselinePerfSpewer&&) = default;
    174  WasmBaselinePerfSpewer& operator=(WasmBaselinePerfSpewer&&) = default;
    175 
    176  [[nodiscard]] bool needsToRecordInstruction() const;
    177  void recordInstruction(MacroAssembler& masm, const wasm::OpBytes& op);
    178  void saveProfile(uintptr_t codeBase, size_t codeSize, JS::UniqueChars& desc);
    179 };
    180 
    181 class BaselineInterpreterPerfSpewer : public PerfSpewer {
    182  // An opcode to insert into the generated IR source file.
    183  struct Op {
    184    uint32_t offset = 0;
    185    uint32_t opcode = 0;
    186    // This string is used to replace the opcode, to define things like
    187    // Prologue/Epilogue, or to add operand info.
    188    JS::UniqueChars str;
    189 
    190    explicit Op(uint32_t offset_, uint32_t opcode_)
    191        : offset(offset_), opcode(opcode_) {}
    192    explicit Op(uint32_t offset_, JS::UniqueChars&& str_)
    193        : offset(offset_), opcode(0), str(std::move(str_)) {}
    194 
    195    Op(Op&& copy) {
    196      offset = copy.offset;
    197      opcode = copy.opcode;
    198      str = std::move(copy.str);
    199    }
    200 
    201    // Do not copy the UniqueChars member.
    202    Op(Op& copy) = delete;
    203  };
    204  Vector<Op, 0, SystemAllocPolicy> ops_;
    205 
    206  const char* CodeName(uint32_t op) override;
    207 
    208 public:
    209  void recordOffset(MacroAssembler& masm, const JSOp& op);
    210  void recordOffset(MacroAssembler& masm, const char* name);
    211  void saveProfile(JitCode* code);
    212 };
    213 
    214 class BaselinePerfSpewer : public PerfSpewer {
    215  const char* CodeName(uint32_t op) override;
    216 
    217 public:
    218  void recordInstruction(MacroAssembler& masm, jsbytecode* pc, JSScript* script,
    219                         CompilerFrameInfo& frame);
    220  void saveProfile(JSContext* cx, JSScript* script, JitCode* code);
    221 };
    222 
    223 class InlineCachePerfSpewer : public PerfSpewer {
    224  const char* CodeName(uint32_t op) override;
    225 
    226 public:
    227  void recordInstruction(MacroAssembler& masm, const CacheOp& op);
    228 };
    229 
    230 class BaselineICPerfSpewer : public InlineCachePerfSpewer {
    231 public:
    232  void saveProfile(JitCode* code, const char* stubName);
    233 };
    234 
    235 class IonICPerfSpewer : public InlineCachePerfSpewer {
    236 public:
    237  explicit IonICPerfSpewer(JSScript* script, jsbytecode* pc);
    238 
    239  void saveProfile(JSContext* cx, JSScript* script, JitCode* code,
    240                   const char* stubName);
    241 };
    242 
    243 class PerfSpewerRangeRecorder {
    244  using OffsetPair = std::tuple<uint32_t, JS::UniqueChars>;
    245  Vector<OffsetPair, 0, js::SystemAllocPolicy> ranges;
    246 
    247  MacroAssembler& masm;
    248 
    249  void appendEntry(JS::UniqueChars& desc);
    250 
    251 public:
    252  explicit PerfSpewerRangeRecorder(MacroAssembler& masm_) : masm(masm_) {};
    253 
    254  void recordOffset(const char* name);
    255  void recordOffset(const char* name, JSContext* cx, JSScript* script);
    256  void recordVMWrapperOffset(const char* name);
    257  void collectRangesForJitCode(JitCode* code);
    258 };
    259 
    260 }  // namespace jit
    261 }  // namespace js
    262 
    263 #endif /* jit_PerfSpewer_h */