tor-browser

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

Simulator-loong64.h (20693B)


      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 // Copyright 2020 the V8 project authors. All rights reserved.
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 //       notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 //       copyright notice, this list of conditions and the following
     12 //       disclaimer in the documentation and/or other materials provided
     13 //       with the distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 //       contributors may be used to endorse or promote products derived
     16 //       from this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 #ifndef jit_loong64_Simulator_loong64_h
     31 #define jit_loong64_Simulator_loong64_h
     32 
     33 #ifdef JS_SIMULATOR_LOONG64
     34 
     35 #  include "mozilla/Atomics.h"
     36 
     37 #  include "jit/IonTypes.h"
     38 #  include "js/ProfilingFrameIterator.h"
     39 #  include "threading/Thread.h"
     40 #  include "vm/MutexIDs.h"
     41 #  include "wasm/WasmSignalHandlers.h"
     42 
     43 namespace js {
     44 
     45 namespace jit {
     46 
     47 class JitActivation;
     48 
     49 class Simulator;
     50 class Redirection;
     51 class CachePage;
     52 class AutoLockSimulator;
     53 
     54 // When the SingleStepCallback is called, the simulator is about to execute
     55 // sim->get_pc() and the current machine state represents the completed
     56 // execution of the previous pc.
     57 typedef void (*SingleStepCallback)(void* arg, Simulator* sim, void* pc);
     58 
     59 const intptr_t kPointerAlignment = 8;
     60 const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
     61 
     62 const intptr_t kDoubleAlignment = 8;
     63 const intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1;
     64 
     65 // Number of general purpose registers.
     66 const int kNumRegisters = 32;
     67 
     68 // In the simulator, the PC register is simulated as the 34th register.
     69 const int kPCRegister = 32;
     70 
     71 // Number coprocessor registers.
     72 const int kNumFPURegisters = 32;
     73 
     74 // FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
     75 // TODO fcsr0 fcsr1 fcsr2 fcsr3
     76 const int kFCSRRegister = 0;
     77 const int kInvalidFPUControlRegister = -1;
     78 const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1 << 31) - 1;
     79 const int32_t kFPUInvalidResultNegative = static_cast<int32_t>(1u << 31);
     80 const uint64_t kFPU64InvalidResult =
     81    static_cast<uint64_t>(static_cast<uint64_t>(1) << 63) - 1;
     82 const int64_t kFPU64InvalidResultNegative =
     83    static_cast<int64_t>(static_cast<uint64_t>(1) << 63);
     84 
     85 const uint32_t kFPURoundingModeShift = 8;
     86 const uint32_t kFPURoundingModeMask = 0b11 << kFPURoundingModeShift;
     87 
     88 // FPU rounding modes.
     89 enum FPURoundingMode {
     90  RN = 0b00 << kFPURoundingModeShift,  // Round to Nearest.
     91  RZ = 0b01 << kFPURoundingModeShift,  // Round towards zero.
     92  RP = 0b10 << kFPURoundingModeShift,  // Round towards Plus Infinity.
     93  RM = 0b11 << kFPURoundingModeShift,  // Round towards Minus Infinity.
     94 
     95  // Aliases.
     96  kRoundToNearest = RN,
     97  kRoundToZero = RZ,
     98  kRoundToPlusInf = RP,
     99  kRoundToMinusInf = RM,
    100 
    101  mode_round = RN,
    102  mode_ceil = RP,
    103  mode_floor = RM,
    104  mode_trunc = RZ
    105 };
    106 
    107 // FCSR constants.
    108 const uint32_t kFCSRInexactFlagBit = 16;
    109 const uint32_t kFCSRUnderflowFlagBit = 17;
    110 const uint32_t kFCSROverflowFlagBit = 18;
    111 const uint32_t kFCSRDivideByZeroFlagBit = 19;
    112 const uint32_t kFCSRInvalidOpFlagBit = 20;
    113 
    114 const uint32_t kFCSRInexactCauseBit = 24;
    115 const uint32_t kFCSRUnderflowCauseBit = 25;
    116 const uint32_t kFCSROverflowCauseBit = 26;
    117 const uint32_t kFCSRDivideByZeroCauseBit = 27;
    118 const uint32_t kFCSRInvalidOpCauseBit = 28;
    119 
    120 const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit;
    121 const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit;
    122 const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit;
    123 const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit;
    124 const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit;
    125 
    126 const uint32_t kFCSRFlagMask =
    127    kFCSRInexactFlagMask | kFCSRUnderflowFlagMask | kFCSROverflowFlagMask |
    128    kFCSRDivideByZeroFlagMask | kFCSRInvalidOpFlagMask;
    129 
    130 const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
    131 
    132 // On LoongArch64 Simulator breakpoints can have different codes:
    133 // - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints,
    134 //   the simulator will run through them and print the registers.
    135 // - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop()
    136 //   instructions (see Assembler::stop()).
    137 // - Breaks larger than kMaxStopCode are simple breaks, dropping you into the
    138 //   debugger.
    139 const uint32_t kMaxWatchpointCode = 31;
    140 const uint32_t kMaxStopCode = 127;
    141 const uint32_t kWasmTrapCode = 6;
    142 
    143 // -----------------------------------------------------------------------------
    144 // Utility functions
    145 
    146 typedef uint32_t Instr;
    147 class SimInstruction;
    148 
    149 // Per thread simulator state.
    150 class Simulator {
    151  friend class loong64Debugger;
    152 
    153 public:
    154  // Registers are declared in order.
    155  enum Register {
    156    no_reg = -1,
    157    zero_reg = 0,
    158    ra,
    159    gp,
    160    sp,
    161    a0,
    162    a1,
    163    a2,
    164    a3,
    165    a4,
    166    a5,
    167    a6,
    168    a7,
    169    t0,
    170    t1,
    171    t2,
    172    t3,
    173    t4,
    174    t5,
    175    t6,
    176    t7,
    177    t8,
    178    tp,
    179    fp,
    180    s0,
    181    s1,
    182    s2,
    183    s3,
    184    s4,
    185    s5,
    186    s6,
    187    s7,
    188    s8,
    189    pc,  // pc must be the last register.
    190    kNumSimuRegisters,
    191    // aliases
    192    v0 = a0,
    193    v1 = a1,
    194  };
    195 
    196  // Condition flag registers.
    197  enum CFRegister {
    198    fcc0,
    199    fcc1,
    200    fcc2,
    201    fcc3,
    202    fcc4,
    203    fcc5,
    204    fcc6,
    205    fcc7,
    206    kNumCFRegisters
    207  };
    208 
    209  // Floating point registers.
    210  enum FPURegister {
    211    f0,
    212    f1,
    213    f2,
    214    f3,
    215    f4,
    216    f5,
    217    f6,
    218    f7,
    219    f8,
    220    f9,
    221    f10,
    222    f11,
    223    f12,
    224    f13,
    225    f14,
    226    f15,
    227    f16,
    228    f17,
    229    f18,
    230    f19,
    231    f20,
    232    f21,
    233    f22,
    234    f23,
    235    f24,
    236    f25,
    237    f26,
    238    f27,
    239    f28,
    240    f29,
    241    f30,
    242    f31,
    243    kNumFPURegisters
    244  };
    245 
    246  // Returns nullptr on OOM.
    247  static Simulator* Create();
    248 
    249  static void Destroy(Simulator* simulator);
    250 
    251  // Constructor/destructor are for internal use only; use the static methods
    252  // above.
    253  Simulator();
    254  ~Simulator();
    255 
    256  // The currently executing Simulator instance. Potentially there can be one
    257  // for each native thread.
    258  static Simulator* Current();
    259 
    260  static inline uintptr_t StackLimit() {
    261    return Simulator::Current()->stackLimit();
    262  }
    263 
    264  uintptr_t* addressOfStackLimit();
    265 
    266  // Accessors for register state. Reading the pc value adheres to the LOONG64
    267  // architecture specification and is off by a 8 from the currently executing
    268  // instruction.
    269  void setRegister(int reg, int64_t value);
    270  int64_t getRegister(int reg) const;
    271  // Same for FPURegisters.
    272  void setFpuRegister(int fpureg, int64_t value);
    273  void setFpuRegisterWord(int fpureg, int32_t value);
    274  void setFpuRegisterHiWord(int fpureg, int32_t value);
    275  void setFpuRegisterFloat(int fpureg, float value);
    276  void setFpuRegisterDouble(int fpureg, double value);
    277 
    278  void setFpuRegisterWordInvalidResult(float original, float rounded,
    279                                       int fpureg);
    280  void setFpuRegisterWordInvalidResult(double original, double rounded,
    281                                       int fpureg);
    282  void setFpuRegisterInvalidResult(float original, float rounded, int fpureg);
    283  void setFpuRegisterInvalidResult(double original, double rounded, int fpureg);
    284  void setFpuRegisterInvalidResult64(float original, float rounded, int fpureg);
    285  void setFpuRegisterInvalidResult64(double original, double rounded,
    286                                     int fpureg);
    287 
    288  int64_t getFpuRegister(int fpureg) const;
    289  //  int32_t getFpuRegisterLo(int fpureg) const;
    290  //  int32_t getFpuRegisterHi(int fpureg) const;
    291  int32_t getFpuRegisterWord(int fpureg) const;
    292  int32_t getFpuRegisterSignedWord(int fpureg) const;
    293  int32_t getFpuRegisterHiWord(int fpureg) const;
    294  float getFpuRegisterFloat(int fpureg) const;
    295  double getFpuRegisterDouble(int fpureg) const;
    296 
    297  void setCFRegister(int cfreg, bool value);
    298  bool getCFRegister(int cfreg) const;
    299 
    300  void set_fcsr_rounding_mode(FPURoundingMode mode);
    301 
    302  void setFCSRBit(uint32_t cc, bool value);
    303  bool testFCSRBit(uint32_t cc);
    304  unsigned int getFCSRRoundingMode();
    305  template <typename T>
    306  bool setFCSRRoundError(double original, double rounded);
    307  bool setFCSRRound64Error(float original, float rounded);
    308 
    309  template <typename T>
    310  void roundAccordingToFCSR(T toRound, T* rounded, int32_t* rounded_int);
    311 
    312  template <typename T>
    313  void round64AccordingToFCSR(T toRound, T* rounded, int64_t* rounded_int);
    314 
    315  // Special case of set_register and get_register to access the raw PC value.
    316  void set_pc(int64_t value);
    317  int64_t get_pc() const;
    318 
    319  template <typename T>
    320  T get_pc_as() const {
    321    return reinterpret_cast<T>(get_pc());
    322  }
    323 
    324  void enable_single_stepping(SingleStepCallback cb, void* arg);
    325  void disable_single_stepping();
    326 
    327  // Accessor to the internal simulator stack area.
    328  uintptr_t stackLimit() const;
    329  bool overRecursed(uintptr_t newsp = 0) const;
    330  bool overRecursedWithExtra(uint32_t extra) const;
    331 
    332  // Executes LOONG64 instructions until the PC reaches end_sim_pc.
    333  template <bool enableStopSimAt>
    334  void execute();
    335 
    336  // Sets up the simulator state and grabs the result on return.
    337  int64_t call(uint8_t* entry, int argument_count, ...);
    338 
    339  // Push an address onto the JS stack.
    340  uintptr_t pushAddress(uintptr_t address);
    341 
    342  // Pop an address from the JS stack.
    343  uintptr_t popAddress();
    344 
    345  // Debugger input.
    346  void setLastDebuggerInput(char* input);
    347  char* lastDebuggerInput() { return lastDebuggerInput_; }
    348 
    349  // Returns true if pc register contains one of the 'SpecialValues' defined
    350  // below (bad_ra, end_sim_pc).
    351  bool has_bad_pc() const;
    352 
    353 private:
    354  enum SpecialValues {
    355    // Known bad pc value to ensure that the simulator does not execute
    356    // without being properly setup.
    357    bad_ra = -1,
    358    // A pc value used to signal the simulator to stop execution.  Generally
    359    // the ra is set to this value on transition from native C code to
    360    // simulated execution, so that the simulator can "return" to the native
    361    // C code.
    362    end_sim_pc = -2,
    363    // Unpredictable value.
    364    Unpredictable = 0xbadbeaf
    365  };
    366 
    367  bool init();
    368 
    369  // Unsupported instructions use Format to print an error and stop execution.
    370  void format(SimInstruction* instr, const char* format);
    371 
    372  // Read and write memory.
    373  inline uint8_t readBU(uint64_t addr);
    374  inline int8_t readB(uint64_t addr);
    375  inline void writeB(uint64_t addr, uint8_t value);
    376  inline void writeB(uint64_t addr, int8_t value);
    377 
    378  inline uint16_t readHU(uint64_t addr, SimInstruction* instr);
    379  inline int16_t readH(uint64_t addr, SimInstruction* instr);
    380  inline void writeH(uint64_t addr, uint16_t value, SimInstruction* instr);
    381  inline void writeH(uint64_t addr, int16_t value, SimInstruction* instr);
    382 
    383  inline uint32_t readWU(uint64_t addr, SimInstruction* instr);
    384  inline int32_t readW(uint64_t addr, SimInstruction* instr);
    385  inline void writeW(uint64_t addr, uint32_t value, SimInstruction* instr);
    386  inline void writeW(uint64_t addr, int32_t value, SimInstruction* instr);
    387 
    388  inline int64_t readDW(uint64_t addr, SimInstruction* instr);
    389  inline void writeDW(uint64_t addr, int64_t value, SimInstruction* instr);
    390 
    391  inline double readD(uint64_t addr, SimInstruction* instr);
    392  inline void writeD(uint64_t addr, double value, SimInstruction* instr);
    393 
    394  inline int32_t loadLinkedW(uint64_t addr, SimInstruction* instr);
    395  inline int storeConditionalW(uint64_t addr, int32_t value,
    396                               SimInstruction* instr);
    397 
    398  inline int64_t loadLinkedD(uint64_t addr, SimInstruction* instr);
    399  inline int storeConditionalD(uint64_t addr, int64_t value,
    400                               SimInstruction* instr);
    401 
    402  // Executing is handled based on the instruction type.
    403  void decodeTypeOp6(SimInstruction* instr);
    404  void decodeTypeOp7(SimInstruction* instr);
    405  void decodeTypeOp8(SimInstruction* instr);
    406  void decodeTypeOp10(SimInstruction* instr);
    407  void decodeTypeOp11(SimInstruction* instr);
    408  void decodeTypeOp12(SimInstruction* instr);
    409  void decodeTypeOp14(SimInstruction* instr);
    410  void decodeTypeOp15(SimInstruction* instr);
    411  void decodeTypeOp16(SimInstruction* instr);
    412  void decodeTypeOp17(SimInstruction* instr);
    413  void decodeTypeOp22(SimInstruction* instr);
    414  void decodeTypeOp24(SimInstruction* instr);
    415 
    416  inline int32_t rj_reg(SimInstruction* instr) const;
    417  inline int64_t rj(SimInstruction* instr) const;
    418  inline uint64_t rj_u(SimInstruction* instr) const;
    419  inline int32_t rk_reg(SimInstruction* instr) const;
    420  inline int64_t rk(SimInstruction* instr) const;
    421  inline uint64_t rk_u(SimInstruction* instr) const;
    422  inline int32_t rd_reg(SimInstruction* instr) const;
    423  inline int64_t rd(SimInstruction* instr) const;
    424  inline uint64_t rd_u(SimInstruction* instr) const;
    425  inline int32_t fa_reg(SimInstruction* instr) const;
    426  inline float fa_float(SimInstruction* instr) const;
    427  inline double fa_double(SimInstruction* instr) const;
    428 
    429  inline int32_t fj_reg(SimInstruction* instr) const;
    430  inline float fj_float(SimInstruction* instr) const;
    431  inline double fj_double(SimInstruction* instr) const;
    432 
    433  inline int32_t fk_reg(SimInstruction* instr) const;
    434  inline float fk_float(SimInstruction* instr) const;
    435  inline double fk_double(SimInstruction* instr) const;
    436  inline int32_t fd_reg(SimInstruction* instr) const;
    437  inline float fd_float(SimInstruction* instr) const;
    438  inline double fd_double(SimInstruction* instr) const;
    439 
    440  inline int32_t cj_reg(SimInstruction* instr) const;
    441  inline bool cj(SimInstruction* instr) const;
    442 
    443  inline int32_t cd_reg(SimInstruction* instr) const;
    444  inline bool cd(SimInstruction* instr) const;
    445 
    446  inline int32_t ca_reg(SimInstruction* instr) const;
    447  inline bool ca(SimInstruction* instr) const;
    448  inline uint32_t sa2(SimInstruction* instr) const;
    449  inline uint32_t sa3(SimInstruction* instr) const;
    450  inline uint32_t ui5(SimInstruction* instr) const;
    451  inline uint32_t ui6(SimInstruction* instr) const;
    452  inline uint32_t lsbw(SimInstruction* instr) const;
    453  inline uint32_t msbw(SimInstruction* instr) const;
    454  inline uint32_t lsbd(SimInstruction* instr) const;
    455  inline uint32_t msbd(SimInstruction* instr) const;
    456  inline uint32_t cond(SimInstruction* instr) const;
    457  inline int32_t si12(SimInstruction* instr) const;
    458  inline uint32_t ui12(SimInstruction* instr) const;
    459  inline int32_t si14(SimInstruction* instr) const;
    460  inline int32_t si16(SimInstruction* instr) const;
    461  inline int32_t si20(SimInstruction* instr) const;
    462 
    463  // Used for breakpoints.
    464  void softwareInterrupt(SimInstruction* instr);
    465 
    466  // Stop helper functions.
    467  bool isWatchpoint(uint32_t code);
    468  void printWatchpoint(uint32_t code);
    469  void handleStop(uint32_t code, SimInstruction* instr);
    470  bool isStopInstruction(SimInstruction* instr);
    471  bool isEnabledStop(uint32_t code);
    472  void enableStop(uint32_t code);
    473  void disableStop(uint32_t code);
    474  void increaseStopCounter(uint32_t code);
    475  void printStopInfo(uint32_t code);
    476 
    477  JS::ProfilingFrameIterator::RegisterState registerState();
    478 
    479  // Handle any wasm faults, returning true if the fault was handled.
    480  // This method is rather hot so inline the normal (no-wasm) case.
    481  bool MOZ_ALWAYS_INLINE handleWasmSegFault(uint64_t addr, unsigned numBytes) {
    482    if (MOZ_LIKELY(!js::wasm::CodeExists)) {
    483      return false;
    484    }
    485 
    486    uint8_t* newPC;
    487    if (!js::wasm::MemoryAccessTraps(registerState(), (uint8_t*)addr, numBytes,
    488                                     &newPC)) {
    489      return false;
    490    }
    491 
    492    LLBit_ = false;
    493    set_pc(int64_t(newPC));
    494    return true;
    495  }
    496 
    497  // Executes one instruction.
    498  void instructionDecode(SimInstruction* instr);
    499 
    500 public:
    501  static int64_t StopSimAt;
    502 
    503  // Runtime call support.
    504  static void* RedirectNativeFunction(void* nativeFunction,
    505                                      ABIFunctionType type);
    506 
    507 private:
    508  enum Exception {
    509    kNone,
    510    kIntegerOverflow,
    511    kIntegerUnderflow,
    512    kDivideByZero,
    513    kNumExceptions
    514  };
    515  int16_t exceptions[kNumExceptions];
    516 
    517  // Exceptions.
    518  void signalExceptions();
    519 
    520  // Handle return value for runtime FP functions.
    521  void setCallResultDouble(double result);
    522  void setCallResultFloat(float result);
    523  void setCallResult(int64_t res);
    524 #  ifdef XP_DARWIN
    525  // add a dedicated setCallResult for intptr_t on Darwin
    526  void setCallResult(intptr_t res);
    527 #  endif
    528  void setCallResult(__int128 res);
    529 
    530  void callInternal(uint8_t* entry);
    531 
    532  // Architecture state.
    533  // Registers.
    534  int64_t registers_[kNumSimuRegisters];
    535  // Floating point Registers.
    536  int64_t FPUregisters_[kNumFPURegisters];
    537  // Condition flags Registers.
    538  bool CFregisters_[kNumCFRegisters];
    539  // FPU control register.
    540  uint32_t FCSR_;
    541 
    542  bool LLBit_;
    543  uintptr_t LLAddr_;
    544  int64_t lastLLValue_;
    545 
    546  // Simulator support.
    547  char* stack_;
    548  uintptr_t stackLimit_;
    549  bool pc_modified_;
    550  int64_t icount_;
    551  int64_t break_count_;
    552 
    553  // Debugger input.
    554  char* lastDebuggerInput_;
    555 
    556  // Registered breakpoints.
    557  SimInstruction* break_pc_;
    558  Instr break_instr_;
    559 
    560  // Single-stepping support
    561  bool single_stepping_;
    562  SingleStepCallback single_step_callback_;
    563  void* single_step_callback_arg_;
    564 
    565  // A stop is watched if its code is less than kNumOfWatchedStops.
    566  // Only watched stops support enabling/disabling and the counter feature.
    567  static const uint32_t kNumOfWatchedStops = 256;
    568 
    569  // Stop is disabled if bit 31 is set.
    570  static const uint32_t kStopDisabledBit = 1U << 31;
    571 
    572  // A stop is enabled, meaning the simulator will stop when meeting the
    573  // instruction, if bit 31 of watchedStops_[code].count is unset.
    574  // The value watchedStops_[code].count & ~(1 << 31) indicates how many times
    575  // the breakpoint was hit or gone through.
    576  struct StopCountAndDesc {
    577    uint32_t count_;
    578    char* desc_;
    579  };
    580  StopCountAndDesc watchedStops_[kNumOfWatchedStops];
    581 };
    582 
    583 // Process wide simulator state.
    584 class SimulatorProcess {
    585  friend class Redirection;
    586  friend class AutoLockSimulatorCache;
    587 
    588 private:
    589  // ICache checking.
    590  struct ICacheHasher {
    591    typedef void* Key;
    592    typedef void* Lookup;
    593    static HashNumber hash(const Lookup& l);
    594    static bool match(const Key& k, const Lookup& l);
    595  };
    596 
    597 public:
    598  typedef HashMap<void*, CachePage*, ICacheHasher, SystemAllocPolicy> ICacheMap;
    599 
    600  static mozilla::Atomic<size_t, mozilla::ReleaseAcquire>
    601      ICacheCheckingDisableCount;
    602  static void FlushICache(void* start, size_t size);
    603 
    604  static void checkICacheLocked(SimInstruction* instr);
    605 
    606  static bool initialize() {
    607    singleton_ = js_new<SimulatorProcess>();
    608    return singleton_;
    609  }
    610  static void destroy() {
    611    js_delete(singleton_);
    612    singleton_ = nullptr;
    613  }
    614 
    615  SimulatorProcess();
    616  ~SimulatorProcess();
    617 
    618 private:
    619  static SimulatorProcess* singleton_;
    620 
    621  // This lock creates a critical section around 'redirection_' and
    622  // 'icache_', which are referenced both by the execution engine
    623  // and by the off-thread compiler (see Redirection::Get in the cpp file).
    624  Mutex cacheLock_;
    625 
    626  Redirection* redirection_;
    627  ICacheMap icache_;
    628 
    629 public:
    630  static ICacheMap& icache() {
    631    // Technically we need the lock to access the innards of the
    632    // icache, not to take its address, but the latter condition
    633    // serves as a useful complement to the former.
    634    singleton_->cacheLock_.assertOwnedByCurrentThread();
    635    return singleton_->icache_;
    636  }
    637 
    638  static Redirection* redirection() {
    639    singleton_->cacheLock_.assertOwnedByCurrentThread();
    640    return singleton_->redirection_;
    641  }
    642 
    643  static void setRedirection(js::jit::Redirection* redirection) {
    644    singleton_->cacheLock_.assertOwnedByCurrentThread();
    645    singleton_->redirection_ = redirection;
    646  }
    647 };
    648 
    649 }  // namespace jit
    650 }  // namespace js
    651 
    652 #endif /* JS_SIMULATOR_LOONG64 */
    653 
    654 #endif /* jit_loong64_Simulator_loong64_h */