/* * Copyright (c) 2021, Ali Mohammad Pur * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include namespace Wasm { #define TRAP_IF_NOT(x) \ do { \ if (trap_if_not(x, #x##sv)) { \ dbgln_if(WASM_TRACE_DEBUG, "Trapped because {} failed, at line {}", #x, __LINE__); \ return; \ } \ } while (false) #define TRAP_IF_NOT_NORETURN(x) \ do { \ if (trap_if_not(x, #x##sv)) { \ dbgln_if(WASM_TRACE_DEBUG, "Trapped because {} failed, at line {}", #x, __LINE__); \ } \ } while (false) void BytecodeInterpreter::interpret(Configuration& configuration) { m_trap.clear(); auto& instructions = configuration.frame().expression().instructions(); auto max_ip_value = InstructionPointer { instructions.size() }; auto& current_ip_value = configuration.ip(); auto const should_limit_instruction_count = configuration.should_limit_instruction_count(); u64 executed_instructions = 0; while (current_ip_value < max_ip_value) { if (should_limit_instruction_count) { if (executed_instructions++ >= Constants::max_allowed_executed_instructions_per_call) [[unlikely]] { m_trap = Trap { "Exceeded maximum allowed number of instructions" }; return; } } auto& instruction = instructions[current_ip_value.value()]; auto old_ip = current_ip_value; interpret(configuration, current_ip_value, instruction); if (m_trap.has_value()) return; if (current_ip_value == old_ip) // If no jump occurred ++current_ip_value; } } void BytecodeInterpreter::branch_to_label(Configuration& configuration, LabelIndex index) { dbgln_if(WASM_TRACE_DEBUG, "Branch to label with index {}...", index.value()); auto label = configuration.nth_label(index.value()); dbgln_if(WASM_TRACE_DEBUG, "...which is actually IP {}, and has {} result(s)", label->continuation().value(), label->arity()); auto results = pop_values(configuration, label->arity()); size_t drop_count = index.value() + 1; for (; !configuration.stack().is_empty();) { auto& entry = configuration.stack().peek(); if (entry.has