Commit 47e501e1 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][interpreter] Remove threads support

The wasm interpreter was always single-threaded, and there are no plans
to change this. Still, there was a concept of threads, but with the
hard-coded constraint that there is always exactly one of them.

In order to clean up the code, and as a preparation to remove more
unneeded functionality before moving the interpreter over to the test
directory, this CL removes the concept of threads and merges the
{ThreadImpl} class into {WasmInterpreterInternals}.

Drive-by: Remove the dead {GetFrameCount} method.

R=ahaas@chromium.org

Bug: v8:10389
Change-Id: If65cdd21b34ce8debf8ba0f24dbeacec15e0a1d7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2231354Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68204}
parent b644fac5
......@@ -191,13 +191,12 @@ class InterpreterHandle {
DCHECK_EQ(sig->return_count(), return_values.size());
WasmCodeRefScope code_ref_scope;
WasmInterpreter::Thread* thread = interpreter_.GetThread(0);
thread->InitFrame(&module()->functions[func_index],
argument_values.begin());
interpreter_.InitFrame(&module()->functions[func_index],
argument_values.begin());
bool finished = false;
while (!finished) {
// TODO(clemensb): Add occasional StackChecks.
WasmInterpreter::State state = thread->Run();
WasmInterpreter::State state = interpreter_.Run();
switch (state) {
case WasmInterpreter::State::PAUSED:
UNREACHABLE();
......@@ -207,16 +206,16 @@ class InterpreterHandle {
break;
case WasmInterpreter::State::TRAPPED: {
MessageTemplate message_id =
WasmOpcodes::TrapReasonToMessageId(thread->GetTrapReason());
WasmOpcodes::TrapReasonToMessageId(interpreter_.GetTrapReason());
Handle<JSObject> exception =
isolate_->factory()->NewWasmRuntimeError(message_id);
JSObject::AddProperty(isolate_, exception,
isolate_->factory()->wasm_uncatchable_symbol(),
isolate_->factory()->true_value(), NONE);
auto result = thread->RaiseException(isolate_, exception);
if (result == WasmInterpreter::Thread::HANDLED) break;
auto result = interpreter_.RaiseException(isolate_, exception);
if (result == WasmInterpreter::HANDLED) break;
// If no local handler was found, we fall-thru to {STOPPED}.
DCHECK_EQ(WasmInterpreter::State::STOPPED, thread->state());
DCHECK_EQ(WasmInterpreter::State::STOPPED, interpreter_.state());
V8_FALLTHROUGH;
}
case WasmInterpreter::State::STOPPED:
......@@ -239,7 +238,7 @@ class InterpreterHandle {
#endif
DCHECK_GE(max_count, sig->return_count());
for (unsigned i = 0; i < sig->return_count(); ++i) {
return_values[i] = thread->GetReturnValue(i);
return_values[i] = interpreter_.GetReturnValue(i);
}
return true;
......
This diff is collapsed.
......@@ -44,7 +44,7 @@ using ControlTransferMap = ZoneMap<pc_t, ControlTransferEntry>;
// An interpreter capable of executing WebAssembly.
class V8_EXPORT_PRIVATE WasmInterpreter {
public:
// State machine for a Thread:
// State machine for the interpreter:
// +----------------------------------------------------------+
// | +--------Run()/Step()---------+ |
// V V | |
......@@ -56,49 +56,7 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
// +----------- Finish -------------> FINISHED
enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
// Tells a thread to pause after certain instructions.
enum BreakFlag : uint8_t {
None = 0,
AfterReturn = 1 << 0,
AfterCall = 1 << 1
};
// Representation of a thread in the interpreter.
class V8_EXPORT_PRIVATE Thread {
public:
// Don't instante Threads; they will be allocated as ThreadImpl in the
// interpreter implementation.
Thread() = delete;
enum ExceptionHandlingResult { HANDLED, UNWOUND };
// Execution control.
State state();
void InitFrame(const WasmFunction* function, WasmValue* args);
// Pass -1 as num_steps to run till completion, pause or breakpoint.
State Run(int num_steps = -1);
State Step() { return Run(1); }
void Pause();
void Reset();
// Raise an exception in the current activation and unwind the stack
// accordingly. Return whether the exception was handled inside wasm:
// - HANDLED: Activation at handler position and in {PAUSED} state.
// - UNWOUND: Frames unwound, exception pending, and in {STOPPED} state.
ExceptionHandlingResult RaiseException(Isolate*, Handle<Object> exception);
// Stack inspection and modification.
int GetFrameCount();
WasmValue GetReturnValue(int index = 0);
TrapReason GetTrapReason();
// Returns true if the thread executed an instruction which may produce
// nondeterministic results, e.g. float div, float sqrt, and float mul,
// where the sign bit of a NaN is nondeterministic.
bool PossibleNondeterminism();
// Returns the number of calls / function frames executed on this thread.
uint64_t NumInterpretedCalls();
};
enum ExceptionHandlingResult { HANDLED, UNWOUND };
WasmInterpreter(Isolate* isolate, const WasmModule* module,
const ModuleWireBytes& wire_bytes,
......@@ -109,14 +67,31 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
//==========================================================================
// Execution controls.
//==========================================================================
void Run();
State state();
void InitFrame(const WasmFunction* function, WasmValue* args);
// Pass -1 as num_steps to run till completion, pause or breakpoint.
State Run(int num_steps = -1);
State Step() { return Run(1); }
void Pause();
void Reset();
//==========================================================================
// Thread iteration and inspection.
//==========================================================================
int GetThreadCount();
Thread* GetThread(int id);
// Raise an exception in the current activation and unwind the stack
// accordingly. Return whether the exception was handled inside wasm:
// - HANDLED: Activation at handler position and in {PAUSED} state.
// - UNWOUND: Frames unwound, exception pending, and in {STOPPED} state.
ExceptionHandlingResult RaiseException(Isolate*, Handle<Object> exception);
// Stack inspection and modification.
WasmValue GetReturnValue(int index = 0);
TrapReason GetTrapReason();
// Returns true if the thread executed an instruction which may produce
// nondeterministic results, e.g. float div, float sqrt, and float mul,
// where the sign bit of a NaN is nondeterministic.
bool PossibleNondeterminism();
// Returns the number of calls / function frames executed on this thread.
uint64_t NumInterpretedCalls();
//==========================================================================
// Testing functionality.
......
......@@ -282,28 +282,27 @@ TEST(Step_I32Mul) {
r.Build(code, code + arraysize(code));
WasmInterpreter* interpreter = r.interpreter();
WasmInterpreter::Thread* thread = interpreter->GetThread(0);
FOR_UINT32_INPUTS(a) {
for (uint32_t b = 33; b < 3000000000u; b += 1000000000u) {
thread->Reset();
interpreter->Reset();
WasmValue args[] = {WasmValue(a), WasmValue(b)};
thread->InitFrame(r.function(), args);
interpreter->InitFrame(r.function(), args);
// Run instructions one by one.
for (int i = 0; i < kTraceLength - 1; i++) {
thread->Step();
// Check the thread stopped.
CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
interpreter->Step();
// Check the interpreter stopped.
CHECK_EQ(WasmInterpreter::PAUSED, interpreter->state());
}
// Run last instruction.
thread->Step();
interpreter->Step();
// Check the thread finished with the right value.
CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
// Check the interpreter finished with the right value.
CHECK_EQ(WasmInterpreter::FINISHED, interpreter->state());
uint32_t expected = (a) * (b);
CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
CHECK_EQ(expected, interpreter->GetReturnValue().to<uint32_t>());
}
}
}
......
......@@ -510,17 +510,16 @@ class WasmRunner : public WasmRunnerBase {
}
ReturnType CallInterpreter(ParamTypes... p) {
WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
thread->Reset();
interpreter()->Reset();
std::array<WasmValue, sizeof...(p)> args{{WasmValue(p)...}};
thread->InitFrame(function(), args.data());
thread->Run();
CHECK_GT(thread->NumInterpretedCalls(), 0);
if (thread->state() == WasmInterpreter::FINISHED) {
WasmValue val = thread->GetReturnValue();
possible_nondeterminism_ |= thread->PossibleNondeterminism();
interpreter()->InitFrame(function(), args.data());
interpreter()->Run();
CHECK_GT(interpreter()->NumInterpretedCalls(), 0);
if (interpreter()->state() == WasmInterpreter::FINISHED) {
WasmValue val = interpreter()->GetReturnValue();
possible_nondeterminism_ |= interpreter()->PossibleNondeterminism();
return val.to<ReturnType>();
} else if (thread->state() == WasmInterpreter::TRAPPED) {
} else if (interpreter()->state() == WasmInterpreter::TRAPPED) {
// TODO(titzer): return the correct trap code
int64_t result = 0xDEADBEEFDEADBEEF;
return static_cast<ReturnType>(result);
......@@ -559,7 +558,7 @@ class WasmRunner : public WasmRunnerBase {
}
if (builder_.interpret()) {
CHECK_GT(builder_.interpreter()->GetThread(0)->NumInterpretedCalls(), 0);
CHECK_GT(builder_.interpreter()->NumInterpretedCalls(), 0);
}
}
......
......@@ -127,12 +127,11 @@ bool InterpretWasmModuleForTesting(Isolate* isolate,
Zone zone(isolate->allocator(), ZONE_NAME);
WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
WasmInterpreter::Thread* thread = interpreter->GetThread(0);
thread->Reset();
interpreter->Reset();
thread->InitFrame(&instance->module()->functions[function_index],
arguments.get());
WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
interpreter->InitFrame(&instance->module()->functions[function_index],
arguments.get());
WasmInterpreter::State interpreter_result = interpreter->Run(kMaxNumSteps);
if (isolate->has_pending_exception()) {
// Stack overflow during interpretation.
......@@ -199,25 +198,25 @@ WasmInterpretationResult InterpretWasmModule(
v8::internal::HandleScope scope(isolate);
WasmInterpreter* interpreter = WasmDebugInfo::SetupForTesting(instance);
WasmInterpreter::Thread* thread = interpreter->GetThread(0);
thread->Reset();
interpreter->Reset();
thread->InitFrame(&(instance->module()->functions[function_index]), args);
WasmInterpreter::State interpreter_result = thread->Run(kMaxNumSteps);
interpreter->InitFrame(&instance->module()->functions[function_index], args);
WasmInterpreter::State interpreter_result = interpreter->Run(kMaxNumSteps);
bool stack_overflow = isolate->has_pending_exception();
isolate->clear_pending_exception();
if (stack_overflow) return WasmInterpretationResult::Stopped();
if (thread->state() == WasmInterpreter::TRAPPED) {
return WasmInterpretationResult::Trapped(thread->PossibleNondeterminism());
if (interpreter->state() == WasmInterpreter::TRAPPED) {
return WasmInterpretationResult::Trapped(
interpreter->PossibleNondeterminism());
}
if (interpreter_result == WasmInterpreter::FINISHED) {
return WasmInterpretationResult::Finished(
thread->GetReturnValue().to<int32_t>(),
thread->PossibleNondeterminism());
interpreter->GetReturnValue().to<int32_t>(),
interpreter->PossibleNondeterminism());
}
return WasmInterpretationResult::Stopped();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment