5#ifndef V8_WASM_INTERPRETER_WASM_INTERPRETER_INL_H_
6#define V8_WASM_INTERPRETER_WASM_INTERPRETER_INL_H_
8#if !V8_ENABLE_WEBASSEMBLY
9#error This header should only be included if WebAssembly is enabled.
22 uint32_t function_index) {
32 uint32_t func_index) {
33 DCHECK_LT(func_index, interpreter_code_.size());
37 return code->bytecode.get();
41 const uint8_t* code_start,
42 const uint8_t* code_end) {
43 DCHECK_EQ(interpreter_code_.size(), function->func_index);
45 const_cast<uint8_t*
>(code_start),
46 const_cast<uint8_t*
>(code_end));
56 uint8_t* interpreter_fp,
59 activations_.emplace_back(std::make_unique<Activation>(
60 this,
wasm_runtime, frame_pointer, interpreter_fp, frame_state));
61 return activations_.back().get();
65 DCHECK(!activations_.empty());
66 activations_.pop_back();
67 if (activations_.empty()) {
68 if (
state_ != State::TRAPPED &&
state_ != State::STOPPED) {
76 for (
int i =
static_cast<int>(activations_.size()) - 1;
i >= 0;
i--) {
78 return &activations_[
i]->GetCurrentFrame();
86 Address frame_pointer, uint8_t* interpreter_fp, uint32_t ref_stack_offset,
87 const std::vector<WasmValue>&
args) {
89 wasm_runtime_->BeginExecution(thread, function_index, frame_pointer,
90 interpreter_fp, ref_stack_offset, &
args);
94 uint32_t function_index,
96 uint8_t* interpreter_fp) {
98 wasm_runtime_->BeginExecution(thread, function_index, frame_pointer,
99 interpreter_fp, thread->NextRefStackOffset());
106inline std::vector<WasmInterpreterStackEntry>
113 return wasm_runtime_->GetFunctionIndex(frame_pointer, index);
122 return signature_->GetReturn(index);
127 return signature_->GetParam(index);
132 DCHECK_LT(index, interpreter_code_->locals.num_locals);
133 return interpreter_code_->locals.local_types[
index];
167 uint32_t args_slots_size = 0;
168 size_t args_count =
sig->parameter_count();
169 for (
size_t i = 0;
i < args_count;
i++) {
172 return args_slots_size;
176 uint32_t rets_slots_size = 0;
177 size_t return_count =
static_cast<uint32_t
>(
sig->return_count());
178 for (
size_t i = 0;
i < return_count;
i++) {
181 return rets_slots_size;
185 uint32_t refs_args_count = 0;
186 size_t args_count =
static_cast<uint32_t
>(
sig->parameter_count());
187 for (
size_t i = 0;
i < args_count;
i++) {
191 return refs_args_count;
195 uint32_t refs_rets_count = 0;
196 size_t return_count =
static_cast<uint32_t
>(
sig->return_count());
197 for (
size_t i = 0;
i < return_count;
i++) {
201 return refs_rets_count;
205 size_t args_count =
static_cast<uint32_t
>(
sig->parameter_count());
206 for (
size_t i = 0;
i < args_count;
i++) {
207 if (
sig->GetParam(
i).kind() ==
kS128)
return true;
210 size_t return_count =
static_cast<uint32_t
>(
sig->return_count());
211 for (
size_t i = 0;
i < return_count;
i++) {
212 if (
sig->GetReturn(
i).kind() ==
kS128)
return true;
219 size_t args_count =
static_cast<uint32_t
>(
sig->parameter_count());
220 for (
size_t i = 0;
i < args_count;
i++) {
231 uint32_t args_size = 0;
232 size_t args_count =
static_cast<uint32_t
>(
sig->parameter_count());
233 for (
size_t i = 0;
i < args_count;
i++) {
234 switch (
sig->GetParam(
i).kind()) {
237 args_size +=
sizeof(int32_t);
241 args_size +=
sizeof(int64_t);
249 args_size += (args_size & 0x04);
257 uint32_t rets_size = 0;
258 size_t rets_count =
static_cast<uint32_t
>(
sig->return_count());
259 for (
size_t i = 0;
i < rets_count;
i++) {
260 switch (
sig->GetReturn(
i).kind()) {
263 rets_size +=
sizeof(int32_t);
267 rets_size +=
sizeof(int64_t);
275 rets_size += (rets_size & 0x04);
283 uint32_t size = std::max(args_size, rets_size);
285 size += (size & 0x04);
290 uint32_t refs_locals_count = 0;
292 for (
size_t i = 0;
i < locals_count;
i++) {
298 return refs_locals_count;
303 uint32_t locals_slots_size = 0;
305 for (
size_t i = 0;
i < locals_count;
i++) {
309 return locals_slots_size;
313 size_t stack_space)
const {
315 if (total_frame_size_in_bytes_ > stack_space) {
319 uint32_t args_slots_size_in_bytes = args_slots_size() *
kSlotSize;
320 uint32_t rets_slots_size_in_bytes = rets_slots_size() *
kSlotSize;
321 uint32_t const_slots_size_in_bytes = this->const_slots_size_in_bytes();
323 uint8_t* start_const_area =
324 sp + args_slots_size_in_bytes + rets_slots_size_in_bytes;
327 if (const_slots_size_in_bytes) {
328 memcpy(start_const_area, const_slots_values_.data(),
329 const_slots_size_in_bytes);
333 memset(start_const_area + const_slots_size_in_bytes, 0,
341 if (!
instr.SupportsToRegister())
return false;
345 switch (
instr.opcode) {
346 case kExprGlobalGet: {
351 case kExprSelectWithType: {
362 uint32_t slot_index = _PushSlot(
kWasmI32);
363 uint32_t slot_offset = slots_[slot_index].slot_offset;
364 if (emit) EmitSlotOffset(slot_offset);
368 uint32_t slot_index = _PushSlot(
kWasmI64);
369 uint32_t slot_offset = slots_[slot_index].slot_offset;
370 if (emit) EmitSlotOffset(slot_offset);
374 uint32_t slot_index = _PushSlot(
kWasmF32);
375 uint32_t slot_offset = slots_[slot_index].slot_offset;
376 if (emit) EmitSlotOffset(slot_offset);
380 uint32_t slot_index = _PushSlot(
kWasmF64);
381 uint32_t slot_offset = slots_[slot_index].slot_offset;
382 if (emit) EmitSlotOffset(slot_offset);
386 uint32_t slot_index = _PushSlot(
kWasmS128);
387 uint32_t slot_offset = slots_[slot_index].slot_offset;
388 if (emit) EmitSlotOffset(slot_offset);
392 uint32_t slot_index = _PushSlot(type);
393 uint32_t slot_offset = slots_[slot_index].slot_offset;
395 EmitSlotOffset(slot_offset);
396 EmitRefStackIndex(slots_[slot_index].ref_stack_index);
401 switch (type.kind()) {
427 DCHECK_LT(from_stack_index, stack_.size());
428 PushSlot(stack_[from_stack_index]);
430#ifdef V8_ENABLE_DRUMBRAKE_TRACING
431 TracePushCopySlot(from_stack_index);
436 PushSlot(slot_index);
438#ifdef V8_ENABLE_DRUMBRAKE_TRACING
439 TracePushConstSlot(slot_index);
448 return 0 == (
sig->parameter_count() +
sig->return_count());
460 return static_cast<uint32_t
>(
sig->parameter_count());
469 return sig->GetParam(index);
477 return static_cast<uint32_t
>(
sig->return_count());
490 return sig->GetReturn(index);
501 return !
module_->memories.empty() &&
module_->memories[0].is_memory64();
505 return module_->memories.size() > 1;
509 Emit(&index,
sizeof(index));
514 int index =
blocks_[current_block_index_].parent_block_index_;
524 int index = current_block_index_;
533 int32_t target_branch_index = GetTargetBranch(delta);
535 blocks_[target_branch_index].branch_code_offsets_.emplace_back(
538 const uint32_t current_code_offset = CurrentCodePos();
539 Emit(¤t_code_offset,
sizeof(current_code_offset));
544 int32_t target_branch_index = GetTargetBranch(delta);
546 blocks_[target_branch_index].branch_code_offsets_.emplace_back(code_pos);
548 Emit(&code_pos,
sizeof(code_pos));
555 blocks_[current_block_index_].branch_code_offsets_.emplace_back(
558 const uint32_t current_code_offset = CurrentCodePos();
559 Emit(¤t_code_offset,
sizeof(current_code_offset));
566 blocks_[current_block_index_].branch_code_offsets_.emplace_back(
569 const uint32_t current_code_offset = CurrentCodePos();
570 Emit(¤t_code_offset,
sizeof(current_code_offset));
576 RestoreIfElseParams(if_block_index);
578 int32_t else_block_index =
579 BeginBlock(kExprElse,
blocks_[if_block_index].signature_);
580 blocks_[if_block_index].if_else_block_index_ = else_block_index;
581 blocks_[else_block_index].if_else_block_index_ = if_block_index;
582 blocks_[else_block_index].first_block_index_ =
583 blocks_[if_block_index].first_block_index_;
587 uint32_t function_index)
const {
588 return module_->functions[function_index].sig;
595 if (stack_.empty())
return kI32;
596 return slots_[stack_[stack_top_index()]].kind();
constexpr ValueKind kind() const
bool IsMultiMemory() const
ValueType GetParamType(const WasmBytecodeGenerator::BlockData &block_data, size_t index) const
void BeginElseBlock(uint32_t if_block_index, bool dummy)
void EmitBranchOffset(uint32_t delta)
void EmitBranchTableOffset(uint32_t delta, uint32_t code_pos)
const FunctionSig * GetFunctionSignature(uint32_t function_index) const
bool HasVoidSignature(const WasmBytecodeGenerator::BlockData &block_data) const
void Push(ValueType type)
ValueKind GetTopStackType(RegMode reg_mode) const
void PushCopySlot(uint32_t from_stack_index)
ValueType GetReturnType(const WasmBytecodeGenerator::BlockData &block_data, size_t index) const
void EmitTryCatchBranchOffset()
uint32_t ReturnsCount(const WasmBytecodeGenerator::BlockData &block_data) const
uint32_t ParamsCount(const WasmBytecodeGenerator::BlockData &block_data) const
void F32Push(bool emit=true)
void EmitGlobalIndex(uint32_t index)
uint32_t PushConstSlot(T value)
uint32_t GetCurrentBranchDepth() const
ValueKind GetGlobalType(uint32_t index) const
void F64Push(bool emit=true)
void I64Push(bool emit=true)
void RefPush(ValueType type, bool emit=true)
void EmitIfElseBranchOffset()
void I32Push(bool emit=true)
int32_t GetTargetBranch(uint32_t delta) const
bool ToRegisterIsAllowed(const WasmInstruction &instr)
void S128Push(bool emit=true)
static bool HasRefOrSimdArgs(const FunctionSig *sig)
ValueType return_type(size_t index) const
static uint32_t RefLocalsCount(const InterpreterCode *wasm_code)
static uint32_t JSToWasmWrapperPackedArraySize(const FunctionSig *sig)
bool InitializeSlots(uint8_t *sp, size_t stack_space) const
static uint32_t RetsSizeInSlots(const FunctionSig *sig)
static uint32_t ArgsSizeInSlots(const FunctionSig *sig)
ValueType local_type(size_t index) const
static bool ContainsSimd(const FunctionSig *sig)
static uint32_t LocalsSizeInSlots(const InterpreterCode *wasm_code)
ValueType arg_type(size_t index) const
static uint32_t RefArgsCount(const FunctionSig *sig)
static uint32_t RefRetsCount(const FunctionSig *sig)
Isolate * GetIsolate() const
const FrameState * GetCurrentActivationFor(const WasmInterpreterRuntime *wasm_runtime) const
WasmInterpreterThread::Activation * StartActivation(WasmInterpreterRuntime *wasm_runtime, Address frame_pointer, uint8_t *interpreter_fp, const FrameState &frame_state)
InterpreterCode * GetCode(uint32_t function_index)
WasmBytecode * GetFunctionBytecode(uint32_t func_index)
void Preprocess(uint32_t function_index)
void AddFunction(const WasmFunction *function, const uint8_t *code_start, const uint8_t *code_end)
ZoneVector< InterpreterCode > interpreter_code_
std::vector< WasmInterpreterStackEntry > GetInterpretedStack(Address frame_pointer)
WasmInterpreterRuntime * GetWasmRuntime()
std::shared_ptr< WasmInterpreterRuntime > wasm_runtime_
int GetFunctionIndex(Address frame_pointer, int index) const
void SetTrapFunctionIndex(int32_t func_index)
void BeginExecution(WasmInterpreterThread *thread, uint32_t function_index, Address frame_pointer, uint8_t *interpreter_fp, uint32_t ref_stack_offset, const std::vector< WasmValue > &argument_values)
WasmValue GetReturnValue(int index) const
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
base::Vector< const DirectHandle< Object > > args
WordWithBits< 128 > Simd128
static const size_t kSlotSize
constexpr IndependentValueType kWasmF32
uint32_t WasmInterpreterRuntime * wasm_runtime
uint32_t GetValueSizeInSlots(ValueKind kind)
constexpr IndependentValueType kWasmI32
DirectHandle< Object > WasmRef
constexpr IndependentHeapType kWasmVoid
constexpr IndependentValueType kWasmS128
constexpr IndependentValueType kWasmF64
constexpr bool is_reference(ValueKind kind)
constexpr IndependentValueType kWasmI64
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
constexpr int kSystemPointerSize
std::vector< std::vector< ValueType > > blocks_
#define DCHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
void ResetHandleScope(Isolate *isolate)
WasmInstruction::Optional::Block signature_
constexpr ValueType value_type() const
ModuleTypeIndex sig_index
constexpr bool is_bottom() const
#define V8_UNLIKELY(condition)
const wasm::WasmModule * module_