diff options
Diffstat (limited to 'src/interp.cc')
-rw-r--r-- | src/interp.cc | 273 |
1 files changed, 133 insertions, 140 deletions
diff --git a/src/interp.cc b/src/interp.cc index 2c9ccdc6..c835b770 100644 --- a/src/interp.cc +++ b/src/interp.cc @@ -144,24 +144,14 @@ Module* Environment::FindRegisteredModule(string_view name) { } Thread::Options::Options(uint32_t value_stack_size, - uint32_t call_stack_size, - IstreamOffset pc, - Stream* trace_stream) + uint32_t call_stack_size) : value_stack_size(value_stack_size), - call_stack_size(call_stack_size), - pc(pc), - trace_stream(trace_stream) {} + call_stack_size(call_stack_size) {} Thread::Thread(Environment* env, const Options& options) : env_(env), value_stack_(options.value_stack_size), - call_stack_(options.call_stack_size), - value_stack_top_(value_stack_.data()), - value_stack_end_(value_stack_.data() + value_stack_.size()), - call_stack_top_(call_stack_.data()), - call_stack_end_(call_stack_.data() + call_stack_.size()), - pc_(options.pc), - trace_stream_(options.trace_stream) {} + call_stack_(options.call_stack_size) {} FuncSignature::FuncSignature(Index param_count, Type* param_types, @@ -243,34 +233,6 @@ HostModule* Environment::AppendHostModule(string_view name) { return module; } -Result Thread::PushArgs(const FuncSignature* sig, const TypedValues& args) { - if (sig->param_types.size() != args.size()) - return interp::Result::ArgumentTypeMismatch; - - for (size_t i = 0; i < sig->param_types.size(); ++i) { - if (sig->param_types[i] != args[i].type) - return interp::Result::ArgumentTypeMismatch; - - interp::Result iresult = Push(args[i].value); - if (iresult != interp::Result::Ok) { - value_stack_top_ = value_stack_.data(); - return iresult; - } - } - return interp::Result::Ok; -} - -void Thread::CopyResults(const FuncSignature* sig, TypedValues* out_results) { - size_t expected_results = sig->result_types.size(); - size_t value_stack_depth = value_stack_top_ - value_stack_.data(); - WABT_USE(value_stack_depth); - assert(expected_results == value_stack_depth); - - out_results->clear(); - for (size_t i = 0; i < expected_results; ++i) - out_results->emplace_back(sig->result_types[i], value_stack_[i]); -} - uint32_t ToRep(bool x) { return x ? 1 : 0; } uint32_t ToRep(uint32_t x) { return x; } uint64_t ToRep(uint64_t x) { return x; } @@ -587,7 +549,7 @@ template<> uint64_t GetValue<double>(Value v) { return v.f64_bits; } } while (0) #define CHECK_STACK() \ - TRAP_IF(value_stack_top_ >= value_stack_end_, ValueStackExhausted) + TRAP_IF(value_stack_top_ >= value_stack_.size(), ValueStackExhausted) #define PUSH_NEG_1_AND_BREAK_IF(cond) \ if (WABT_UNLIKELY(cond)) { \ @@ -690,17 +652,28 @@ Value& Thread::Top() { } Value& Thread::Pick(Index depth) { - return *(value_stack_top_ - depth); + return value_stack_[value_stack_top_ - depth]; +} + +void Thread::Reset() { + pc_ = 0; + value_stack_top_ = 0; + call_stack_top_ = 0; } Result Thread::Push(Value value) { CHECK_STACK(); - *value_stack_top_++ = value; + value_stack_[value_stack_top_++] = value; return Result::Ok; } Value Thread::Pop() { - return *--value_stack_top_; + return value_stack_[--value_stack_top_]; +} + +Value Thread::ValueAt(Index at) const { + assert(at < value_stack_top_); + return value_stack_[at]; } template <typename T> @@ -731,13 +704,13 @@ void Thread::DropKeep(uint32_t drop_count, uint8_t keep_count) { } Result Thread::PushCall(const uint8_t* pc) { - TRAP_IF(call_stack_top_ >= call_stack_end_, CallStackExhausted); - *call_stack_top_++ = pc - GetIstream(); + TRAP_IF(call_stack_top_ >= call_stack_.size(), CallStackExhausted); + call_stack_[call_stack_top_++] = pc - GetIstream(); return Result::Ok; } IstreamOffset Thread::PopCall() { - return *--call_stack_top_; + return call_stack_[--call_stack_top_]; } template <typename T> @@ -1221,87 +1194,6 @@ bool Environment::FuncSignaturesAreEqual(Index sig_index_0, sig_0->result_types == sig_1->result_types; } -Result Thread::RunFunction(Index func_index, - const TypedValues& args, - TypedValues* out_results) { - Func* func = env_->GetFunc(func_index); - FuncSignature* sig = env_->GetFuncSignature(func->sig_index); - - Result result = PushArgs(sig, args); - if (result == Result::Ok) { - result = func->is_host - ? CallHost(cast<HostFunc>(func)) - : RunDefinedFunction(cast<DefinedFunc>(func)->offset); - if (result == Result::Ok) - CopyResults(sig, out_results); - } - - // Always reset the value and call stacks. - value_stack_top_ = value_stack_.data(); - call_stack_top_ = call_stack_.data(); - return result; -} - -Result Thread::RunStartFunction(DefinedModule* module) { - if (module->start_func_index == kInvalidIndex) - return Result::Ok; - - if (trace_stream_) { - trace_stream_->Writef(">>> running start function:\n"); - } - TypedValues args; - TypedValues results; - Result result = RunFunction(module->start_func_index, args, &results); - assert(results.size() == 0); - return result; -} - -Result Thread::RunExport(const Export* export_, - const TypedValues& args, - TypedValues* out_results) { - if (trace_stream_) { - trace_stream_->Writef(">>> running export \"" PRIstringview "\":\n", - WABT_PRINTF_STRING_VIEW_ARG(export_->name)); - } - - assert(export_->kind == ExternalKind::Func); - return RunFunction(export_->index, args, out_results); -} - -Result Thread::RunExportByName(interp::Module* module, - string_view name, - const TypedValues& args, - TypedValues* out_results) { - interp::Export* export_ = module->GetExport(name); - if (!export_) - return interp::Result::UnknownExport; - if (export_->kind != ExternalKind::Func) - return interp::Result::ExportKindMismatch; - return RunExport(export_, args, out_results); -} - -Result Thread::RunDefinedFunction(IstreamOffset function_offset) { - Result result = Result::Ok; - pc_ = function_offset; - IstreamOffset* call_stack_return_top = call_stack_top_; - if (trace_stream_) { - const int kNumInstructions = 1; - while (result == Result::Ok) { - Trace(trace_stream_); - result = Run(kNumInstructions, call_stack_return_top); - } - } else { - const int kNumInstructions = 1000; - while (result == Result::Ok) { - result = Run(kNumInstructions, call_stack_return_top); - } - } - if (result != Result::Returned) - return result; - // Use OK instead of RETURNED for consistency. - return Result::Ok; -} - Result Thread::CallHost(HostFunc* func) { FuncSignature* sig = &env_->sigs_[func->sig_index]; @@ -1330,9 +1222,8 @@ Result Thread::CallHost(HostFunc* func) { return Result::Ok; } -Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { +Result Thread::Run(int num_instructions) { Result result = Result::Ok; - assert(call_stack_return_top < call_stack_end_); const uint8_t* istream = GetIstream(); const uint8_t* pc = &istream[pc_]; @@ -1376,7 +1267,7 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { } case Opcode::Return: - if (call_stack_top_ == call_stack_return_top) { + if (call_stack_top_ == 0) { result = Result::Returned; goto exit_loop; } @@ -2271,11 +2162,11 @@ Result Thread::Run(int num_instructions, IstreamOffset* call_stack_return_top) { break; case Opcode::InterpAlloca: { - Value* old_value_stack_top = value_stack_top_; - value_stack_top_ += ReadU32(&pc); + uint32_t old_value_stack_top = value_stack_top_; + size_t count = ReadU32(&pc); + value_stack_top_ += count; CHECK_STACK(); - memset(old_value_stack_top, 0, - (value_stack_top_ - old_value_stack_top) * sizeof(Value)); + memset(&value_stack_[old_value_stack_top], 0, count * sizeof(Value)); break; } @@ -2334,11 +2225,9 @@ exit_loop: void Thread::Trace(Stream* stream) { const uint8_t* istream = GetIstream(); const uint8_t* pc = &istream[pc_]; - size_t value_stack_depth = value_stack_top_ - value_stack_.data(); - size_t call_stack_depth = call_stack_top_ - call_stack_.data(); - stream->Writef("#%" PRIzd ". %4" PRIzd ": V:%-3" PRIzd "| ", call_stack_depth, - pc - istream, value_stack_depth); + stream->Writef("#%u. %4" PRIzd ": V:%-3u| ", call_stack_top_, pc - istream, + value_stack_top_); Opcode opcode = ReadOpcode(&pc); assert(!opcode.IsInvalid()); @@ -3200,5 +3089,109 @@ void Environment::DisassembleModule(Stream* stream, Module* module) { defined_module->istream_end); } +Executor::Executor(Environment* env, + Stream* trace_stream, + const Thread::Options& options) + : env_(env), trace_stream_(trace_stream), thread_(env, options) {} + +ExecResult Executor::RunFunction(Index func_index, const TypedValues& args) { + ExecResult exec_result; + Func* func = env_->GetFunc(func_index); + FuncSignature* sig = env_->GetFuncSignature(func->sig_index); + + exec_result.result = PushArgs(sig, args); + if (exec_result.result == Result::Ok) { + exec_result.result = func->is_host + ? thread_.CallHost(cast<HostFunc>(func)) + : RunDefinedFunction(cast<DefinedFunc>(func)->offset); + if (exec_result.result == Result::Ok) + CopyResults(sig, &exec_result.values); + } + + thread_.Reset(); + return exec_result; +} + +ExecResult Executor::RunStartFunction(DefinedModule* module) { + if (module->start_func_index == kInvalidIndex) + return ExecResult(Result::Ok); + + if (trace_stream_) { + trace_stream_->Writef(">>> running start function:\n"); + } + + TypedValues args; + ExecResult exec_result = RunFunction(module->start_func_index, args); + assert(exec_result.values.size() == 0); + return exec_result; +} + +ExecResult Executor::RunExport(const Export* export_, const TypedValues& args) { + if (trace_stream_) { + trace_stream_->Writef(">>> running export \"" PRIstringview "\":\n", + WABT_PRINTF_STRING_VIEW_ARG(export_->name)); + } + + assert(export_->kind == ExternalKind::Func); + return RunFunction(export_->index, args); +} + +ExecResult Executor::RunExportByName(Module* module, + string_view name, + const TypedValues& args) { + Export* export_ = module->GetExport(name); + if (!export_) + return ExecResult(Result::UnknownExport); + if (export_->kind != ExternalKind::Func) + return ExecResult(Result::ExportKindMismatch); + return RunExport(export_, args); +} + +Result Executor::RunDefinedFunction(IstreamOffset function_offset) { + Result result = Result::Ok; + thread_.set_pc(function_offset); + if (trace_stream_) { + const int kNumInstructions = 1; + while (result == Result::Ok) { + thread_.Trace(trace_stream_); + result = thread_.Run(kNumInstructions); + } + } else { + const int kNumInstructions = 1000; + while (result == Result::Ok) { + result = thread_.Run(kNumInstructions); + } + } + if (result != Result::Returned) + return result; + // Use OK instead of RETURNED for consistency. + return Result::Ok; +} + +Result Executor::PushArgs(const FuncSignature* sig, const TypedValues& args) { + if (sig->param_types.size() != args.size()) + return Result::ArgumentTypeMismatch; + + for (size_t i = 0; i < sig->param_types.size(); ++i) { + if (sig->param_types[i] != args[i].type) + return Result::ArgumentTypeMismatch; + + Result result = thread_.Push(args[i].value); + if (result != Result::Ok) { + return result; + } + } + return Result::Ok; +} + +void Executor::CopyResults(const FuncSignature* sig, TypedValues* out_results) { + size_t expected_results = sig->result_types.size(); + assert(expected_results == thread_.NumValues()); + + out_results->clear(); + for (size_t i = 0; i < expected_results; ++i) + out_results->emplace_back(sig->result_types[i], thread_.ValueAt(i)); +} + } // namespace interp } // namespace wabt |