2016-05-25 08:32:37 +00:00
|
|
|
// Copyright 2016 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef V8_WASM_INTERPRETER_H_
|
|
|
|
#define V8_WASM_INTERPRETER_H_
|
|
|
|
|
|
|
|
#include "src/wasm/wasm-opcodes.h"
|
2016-09-20 16:07:25 +00:00
|
|
|
#include "src/zone/zone-containers.h"
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace base {
|
|
|
|
class AccountingAllocator;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
namespace wasm {
|
|
|
|
|
|
|
|
// forward declarations.
|
2016-11-30 15:02:40 +00:00
|
|
|
struct ModuleBytesEnv;
|
2016-05-25 08:32:37 +00:00
|
|
|
struct WasmFunction;
|
|
|
|
class WasmInterpreterInternals;
|
|
|
|
|
|
|
|
typedef size_t pc_t;
|
|
|
|
typedef size_t sp_t;
|
|
|
|
typedef int32_t pcdiff_t;
|
|
|
|
typedef uint32_t spdiff_t;
|
|
|
|
|
2016-05-30 10:02:34 +00:00
|
|
|
const pc_t kInvalidPc = 0x80000000;
|
|
|
|
|
2016-09-27 20:46:10 +00:00
|
|
|
typedef ZoneMap<pc_t, pcdiff_t> ControlTransferMap;
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
// Macro for defining union members.
|
|
|
|
#define FOREACH_UNION_MEMBER(V) \
|
2016-12-21 13:43:00 +00:00
|
|
|
V(i32, kWasmI32, int32_t) \
|
|
|
|
V(u32, kWasmI32, uint32_t) \
|
|
|
|
V(i64, kWasmI64, int64_t) \
|
|
|
|
V(u64, kWasmI64, uint64_t) \
|
|
|
|
V(f32, kWasmF32, float) \
|
|
|
|
V(f64, kWasmF64, double)
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
// Representation of values within the interpreter.
|
|
|
|
struct WasmVal {
|
2016-12-21 13:43:00 +00:00
|
|
|
ValueType type;
|
2016-05-25 08:32:37 +00:00
|
|
|
union {
|
|
|
|
#define DECLARE_FIELD(field, localtype, ctype) ctype field;
|
|
|
|
FOREACH_UNION_MEMBER(DECLARE_FIELD)
|
|
|
|
#undef DECLARE_FIELD
|
|
|
|
} val;
|
|
|
|
|
2016-12-21 13:43:00 +00:00
|
|
|
WasmVal() : type(kWasmStmt) {}
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
#define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
|
|
|
|
explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
|
|
|
|
FOREACH_UNION_MEMBER(DECLARE_CONSTRUCTOR)
|
|
|
|
#undef DECLARE_CONSTRUCTOR
|
|
|
|
|
|
|
|
template <typename T>
|
2017-01-20 10:46:48 +00:00
|
|
|
inline T to() {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline T to_unchecked() {
|
2016-05-25 08:32:37 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define DECLARE_CAST(field, localtype, ctype) \
|
2017-01-20 10:46:48 +00:00
|
|
|
template <> \
|
|
|
|
inline ctype WasmVal::to_unchecked() { \
|
|
|
|
return val.field; \
|
|
|
|
} \
|
2016-05-25 08:32:37 +00:00
|
|
|
template <> \
|
|
|
|
inline ctype WasmVal::to() { \
|
|
|
|
CHECK_EQ(localtype, type); \
|
|
|
|
return val.field; \
|
|
|
|
}
|
|
|
|
FOREACH_UNION_MEMBER(DECLARE_CAST)
|
|
|
|
#undef DECLARE_CAST
|
|
|
|
|
|
|
|
// Representation of frames within the interpreter.
|
2017-01-20 12:58:14 +00:00
|
|
|
class InterpretedFrame {
|
2016-05-25 08:32:37 +00:00
|
|
|
public:
|
|
|
|
const WasmFunction* function() const { return function_; }
|
2017-01-20 12:58:14 +00:00
|
|
|
int pc() const { return pc_; }
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// Stack frame inspection.
|
|
|
|
//==========================================================================
|
|
|
|
int GetParameterCount() const;
|
|
|
|
WasmVal GetLocalVal(int index) const;
|
|
|
|
WasmVal GetExprVal(int pc) const;
|
|
|
|
void SetLocalVal(int index, WasmVal val);
|
|
|
|
void SetExprVal(int pc, WasmVal val);
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class WasmInterpreter;
|
|
|
|
|
2017-01-20 12:58:14 +00:00
|
|
|
InterpretedFrame(const WasmFunction* function, int pc, int fp, int sp)
|
2016-05-25 08:32:37 +00:00
|
|
|
: function_(function), pc_(pc), fp_(fp), sp_(sp) {}
|
|
|
|
|
|
|
|
const WasmFunction* function_;
|
|
|
|
int pc_;
|
|
|
|
int fp_;
|
|
|
|
int sp_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// An interpreter capable of executing WASM.
|
2016-09-26 07:40:24 +00:00
|
|
|
class V8_EXPORT_PRIVATE WasmInterpreter {
|
2016-05-25 08:32:37 +00:00
|
|
|
public:
|
|
|
|
// State machine for a Thread:
|
|
|
|
// +---------------Run()-----------+
|
|
|
|
// V |
|
|
|
|
// STOPPED ---Run()--> RUNNING ------Pause()-----+-> PAUSED <------+
|
|
|
|
// | | | / | |
|
|
|
|
// | | +---- Breakpoint ---+ +-- Step() --+
|
|
|
|
// | |
|
|
|
|
// | +------------ Trap --------------> TRAPPED
|
|
|
|
// +------------- Finish -------------> FINISHED
|
|
|
|
enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
|
|
|
|
|
2017-01-24 10:13:33 +00:00
|
|
|
// Tells a thread to pause after certain instructions.
|
|
|
|
enum BreakFlag : uint8_t {
|
|
|
|
None = 0,
|
|
|
|
AfterReturn = 1 << 0,
|
|
|
|
AfterCall = 1 << 1
|
|
|
|
};
|
|
|
|
|
2016-05-25 08:32:37 +00:00
|
|
|
// Representation of a thread in the interpreter.
|
2017-01-18 10:23:20 +00:00
|
|
|
class V8_EXPORT_PRIVATE Thread {
|
2017-01-18 11:40:29 +00:00
|
|
|
// Don't instante Threads; they will be allocated as ThreadImpl in the
|
|
|
|
// interpreter implementation.
|
|
|
|
Thread() = delete;
|
2017-01-18 10:23:20 +00:00
|
|
|
|
2016-05-25 08:32:37 +00:00
|
|
|
public:
|
|
|
|
// Execution control.
|
2017-01-18 10:23:20 +00:00
|
|
|
State state();
|
2017-03-14 15:54:43 +00:00
|
|
|
void InitFrame(const WasmFunction* function, WasmVal* args);
|
2017-01-18 10:23:20 +00:00
|
|
|
State Run();
|
|
|
|
State Step();
|
|
|
|
void Pause();
|
|
|
|
void Reset();
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
// Stack inspection and modification.
|
2017-01-18 10:23:20 +00:00
|
|
|
pc_t GetBreakpointPc();
|
|
|
|
int GetFrameCount();
|
2017-01-20 12:58:14 +00:00
|
|
|
const InterpretedFrame GetFrame(int index);
|
|
|
|
InterpretedFrame GetMutableFrame(int index);
|
2017-01-18 10:23:20 +00:00
|
|
|
WasmVal GetReturnValue(int index = 0);
|
2017-03-16 11:54:31 +00:00
|
|
|
TrapReason GetTrapReason();
|
2017-02-21 18:21:31 +00:00
|
|
|
|
2016-10-20 14:27:23 +00:00
|
|
|
// 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.
|
2017-01-18 10:23:20 +00:00
|
|
|
bool PossibleNondeterminism();
|
2016-05-25 08:32:37 +00:00
|
|
|
|
2017-02-21 18:21:31 +00:00
|
|
|
// Returns the number of calls / function frames executed on this thread.
|
|
|
|
uint64_t NumInterpretedCalls();
|
|
|
|
|
2016-05-25 08:32:37 +00:00
|
|
|
// Thread-specific breakpoints.
|
2017-01-18 10:23:20 +00:00
|
|
|
// TODO(wasm): Implement this once we support multiple threads.
|
|
|
|
// bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
|
|
|
|
// bool GetBreakpoint(const WasmFunction* function, int pc);
|
2017-01-24 10:13:33 +00:00
|
|
|
|
|
|
|
void AddBreakFlags(uint8_t flags);
|
|
|
|
void ClearBreakFlags();
|
2016-05-25 08:32:37 +00:00
|
|
|
};
|
|
|
|
|
2016-11-30 15:02:40 +00:00
|
|
|
WasmInterpreter(const ModuleBytesEnv& env, AccountingAllocator* allocator);
|
2016-05-25 08:32:37 +00:00
|
|
|
~WasmInterpreter();
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// Execution controls.
|
|
|
|
//==========================================================================
|
|
|
|
void Run();
|
|
|
|
void Pause();
|
|
|
|
|
|
|
|
// Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
|
|
|
|
// previous state of the breakpoint at {pc}.
|
2016-05-30 10:02:34 +00:00
|
|
|
bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
// Gets the current state of the breakpoint at {function}.
|
2016-05-30 10:02:34 +00:00
|
|
|
bool GetBreakpoint(const WasmFunction* function, pc_t pc);
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
// Enable or disable tracing for {function}. Return the previous state.
|
|
|
|
bool SetTracing(const WasmFunction* function, bool enabled);
|
|
|
|
|
2017-03-15 15:57:02 +00:00
|
|
|
// Add an imported function.
|
|
|
|
// We store the passed Handle internally, so the caller must ensure that it
|
|
|
|
// stays valid at least as long as the WasmInterpreter.
|
|
|
|
void AddImportedFunction(Handle<HeapObject>);
|
|
|
|
|
2016-05-25 08:32:37 +00:00
|
|
|
//==========================================================================
|
|
|
|
// Thread iteration and inspection.
|
|
|
|
//==========================================================================
|
|
|
|
int GetThreadCount();
|
2016-06-09 14:22:05 +00:00
|
|
|
Thread* GetThread(int id);
|
2016-05-25 08:32:37 +00:00
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// Memory access.
|
|
|
|
//==========================================================================
|
|
|
|
size_t GetMemorySize();
|
|
|
|
WasmVal ReadMemory(size_t offset);
|
|
|
|
void WriteMemory(size_t offset, WasmVal val);
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
// Testing functionality.
|
|
|
|
//==========================================================================
|
2017-03-14 15:54:43 +00:00
|
|
|
// Manually adds a function to this interpreter. The func_index of the
|
|
|
|
// function must match the current number of functions.
|
|
|
|
void AddFunctionForTesting(const WasmFunction* function);
|
2016-05-25 08:32:37 +00:00
|
|
|
// Manually adds code to the interpreter for the given function.
|
2017-03-14 15:54:43 +00:00
|
|
|
void SetFunctionCodeForTesting(const WasmFunction* function,
|
2016-05-25 08:32:37 +00:00
|
|
|
const byte* start, const byte* end);
|
|
|
|
|
2016-09-27 20:46:10 +00:00
|
|
|
// Computes the control transfers for the given bytecode. Used internally in
|
|
|
|
// the interpreter, but exposed for testing.
|
2016-05-25 08:32:37 +00:00
|
|
|
static ControlTransferMap ComputeControlTransfersForTesting(Zone* zone,
|
|
|
|
const byte* start,
|
|
|
|
const byte* end);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Zone zone_;
|
|
|
|
WasmInterpreterInternals* internals_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace wasm
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_WASM_INTERPRETER_H_
|