5#ifndef V8_WASM_INTERPRETER_WASM_INTERPRETER_H_ 
    6#define V8_WASM_INTERPRETER_WASM_INTERPRETER_H_ 
    8#if !V8_ENABLE_WEBASSEMBLY 
    9#error This header should only be included if WebAssembly is enabled. 
   37#ifdef V8_HOST_ARCH_ARM64 
   39#elif !defined(__clang__)   
   41#elif defined(V8_DRUMBRAKE_BOUNDS_CHECKS) 
   44#define VECTORCALL __vectorcall 
   47#define INSTRUCTION_HANDLER_FUNC \ 
   48  __attribute__((noinline)) static DISABLE_CFI_ICALL void VECTORCALL 
 
   55class WasmInstanceObject;
 
   61struct InterpreterCode;
 
   62class InterpreterHandle;
 
   63struct ModuleWireBytes;
 
   65class WasmBytecodeGenerator;
 
   69class WasmInterpreterRuntime;
 
   70class WasmInterpreterThread;
 
   83                  const uint8_t* 
start, 
const uint8_t* 
end)
 
 
 
  104#ifdef V8_ENABLE_DRUMBRAKE_TRACING
 
  106        current_stack_height_(0),
 
  107        current_stack_start_args_(0),
 
  108        current_stack_start_locals_(0),
 
  109        current_stack_start_stack_(0)
 
 
  126                                          uint32_t catch_block_index) 
const;
 
  132#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  133  uint32_t current_stack_height_;
 
  134  uint32_t current_stack_start_args_;
 
  135  uint32_t current_stack_start_locals_;
 
  136  uint32_t current_stack_start_stack_;
 
 
  190  void NotifyIsolateDisposal(
Isolate* isolate);
 
  193  typedef std::unordered_map<int, std::unique_ptr<WasmInterpreterThread>>
 
 
  276  enum State { STOPPED, RUNNING, FINISHED, TRAPPED, EH_UNWINDING };
 
  290               uint8_t* start_fp, 
const FrameState& callee_frame_state)
 
  293          frame_pointer_(frame_pointer),
 
  294          current_frame_size_(0),
 
  295          current_ref_stack_fp_(0),
 
  296          current_ref_stack_frame_size_(0),
 
  297          current_fp_(start_fp),
 
  298          current_frame_state_(callee_frame_state)
 
  299#ifdef V8_ENABLE_DRUMBRAKE_TRACING
 
  301          current_stack_start_(callee_frame_state.current_stack_start_args_ +
 
  302                               thread->CurrentStackFrameSize()),
 
  303          current_stack_size_(0)
 
 
  310    inline Isolate* GetIsolate() 
const;
 
  315      current_frame_state_ = frame_state;
 
 
  320                                   uint32_t current_frame_size,
 
  321                                   uint32_t current_stack_size,
 
  322                                   uint32_t current_ref_stack_fp,
 
  323                                   uint32_t current_ref_stack_frame_size) {
 
  324      current_fp_ = current_fp;
 
  325      current_frame_size_ = current_frame_size;
 
  326      current_ref_stack_fp_ = current_ref_stack_fp;
 
  327      current_ref_stack_frame_size_ = current_ref_stack_frame_size;
 
  329#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  330      current_stack_size_ = current_stack_size;
 
 
  335      return current_fp_ + current_frame_size_;
 
 
  339      return current_ref_stack_fp_ + current_ref_stack_frame_size_;
 
 
  347      TrapStatus trap_status{trap_function_index, trap_pc};
 
  349          std::make_unique<std::vector<WasmInterpreterStackEntry>>(
 
  350              CaptureStackTrace(&trap_status));
 
 
  354      if (trap_stack_trace_) {
 
  355        return *trap_stack_trace_;
 
  360      return CaptureStackTrace();
 
 
  363    int GetFunctionIndex(
int index) 
const;
 
  366      return wasm_runtime_;
 
 
  369#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  370    uint32_t CurrentStackFrameStart()
 const { 
return current_stack_start_; }
 
  371    uint32_t CurrentStackFrameSize()
 const { 
return current_stack_size_; }
 
  375    std::vector<WasmInterpreterStackEntry> CaptureStackTrace(
 
  376        const TrapStatus* trap_status = 
nullptr) 
const;
 
  387#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  388    uint32_t current_stack_start_;
 
  389    uint32_t current_stack_size_;
 
 
  399    if (current_stack_size_ + additional_required_size > kMaxStackSize) {
 
  403    uint32_t new_size = current_stack_size_;
 
  404    while (new_size < current_stack_size_ + additional_required_size) {
 
  405      new_size = std::min(new_size + kStackSizeIncrement, kMaxStackSize);
 
  409                       PageAllocator::Permission::kReadWrite)) {
 
  410      current_stack_size_ = new_size;
 
 
  418    if (thread_interpreter_map_s) 
return;
 
 
  423    delete thread_interpreter_map_s;
 
  424    thread_interpreter_map_s = 
nullptr;
 
 
  428    thread_interpreter_map_s->NotifyIsolateDisposal(isolate);
 
 
  433    return thread_interpreter_map_s->GetCurrentInterpreterThread(isolate);
 
 
  441    if (!trap_handler::IsThreadInWasm()) {
 
  442      trap_handler::SetThreadInWasm();
 
 
  451    trap_reason_ = trap_reason;
 
  453    DCHECK(!activations_.empty());
 
  454    activations_.back()->SetCurrentFrame(current_frame);
 
  455    activations_.back()->SetTrapped(trap_function_index, trap_pc);
 
 
  463      uint8_t* interpreter_fp, 
const FrameState& frame_state);
 
  464  inline void FinishActivation();
 
  465  inline const FrameState* GetCurrentActivationFor(
 
  469    DCHECK(!activations_.empty());
 
  470    activations_.back()->SetCurrentFrame(frame_state);
 
 
  474                                        uint32_t current_frame_size,
 
  475                                        uint32_t current_stack_size,
 
  476                                        uint32_t current_ref_stack_fp,
 
  477                                        uint32_t current_ref_stack_frame_size) {
 
  478    DCHECK(!activations_.empty());
 
  479    activations_.back()->SetCurrentActivationFrame(
 
  480        reinterpret_cast<uint8_t*
>(fp), current_frame_size, current_stack_size,
 
  481        current_ref_stack_fp, current_ref_stack_frame_size);
 
 
  485      Address frame_pointer)
 const {
 
  486    for (
size_t i = 0; 
i < activations_.
size(); 
i++) {
 
  487      if (activations_[
i]->GetFramePointer() == frame_pointer) {
 
  488        return activations_[
i].get();
 
 
  495    if (activations_.empty()) {
 
  498      return activations_.back()->NextFrameAddress();
 
 
  503    if (activations_.empty()) {
 
  506      return activations_.back()->NextRefStackOffset();
 
 
  510    return stack_mem() + current_stack_size_;
 
 
  513  void EnsureRefStackSpace(
size_t new_size);
 
  514  void ClearRefStackValues(
size_t index, 
size_t count);
 
  516  void StartExecutionTimer();
 
  517  void StopExecutionTimer();
 
  518  void TerminateExecutionTimers();
 
  520  static void SetRuntimeLastWasmError(
Isolate* isolate,
 
  524#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  525  uint32_t CurrentStackFrameStart()
 const {
 
  526    if (activations_.empty()) {
 
  529      return activations_.back()->CurrentStackFrameStart();
 
  533  uint32_t CurrentStackFrameSize()
 const {
 
  534    if (activations_.empty()) {
 
  537      return activations_.back()->CurrentStackFrameSize();
 
  542  void RaiseException(Isolate* isolate, MessageTemplate message);
 
  548    return reinterpret_cast<uint8_t*
>(stack_mem_);
 
 
  557  static constexpr uint32_t kInitialStackSize = 1 * 
MB;
 
  558  static constexpr uint32_t kStackSizeIncrement = 1 * 
MB;
 
  559  static constexpr uint32_t kMaxStackSize = 32 * 
MB;
 
 
  591            const uint8_t* module_start, 
Zone* zone);
 
  597    inline WasmBytecode* GetFunctionBytecode(uint32_t func_index);
 
  600                            const uint8_t* code_start, 
const uint8_t* code_end);
 
  603      return generated_code_size_.load(std::memory_order_relaxed);
 
 
  607    void Preprocess(uint32_t function_index);
 
 
  622  static void InitializeOncePerProcess();
 
  623  static void GlobalTearDown();
 
  624  static void NotifyIsolateDisposal(
Isolate* isolate);
 
  627                             uint32_t function_index, Address frame_pointer,
 
  628                             uint8_t* interpreter_fp, uint32_t ref_stack_offset,
 
  629                             const std::vector<WasmValue>& argument_values);
 
  631                             uint32_t function_index, Address frame_pointer,
 
  632                             uint8_t* interpreter_fp);
 
  635                                                 bool called_from_js);
 
  637  inline WasmValue GetReturnValue(
int index) 
const;
 
  639  inline std::vector<WasmInterpreterStackEntry> GetInterpretedStack(
 
  640      Address frame_pointer);
 
  642  inline int GetFunctionIndex(Address frame_pointer, 
int index) 
const;
 
  644  inline void SetTrapFunctionIndex(int32_t func_index);
 
  647    return wasm_runtime_.get();
 
 
 
  676#define MUSTTAIL [[clang::musttail]] 
  683#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
  684extern char const* kInstructionHandlerNames[];
 
  688template <
bool compact_handler>
 
 1152  operator bool()
 const { 
return length > 0; }
 
 
 1173template <
typename T>
 
 1176                                        int64_t 
r0, 
double fp0);
 
 1178template <
typename T>
 
 1218#define DEFINE_INSTR_HANDLER(name) k_##name, 
 1221#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 
 1226#undef DEFINE_INSTR_HANDLER 
 1230      reinterpret_cast<Address>(code));
 
 1231#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1232  if (
v8_flags.trace_drumbrake_compact_bytecode) {
 
 1233    printf(
"* ReadFnId %04x %s%s\n", 
result,
 
 
 1324                   BlockIndex parent_or_matching_try_block_index,
 
 1327                     uint32_t first_param_slot_offset,
 
 1328                     uint32_t first_param_ref_stack_index,
 
 
 1345  WasmBytecode(
int func_index, 
const uint8_t* code_data, 
size_t code_length,
 
 1346               uint32_t stack_frame_size, 
const FunctionSig* signature,
 
 1349               const uint8_t* const_slots_data, 
size_t const_slots_length,
 
 1351               const std::map<CodeOffset, pc_t>&& code_pc_map);
 
 1416                                          uint32_t catch_block_index)
 const {
 
 
 
 1468              int32_t parent_block_index, uint32_t stack_size,
 
 1470              uint32_t first_block_index, uint32_t rets_slots_count,
 
 1471              uint32_t params_slots_count, int32_t parent_try_block_index)
 
 
 1498      for (
size_t i = 0; 
i < params_count; 
i++) {
 
 
 
 1531    return static_cast<uint32_t
>(
code_.size());
 
 
 1563  void Emit(
const void* buff, 
size_t len) {
 
 1564    code_.insert(
code_.end(), 
static_cast<const uint8_t*
>(buff),
 
 1565                 static_cast<const uint8_t*
>(buff) + len);
 
 
 1568  inline void I32Push(
bool emit = 
true);
 
 1569  inline void I64Push(
bool emit = 
true);
 
 1572  inline void F32Push(
bool emit = 
true);
 
 1573  inline void F64Push(
bool emit = 
true);
 
 1574  inline void S128Push(
bool emit = 
true);
 
 1599    } 
else if (value_kind == 
kI8 || value_kind == 
kI16) {
 
 1600      return stack_slot_kind == 
kI32;
 
 1602      return value_kind == stack_slot_kind;
 
 1613    uint32_t slot_offset = 
PopSlot();
 
 
 1623#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1624    if (
v8_flags.trace_drumbrake_compact_bytecode) {
 
 1625      printf(
"EmitSlotOffset %d\n", value);
 
 1633        uint16_t u16 = 
static_cast<uint16_t
>(
value);
 
 1634        Emit(&u16, 
sizeof(u16));
 
 1639      Emit(&value, 
sizeof(value));
 
 
 1643#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1644    if (
v8_flags.trace_drumbrake_compact_bytecode) {
 
 1645      printf(
"EmitMemoryOffset %llu\n", value);
 
 1653        uint32_t u32 = 
static_cast<uint32_t
>(
value);
 
 1654        Emit(&u32, 
sizeof(u32));
 
 1659      Emit(&value, 
sizeof(value));
 
 
 1667    Emit(&value, 
sizeof(value));
 
 
 1675    if (
pc != UINT_MAX) {
 
 1681    int16_t 
id = func_id;
 
 1687    Emit(&
id, 
sizeof(
id));
 
 1689#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1690    if (
v8_flags.trace_drumbrake_compact_bytecode) {
 
 1691      printf(
"* EmitFnId %04x %s%s\n", 
id, kInstructionHandlerNames[func_id],
 
 
 1698                    uint32_t to_slot_index, 
bool copy_from_reg = 
false);
 
 1708                             size_t* rets_slots_count,
 
 1709                             size_t* params_slots_count);
 
 1746  bool FindSharedSlot(uint32_t stack_index, uint32_t* new_slot_index);
 
 1776  template <
typename T>
 
 1781    if constexpr (std::is_same_v<T, WasmRef>) {
 
 1784    uint32_t slot_index = 
static_cast<uint32_t
>(
slots_.size());
 
 
 1790    uint32_t slot_index = 
static_cast<uint32_t
>(
slots_.size());
 
 
 1797  template <
typename T>
 
 1799    if constexpr (std::is_same_v<T, int32_t>) {
 
 1802    if constexpr (std::is_same_v<T, int64_t>) {
 
 1805    if constexpr (std::is_same_v<T, float>) {
 
 1808    if constexpr (std::is_same_v<T, double>) {
 
 1811    if constexpr (std::is_same_v<T, Simd128>) {
 
 
 1852  template <
typename T>
 
 1854    if constexpr (std::is_same_v<T, WasmRef>) {
 
 1858    if (slot_index == UINT_MAX) {
 
 1862      slot_index = 
static_cast<uint32_t
>(
slots_.size());
 
 
 1873  template <
typename T>
 
 1877    return new_slot_index;
 
 
 1880#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1881  void TracePushConstSlot(uint32_t slot_index);
 
 1885#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1886    if (
v8_flags.trace_drumbrake_bytecode_generator &&
 
 1887        v8_flags.trace_drumbrake_execution_verbose) {
 
 1888      printf(
"    push - slot[%d] = %d\n", 
stack_size(), slot_index);
 
 
 1901#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1902  void TracePushCopySlot(uint32_t from_stack_index);
 
 1912#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1913    if (
v8_flags.trace_drumbrake_bytecode_generator &&
 
 1914        v8_flags.trace_drumbrake_execution_verbose) {
 
 
 1924                  uint32_t to_stack_index, 
bool copy_from_reg);
 
 1926                        bool copy_from_reg);
 
 1931    uint32_t slot_index = 
stack_[stack_index];
 
 1934#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1935    TraceSetSlotType(stack_index, type);
 
 
 1939#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 1940  void TraceSetSlotType(uint32_t stack_index, 
ValueType typo);
 
 1956    return static_cast<uint32_t
>(
stack_.
size() - 1);
 
 
 1981  static bool HasSideEffects(
WasmOpcode opcode);
 
 2068  bool was_current_instruction_reachable_;
 
 
 2113#ifdef V8_ENABLE_DRUMBRAKE_TRACING 
 2114class InterpreterTracer final : 
public Malloced {
 
 2116  explicit InterpreterTracer(
int isolate_id)
 
 2117      : isolate_id_(isolate_id),
 
 2119        current_chunk_index_(0),
 
 2121    if (0 != strcmp(
v8_flags.trace_drumbrake_filter.value(), 
"*")) {
 
 2122      std::stringstream 
s(
v8_flags.trace_drumbrake_filter.value());
 
 2123      for (
int i; s >> 
i;) {
 
 2124        traced_functions_.insert(
i);
 
 2125        if (s.peek() == 
',') s.ignore();
 
 2132  ~InterpreterTracer() { CloseFile(); }
 
 2135    if (!ShouldRedirect()) {
 
 2140    if (isolate_id_ >= 0) {
 
 2141      base::SNPrintF(filename_, 
"trace-%d-%d-%d.dbt",
 
 2142                     base::OS::GetCurrentProcessId(), isolate_id_,
 
 2143                     current_chunk_index_);
 
 2145      base::SNPrintF(filename_, 
"trace-%d-%d.dbt",
 
 2146                     base::OS::GetCurrentProcessId(), current_chunk_index_);
 
 2150    if (file_ == 
nullptr) {
 
 2151      file_ = base::OS::FOpen(filename_.begin(), 
"w");
 
 2157    if (!ShouldRedirect()) {
 
 2162    base::Fclose(file_);
 
 2166  bool ShouldTraceFunction(
int function_index)
 const {
 
 2167    return traced_functions_.empty() ||
 
 2168           traced_functions_.find(function_index) != traced_functions_.end();
 
 2171  void PrintF(
const char* format, ...);
 
 2173  void CheckFileSize() {
 
 2174    if (!ShouldRedirect()) {
 
 2179    if (++write_count_ >= kWriteCountCheckInterval) {
 
 2181      ::fseek(file_, 0L, SEEK_END);
 
 2182      if (::ftell(file_) > kMaxFileSize) {
 
 2184        current_chunk_index_ = (current_chunk_index_ + 1) % kFileChunksCount;
 
 2190  FILE* 
file()
 const { 
return file_; }
 
 2193  static bool ShouldRedirect() { 
return v8_flags.redirect_drumbrake_traces; }
 
 2196  base::EmbeddedVector<char, 128> filename_;
 
 2198  std::unordered_set<int> traced_functions_;
 
 2199  int current_chunk_index_;
 
 2200  int64_t write_count_;
 
 2202  static const int64_t kWriteCountCheckInterval = 1000;
 
 2203  static const int kFileChunksCount = 10;
 
 2204  static const int64_t kMaxFileSize = 100 * 
MB;
 
 2209  void TracePop() { stack_.pop_back(); }
 
 2211  void TraceSetSlotType(uint32_t index, uint32_t type) {
 
 2212    if (stack_.size() <= index) stack_.resize(index + 1);
 
 2213    stack_[
index].type_ = ValueType::FromRawBitField(type);
 
 2216  template <
typename T>
 
 2217  void TracePush(uint32_t slot_offset) {
 
 2218    stack_.push_back({value_type<T>(), slot_offset});
 
 2221  void TracePushCopy(uint32_t index) { stack_.push_back(stack_[index]); }
 
 2223  void TraceUpdate(uint32_t stack_index, uint32_t slot_offset) {
 
 2224    if (stack_.size() <= stack_index) stack_.resize(stack_index + 1);
 
 2225    stack_[stack_index].slot_offset_ = slot_offset;
 
 2228  void Print(WasmInterpreterRuntime* wasm_runtime, 
const uint32_t* sp,
 
 2229             size_t start_params, 
size_t start_locals, 
size_t start_stack,
 
 2230             RegMode reg_mode, int64_t r0, 
double fp0) 
const;
 
 2233    static void Print(WasmInterpreterRuntime* wasm_runtime, ValueType type,
 
 2234                      size_t index, 
char kind, 
const uint8_t* addr);
 
 2235    void Print(WasmInterpreterRuntime* wasm_runtime, 
size_t index, 
char kind,
 
 2236               const uint8_t* addr)
 const {
 
 2237      return Print(wasm_runtime, 
type_, index, 
kind, addr);
 
 2241    uint32_t slot_offset_;
 
 2245  std::vector<Slot> stack_;
 
static constexpr HeapType FromBits(uint32_t bits)
constexpr bool is_bottom() const
constexpr ValueKind kind() const
constexpr bool is_object_reference() const
static constexpr ValueType FromRawBitField(uint32_t bits)
std::vector< uint32_t > Stack
void resize(Stack::size_type count)
Stack::const_reference operator[](Stack::size_type pos) const
Stack::const_reference back() const
void reserve(Stack::size_type new_cap)
void push_back(const uint32_t &value)
Stack::reference operator[](Stack::size_type pos)
std::vector< Entry > history_
bool IsMultiMemory() const
uint32_t GetS128ConstSlot(Simd128 value)
static void PrintBytecodeCompressionStats()
void EmitI32Const(int32_t value)
static std::atomic< size_t > emitted_short_memory_offset_count_
int32_t EndBlock(WasmOpcode opcode)
ValueType GetParamType(const WasmBytecodeGenerator::BlockData &block_data, size_t index) const
uint32_t const_slots_start() const
void BeginElseBlock(uint32_t if_block_index, bool dummy)
void Pop(ValueKind kind, bool emit=true)
void EmitFnId(InstructionHandler func_id, uint32_t pc=UINT_MAX)
void CopyToSlotAndPop(ValueType value_type, uint32_t to, bool is_tee, bool copy_from_reg)
void(WasmBytecodeGenerator::*) MemIndexPopFunc(bool emit)
void EmitBranchOffset(uint32_t delta)
void EmitStackIndex(int32_t value)
std::vector< uint8_t > code_
uint32_t rets_slots_size_
void EmitBranchTableOffset(uint32_t delta, uint32_t code_pos)
void EmitCopySlot(ValueType value_type, uint32_t from_slot_index, uint32_t to_slot_index, bool copy_from_reg=false)
uint32_t _PushSlot(ValueType value_type)
std::vector< Simd128 > simd_immediates_
void SetSlotType(uint32_t stack_index, ValueType type)
base::SmallVector< uint32_t, 8 > br_table_labels_
bool TypeCheckAlwaysSucceeds(ValueType obj_type, HeapType type) const
const FunctionSig * GetFunctionSignature(uint32_t function_index) const
uint32_t GetF64ConstSlot(double value)
bool no_nested_emit_instr_handler_guard_
WasmEHDataGenerator eh_data_
void ITableIndexPush(bool is_table64, bool emit=true)
void PushSlot(uint32_t slot_index)
bool HasVoidSignature(const WasmBytecodeGenerator::BlockData &block_data) const
uint32_t function_index() const
std::unordered_map< float, uint32_t > f32_const_cache_
WasmBytecodeGenerator(const WasmBytecodeGenerator &)=delete
void(WasmBytecodeGenerator::*) MemIndexPushFunc(bool emit)
void EmitMemoryOffset(uint64_t value)
uint32_t CurrentCodePos() const
uint32_t CreateWasmRefSlot(ValueType value_type)
uint32_t CreateConstSlot(T value)
uint32_t CreateSlot(ValueType value_type)
uint32_t stack_top_index() const
void DecodeAtomicOp(WasmOpcode opcode, WasmInstruction::Optional *optional, Decoder *decoder, InterpreterCode *code, pc_t pc, int *const len)
base::SmallVector< uint32_t, 16 > loop_begin_code_offsets_
void Push(ValueType type)
uint32_t GetI32ConstSlot(int32_t value)
ValueKind GetTopStackType(RegMode reg_mode) const
uint32_t GetConstSlot(T value)
RegMode DoEncodeInstruction(const WasmInstruction &instr, RegMode curr_reg_mode, RegMode next_reg_mode)
void DecodeGCOp(WasmOpcode opcode, WasmInstruction::Optional *optional, Decoder *decoder, InterpreterCode *code, pc_t pc, int *const len)
void PushCopySlot(uint32_t from_stack_index)
std::map< CodeOffset, pc_t > code_pc_map_
ValueType GetReturnType(const WasmBytecodeGenerator::BlockData &block_data, size_t index) const
std::unordered_map< Simd128, uint32_t, Simd128Hash > s128_const_cache_
void I32Pop(bool emit=true)
uint32_t GetStackFrameSize() const
void EmitI16Const(int16_t value)
uint32_t const_slot_offset_
static const CodeOffset kInvalidCodeOffset
void StoreBlockParamsAndResultsIntoSlots(uint32_t target_block_index, WasmOpcode opcode)
void EmitTryCatchBranchOffset()
std::unordered_map< double, uint32_t > f64_const_cache_
static std::atomic< size_t > total_bytecode_size_
uint32_t ReturnsCount(const WasmBytecodeGenerator::BlockData &block_data) const
WasmBytecodeGenerator(uint32_t function_index, InterpreterCode *wasm_code, const WasmModule *module)
uint32_t ParamsCount(const WasmBytecodeGenerator::BlockData &block_data) const
std::unordered_map< int64_t, uint32_t > i64_const_cache_
bool DoEncodeSuperInstruction(RegMode ®_mode, const WasmInstruction &curr_instr, const WasmInstruction &next_instr)
void F32Push(bool emit=true)
int GetCurrentTryBlockIndex(bool return_matching_try_for_catch_blocks) const
uint32_t GetI64ConstSlot(int64_t value)
void EmitGlobalIndex(uint32_t index)
void RestoreIfElseParams(uint32_t if_block_index)
void MemIndexPop(bool emit=true)
uint32_t PushConstSlot(T value)
WasmInstruction DecodeInstruction(pc_t pc, Decoder &decoder)
std::unordered_map< int32_t, uint32_t > i32_const_cache_
void EmitF64Const(double value)
void S128Pop(bool emit=true)
void StoreBlockParamsIntoSlots(uint32_t target_block_index, bool update_stack)
void UpdateStack(uint32_t index, uint32_t slot_index)
uint32_t GetCurrentBranchDepth() const
bool EncodeSuperInstruction(RegMode ®_mode, const WasmInstruction &curr_instr, const WasmInstruction &next_instr)
bool HasSharedSlot(uint32_t stack_index) const
InterpreterCode * wasm_code_
ValueKind GetGlobalType(uint32_t index) const
void InitSlotsForFunctionArgs(const FunctionSig *sig, bool is_indirect_call)
uint32_t unreachable_block_count_
CodeOffset last_instr_offset_
MemIndexPushFunc int_mem_push_
uint32_t ReserveBlockSlots(uint8_t opcode, const WasmInstruction::Optional::Block &block_data, size_t *rets_slots_count, size_t *params_slots_count)
void PreserveArgsAndLocals()
void EmitRefStackIndex(int32_t value)
bool TypeCheckAlwaysFails(ValueType obj_type, HeapType expected_type, bool null_succeeds) const
void F64Push(bool emit=true)
void I64Push(bool emit=true)
int32_t current_block_index_
void EmitSlotOffset(uint32_t value)
int32_t BeginBlock(WasmOpcode opcode, const WasmInstruction::Optional::Block signature)
bool DecodeSimdOp(WasmOpcode opcode, WasmInstruction::Optional *optional, Decoder *decoder, InterpreterCode *code, pc_t pc, int *const len)
ValueType RefPop(bool emit=true)
void RefPush(ValueType type, bool emit=true)
void EmitIfElseBranchOffset()
uint32_t CreateSlot(ValueType value_type)
uint32_t ScanConstInstructions() const
bool TryCompactInstructionHandler(InstructionHandler func_addr)
InstrHandlerSize handler_size_
void EmitF32Const(float value)
void F64Pop(bool emit=true)
bool current_instr_encoding_failed_
void I32Push(bool emit=true)
RegMode EncodeInstruction(const WasmInstruction &instr, RegMode curr_reg_mode, RegMode next_reg_mode)
void EmitStructFieldOffset(int32_t value)
MemIndexPopFunc int_mem_pop_
const WasmModule * module_
void DecodeNumericOp(WasmOpcode opcode, WasmInstruction::Optional *optional, Decoder *decoder, InterpreterCode *code, pc_t pc, int *const len)
int32_t GetTargetBranch(uint32_t delta) const
uint32_t args_slots_size_
void UpdateStack(uint32_t index, uint32_t slot_index, ValueType value_type)
uint32_t GetF32ConstSlot(float value)
void EmitRefValueType(int32_t value)
bool FindSharedSlot(uint32_t stack_index, uint32_t *new_slot_index)
static std::atomic< size_t > emitted_short_slot_offset_count_
bool is_instruction_reachable_
uint32_t ref_slots_count_
void I64Pop(bool emit=true)
void SetUnreachableMode()
void Emit(const void *buff, size_t len)
std::vector< Slot > slots_
bool ToRegisterIsAllowed(const WasmInstruction &instr)
uint32_t stack_size() const
void F32Pop(bool emit=true)
WasmBytecodeGenerator & operator=(const WasmBytecodeGenerator &)=delete
void PatchBranchOffsets()
void S128Push(bool emit=true)
void CopyToSlot(ValueType value_type, uint32_t from_slot_index, uint32_t to_stack_index, bool copy_from_reg)
void PatchLoopBeginInstructions()
std::vector< BlockData > blocks_
std::vector< uint8_t > const_slots_values_
std::unique_ptr< WasmBytecode > GenerateBytecode()
void MemIndexPush(bool emit=true)
uint32_t args_slots_size_
static bool HasRefOrSimdArgs(const FunctionSig *sig)
uint32_t return_count() const
uint32_t args_count() const
ValueType return_type(size_t index) const
static uint32_t RefLocalsCount(const InterpreterCode *wasm_code)
std::vector< uint8_t > code_
uint32_t locals_slots_size_
const FunctionSig * GetFunctionSignature() const
static uint32_t JSToWasmWrapperPackedArraySize(const FunctionSig *sig)
uint32_t ref_slots_count_
WasmEHData::ExceptionPayloadSlotOffsets GetExceptionPayloadStartSlotOffsets(WasmEHData::BlockIndex catch_block_index) const
uint32_t total_frame_size_in_bytes_
bool InitializeSlots(uint8_t *sp, size_t stack_space) const
uint32_t locals_count() const
uint32_t ref_slots_count() const
size_t GetCodeSize() const
uint32_t locals_slots_size() const
uint32_t internal_ref_slots_count() const
uint32_t GetBlocksCount() const
WasmBytecode(int func_index, const uint8_t *code_data, size_t code_length, uint32_t stack_frame_size, const FunctionSig *signature, const CanonicalSig *canonical_signature, const InterpreterCode *interpreter_code, size_t blocks_count, const uint8_t *const_slots_data, size_t const_slots_length, uint32_t ref_slots_count, const WasmEHData &&eh_data, const std::map< CodeOffset, pc_t > &&code_pc_map)
static uint32_t RetsSizeInSlots(const FunctionSig *sig)
pc_t GetPcFromTrapCode(const uint8_t *current_code) const
const InterpreterCode * interpreter_code_
int GetFunctionIndex() const
const FunctionSig * signature_
const uint8_t * code_bytes_
DirectHandle< Object > GetCaughtException(Isolate *isolate, uint32_t catch_block_index) const
uint32_t ref_locals_count_
static uint32_t ArgsSizeInSlots(const FunctionSig *sig)
ValueType local_type(size_t index) const
const WasmEHData::TryBlock * GetParentTryBlock(const WasmEHData::TryBlock *try_block) const
uint32_t ref_rets_count() const
static bool ContainsSimd(const FunctionSig *sig)
static uint32_t LocalsSizeInSlots(const InterpreterCode *wasm_code)
ValueType arg_type(size_t index) const
uint32_t rets_slots_size() const
uint32_t ref_args_count() const
const CanonicalSig * canonical_signature_
uint32_t const_slots_size_in_bytes() const
uint32_t rets_slots_size_
std::map< CodeOffset, pc_t > code_pc_map_
std::vector< uint8_t > const_slots_values_
const CanonicalSig * GetCanonicalFunctionSignature() const
const uint8_t * GetCode() const
uint32_t ref_locals_count() const
static uint32_t RefArgsCount(const FunctionSig *sig)
static uint32_t RefRetsCount(const FunctionSig *sig)
uint32_t args_slots_size() const
const WasmEHData::TryBlock * GetTryBlock(CodeOffset code_offset) const
void AddCatchBlock(BlockIndex catch_block_index, int tag_index, uint32_t first_param_slot_offset, uint32_t first_param_ref_stack_index, CodeOffset code_offset)
BlockIndex current_try_block_index_
void AddTryBlock(BlockIndex try_block_index, BlockIndex parent_or_matching_try_block_index, BlockIndex ancestor_try_block_index)
void AddDelegatedBlock(BlockIndex delegated_try_block_index)
BlockIndex GetCurrentTryBlockIndex() const
void RecordPotentialExceptionThrowingInstruction(WasmOpcode opcode, CodeOffset code_offset)
BlockIndex EndTryCatchBlocks(BlockIndex block_index, CodeOffset code_offset)
ExceptionPayloadSlotOffsets GetExceptionPayloadStartSlotOffsets(BlockIndex catch_block_index) const
static const int kCatchAllTagIndex
std::unordered_map< BlockIndex, CatchBlock > catch_blocks_
void SetCaughtException(Isolate *isolate, BlockIndex catch_block_index, DirectHandle< Object > exception)
DirectHandle< Object > GetCaughtException(Isolate *isolate, BlockIndex catch_block_index) const
std::unordered_map< CodeOffset, BlockIndex > code_trycatch_map_
const TryBlock * GetTryBlock(CodeOffset code_offset) const
std::unordered_map< BlockIndex, TryBlock > try_blocks_
static const int kDelegateToCallerIndex
size_t GetEndInstructionOffsetFor(BlockIndex catch_block_index) const
BlockIndex GetTryBranchOf(BlockIndex catch_block_index) const
const TryBlock * GetParentTryBlock(const TryBlock *try_block) const
const TryBlock * GetDelegateTryBlock(const TryBlock *try_block) const
base::TimeTicks start_interval_time_
base::TimeTicks next_interval_time_
base::TimeDelta window_running_time_
const size_t slow_threshold_samples_count_
base::TimeDelta cooldown_interval_
std::vector< int > samples_
Histogram * slow_wasm_histogram_
base::ElapsedTimer window_execute_timer_
const int slow_threshold_
void BeginInterval(bool start_timer)
static const int kMaxPercentValue
const base::TimeDelta sample_duration_
Histogram * execute_ratio_histogram_
void AddSample(int running_ratio)
WasmExecutionTimer(Isolate *isolate, bool track_jitless_wasm)
std::unordered_map< int, std::unique_ptr< WasmInterpreterThread > > ThreadInterpreterMap
ThreadInterpreterMap map_
void SetCurrentActivationFrame(uint8_t *current_fp, uint32_t current_frame_size, uint32_t current_stack_size, uint32_t current_ref_stack_fp, uint32_t current_ref_stack_frame_size)
void SetCurrentFrame(const FrameState &frame_state)
uint32_t current_ref_stack_fp_
std::unique_ptr< std::vector< WasmInterpreterStackEntry > > trap_stack_trace_
const FrameState & GetCurrentFrame() const
WasmInterpreterThread * thread() const
WasmInterpreterRuntime * wasm_runtime_
Activation(WasmInterpreterThread *thread, WasmInterpreterRuntime *wasm_runtime, Address frame_pointer, uint8_t *start_fp, const FrameState &callee_frame_state)
uint32_t current_ref_stack_frame_size_
uint32_t current_frame_size_
void SetTrapped(int trap_function_index, int trap_pc)
WasmInterpreterThread * thread_
FrameState current_frame_state_
uint32_t NextRefStackOffset() const
Address GetFramePointer() const
std::vector< WasmInterpreterStackEntry > GetStackTrace()
uint8_t * NextFrameAddress() const
const WasmInterpreterRuntime * GetWasmRuntime() const
void Trap(TrapReason trap_reason, int trap_function_index, int trap_pc, const FrameState ¤t_frame)
bool ExpandStack(size_t additional_required_size)
TrapReason GetTrapReason() const
static void NotifyIsolateDisposal(Isolate *isolate)
void SetCurrentActivationFrame(uint32_t *fp, uint32_t current_frame_size, uint32_t current_stack_size, uint32_t current_ref_stack_fp, uint32_t current_ref_stack_frame_size)
static WasmInterpreterThreadMap * thread_interpreter_map_s
WasmInterpreterThread::Activation * GetActivation(Address frame_pointer) const
Handle< FixedArray > reference_stack() const
std::vector< std::unique_ptr< Activation > > activations_
uint32_t NextRefStackOffset() const
const uint8_t * StackLimitAddress() const
Handle< FixedArray > reference_stack_
uint8_t * stack_mem() const
size_t current_ref_stack_size_
WasmExecutionTimer execution_timer_
static WasmInterpreterThread * GetCurrentInterpreterThread(Isolate *isolate)
uint32_t current_stack_size_
const Isolate * GetIsolate() const
void SetCurrentFrame(const FrameState &frame_state)
uint8_t * NextFrameAddress() const
size_t TotalBytecodeSize()
std::atomic< size_t > generated_code_size_
const WasmModule * module() const
base::TimeDelta bytecode_generation_time_
const WasmModule * module_
ZoneVector< InterpreterCode > interpreter_code_
WasmInterpreter & operator=(const WasmInterpreter &)=delete
WasmInterpreterRuntime * GetWasmRuntime()
std::shared_ptr< WasmInterpreterRuntime > wasm_runtime_
IndirectHandle< WasmInstanceObject > instance_object_
const ZoneVector< uint8_t > module_bytes_
WasmInterpreter(const WasmInterpreter &)=delete
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage * MB
#define FOREACH_INSTR_HANDLER(V)
ZoneVector< RpoNumber > & result
static V ReadUnalignedValue(Address p)
static void WriteUnalignedValue(Address p, V value)
RegMode GetRegMode(ValueKind kind)
ValueType value_type< int64_t >()
static ValueType value_type()
static const size_t kSlotSize
ValueType value_type< uint64_t >()
PWasmOp * kInstructionTable[kInstructionTableSize]
static const RegModeTransform kRegModes[256]
constexpr uint32_t kBranchOnCastDataTargetTypeBitSize
static const size_t kOperatorModeCount
InstructionHandler ReadFnId(const uint8_t *&code)
ValueType value_type< Simd128 >()
uint32_t WasmInterpreterRuntime int64_t r0
ValueType value_type< double >()
constexpr IndependentValueType kWasmF32
constexpr IndependentHeapType kWasmAnyRef
uint32_t WasmInterpreterRuntime * wasm_runtime
constexpr IndependentValueType kWasmI32
ValueType value_type< uint32_t >()
uint32_t WasmInterpreterRuntime int64_t double fp0
DirectHandle< Object > WasmRef
INSTRUCTION_HANDLER_FUNC trace_PushSlot(const uint8_t *code, uint32_t *sp, WasmInterpreterRuntime *wasm_runtime, int64_t r0, double fp0)
static const ptrdiff_t kCodeOffsetSize
static constexpr uint32_t kInstructionTableMask
InstructionHandler s_unwind_code
ValueType value_type< WasmRef >()
ValueType value_type< int32_t >()
typedef void(VECTORCALL PWasmOp)(const uint8_t *code
static constexpr uint32_t kInstructionTableSize
constexpr IndependentValueType kWasmS128
constexpr IndependentValueType kWasmF64
constexpr bool is_reference(ValueKind kind)
constexpr IndependentValueType kWasmI64
ValueType value_type< float >()
bool SetPermissions(v8::PageAllocator *page_allocator, void *address, size_t size, PageAllocator::Permission access)
v8::PageAllocator * GetPlatformPageAllocator()
void PrintF(const char *format,...)
wasm::WasmModule WasmModule
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr int kSystemPointerSize
int WriteChars(const char *filename, const char *str, int size, bool verbose)
V8_EXPORT_PRIVATE FlagValues v8_flags
wasm::WasmFunction WasmFunction
#define DCHECK_LE(v1, v2)
#define CHECK_GE(lhs, rhs)
#define CHECK_WITH_MSG(condition, message)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define V8_EXPORT_PRIVATE
uint32_t target_type_bit_fields
WasmInterpreterThread * thread_
DirectHandle< Object > GetCaughtException(Isolate *isolate, uint32_t catch_block_index) const
void ResetHandleScope(Isolate *isolate)
const FrameState * previous_frame_
HandleScope * handle_scope_
void SetCaughtException(Isolate *isolate, uint32_t catch_block_index, DirectHandle< Object > exception)
const WasmBytecode * current_function_
Handle< FixedArray > caught_exceptions_
const uint8_t * current_bytecode_
uint32_t ref_array_current_sp_
void DisposeCaughtExceptionsArray(Isolate *isolate)
std::unique_ptr< WasmBytecode > bytecode
InterpreterCode(const WasmFunction *function, BodyLocalDecls locals, const uint8_t *start, const uint8_t *end)
const WasmFunction * function
const uint8_t * at(pc_t pc)
constexpr ValueKind kind() const
int32_t parent_block_index_
BlockData(WasmOpcode opcode, uint32_t begin_code_offset, int32_t parent_block_index, uint32_t stack_size, WasmInstruction::Optional::Block signature, uint32_t first_block_index, uint32_t rets_slots_count, uint32_t params_slots_count, int32_t parent_try_block_index)
uint32_t end_code_offset_
base::SmallVector< uint32_t, 4 > branch_code_offsets_
base::SmallVector< uint32_t, 4 > if_block_params_
uint32_t params_slots_count_
int32_t parent_try_block_index_
void SaveParams(uint32_t *from, size_t params_count)
WasmInstruction::Optional::Block signature_
uint32_t begin_code_offset_
uint32_t rets_slots_count_
uint32_t first_block_index_
int32_t if_else_block_index_
bool HasElseBranch() const
uint32_t GetParam(size_t index) const
size_t operator()(const Simd128 &s128) const
BlockIndex try_block_index
uint32_t first_param_ref_stack_index
uint32_t first_param_slot_offset
BlockIndex catch_block_index
uint32_t first_param_ref_stack_index
uint32_t first_param_slot_offset
TryBlock(BlockIndex parent_or_matching_try_block, BlockIndex ancestor_try_index)
BlockIndex delegate_try_index
void SetDelegated(BlockIndex delegate_try_idx)
std::vector< CatchHandler > catch_handlers
BlockIndex ancestor_try_index
bool IsTryDelegate() const
size_t end_instruction_code_offset
BlockIndex parent_or_matching_try_block
constexpr ValueType value_type() const
ModuleTypeIndex sig_index
uint32_t value_type_bitfield
constexpr bool is_bottom() const
uint32_t dest_array_index
uint32_t element_segment_index
WasmInstruction(uint8_t orig, WasmOpcode opcode, int length, uint32_t pc, Optional optional)
RegMode InputRegMode() const
bool SupportsToRegister() const
uint64_t memory_offset32_t
uint64_t memory_offset64_t
uint32_t memory_offset64_t
uint32_t memory_offset32_t
BranchOnCastData br_on_cast_data
struct v8::internal::wasm::WasmInstruction::Optional::Block block
struct v8::internal::wasm::WasmInstruction::Optional::BrTable br_table
struct v8::internal::wasm::WasmInstruction::Optional::SimdLaneLoad simd_loadstore_lane
struct v8::internal::wasm::WasmInstruction::Optional::TableInit table_init
struct v8::internal::wasm::WasmInstruction::Optional::GC_ArrayNewFixed gc_array_new_fixed
struct v8::internal::wasm::WasmInstruction::Optional::IndirectCall indirect_call
struct v8::internal::wasm::WasmInstruction::Optional::GC_FieldImmediate gc_field_immediate
uint32_t ref_type_bit_field
struct v8::internal::wasm::WasmInstruction::Optional::GC_ArrayCopy gc_array_copy
struct v8::internal::wasm::WasmInstruction::Optional::GC_MemoryImmediate gc_memory_immediate
struct v8::internal::wasm::WasmInstruction::Optional::GC_HeapTypeImmediate gc_heap_type_immediate
struct v8::internal::wasm::WasmInstruction::Optional::TableCopy table_copy
struct v8::internal::wasm::WasmInstruction::Optional::GC_ArrayNewOrInitData gc_array_new_or_init_data
size_t simd_immediate_index
#define V8_UNLIKELY(condition)
const wasm::WasmModule * module_
#define DEFINE_INSTR_HANDLER(name)
#define INSTRUCTION_HANDLER_FUNC