| // 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" |
| #include "src/zone/zone-containers.h" |
| |
| namespace v8 { |
| namespace base { |
| class AccountingAllocator; |
| } |
| |
| namespace internal { |
| namespace wasm { |
| |
| // forward declarations. |
| struct ModuleBytesEnv; |
| struct WasmFunction; |
| class WasmInterpreterInternals; |
| |
| typedef size_t pc_t; |
| typedef size_t sp_t; |
| typedef int32_t pcdiff_t; |
| typedef uint32_t spdiff_t; |
| |
| const pc_t kInvalidPc = 0x80000000; |
| |
| typedef ZoneMap<pc_t, pcdiff_t> ControlTransferMap; |
| |
| // Macro for defining union members. |
| #define FOREACH_UNION_MEMBER(V) \ |
| 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) |
| |
| // Representation of values within the interpreter. |
| struct WasmVal { |
| ValueType type; |
| union { |
| #define DECLARE_FIELD(field, localtype, ctype) ctype field; |
| FOREACH_UNION_MEMBER(DECLARE_FIELD) |
| #undef DECLARE_FIELD |
| } val; |
| |
| WasmVal() : type(kWasmStmt) {} |
| |
| #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> |
| inline T to() { |
| UNREACHABLE(); |
| } |
| |
| template <typename T> |
| inline T to_unchecked() { |
| UNREACHABLE(); |
| } |
| }; |
| |
| #define DECLARE_CAST(field, localtype, ctype) \ |
| template <> \ |
| inline ctype WasmVal::to_unchecked() { \ |
| return val.field; \ |
| } \ |
| 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. |
| class InterpretedFrame { |
| public: |
| const WasmFunction* function() const { return function_; } |
| 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); |
| |
| private: |
| friend class WasmInterpreter; |
| |
| InterpretedFrame(const WasmFunction* function, int pc, int fp, int sp) |
| : function_(function), pc_(pc), fp_(fp), sp_(sp) {} |
| |
| const WasmFunction* function_; |
| int pc_; |
| int fp_; |
| int sp_; |
| }; |
| |
| // An interpreter capable of executing WASM. |
| class V8_EXPORT_PRIVATE WasmInterpreter { |
| 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 }; |
| |
| // 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 { |
| // Don't instante Threads; they will be allocated as ThreadImpl in the |
| // interpreter implementation. |
| Thread() = delete; |
| |
| public: |
| // Execution control. |
| State state(); |
| void PushFrame(const WasmFunction* function, WasmVal* args); |
| State Run(); |
| State Step(); |
| void Pause(); |
| void Reset(); |
| |
| // Stack inspection and modification. |
| pc_t GetBreakpointPc(); |
| int GetFrameCount(); |
| const InterpretedFrame GetFrame(int index); |
| InterpretedFrame GetMutableFrame(int index); |
| WasmVal GetReturnValue(int index = 0); |
| // 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(); |
| |
| // Thread-specific breakpoints. |
| // 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); |
| |
| void AddBreakFlags(uint8_t flags); |
| void ClearBreakFlags(); |
| }; |
| |
| WasmInterpreter(const ModuleBytesEnv& env, AccountingAllocator* allocator); |
| ~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}. |
| bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled); |
| |
| // Gets the current state of the breakpoint at {function}. |
| bool GetBreakpoint(const WasmFunction* function, pc_t pc); |
| |
| // Enable or disable tracing for {function}. Return the previous state. |
| bool SetTracing(const WasmFunction* function, bool enabled); |
| |
| //========================================================================== |
| // Thread iteration and inspection. |
| //========================================================================== |
| int GetThreadCount(); |
| Thread* GetThread(int id); |
| |
| //========================================================================== |
| // Memory access. |
| //========================================================================== |
| size_t GetMemorySize(); |
| WasmVal ReadMemory(size_t offset); |
| void WriteMemory(size_t offset, WasmVal val); |
| |
| //========================================================================== |
| // Testing functionality. |
| //========================================================================== |
| // Manually adds a function to this interpreter, returning the index of the |
| // function. |
| int AddFunctionForTesting(const WasmFunction* function); |
| // Manually adds code to the interpreter for the given function. |
| bool SetFunctionCodeForTesting(const WasmFunction* function, |
| const byte* start, const byte* end); |
| |
| // Computes the control transfers for the given bytecode. Used internally in |
| // the interpreter, but exposed for testing. |
| 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_ |