1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_INTERPRETER_H_
6 #define V8_WASM_INTERPRETER_H_
7 
8 #include "src/wasm/wasm-opcodes.h"
9 #include "src/zone/zone-containers.h"
10 
11 namespace v8 {
12 namespace base {
13 class AccountingAllocator;
14 }
15 
16 namespace internal {
17 namespace wasm {
18 
19 // forward declarations.
20 struct WasmFunction;
21 struct WasmInstance;
22 class WasmInterpreterInternals;
23 
24 typedef size_t pc_t;
25 typedef size_t sp_t;
26 typedef int32_t pcdiff_t;
27 typedef uint32_t spdiff_t;
28 
29 const pc_t kInvalidPc = 0x80000000;
30 
31 typedef ZoneMap<pc_t, pcdiff_t> ControlTransferMap;
32 
33 // Macro for defining union members.
34 #define FOREACH_UNION_MEMBER(V) \
35   V(i32, kAstI32, int32_t)      \
36   V(u32, kAstI32, uint32_t)     \
37   V(i64, kAstI64, int64_t)      \
38   V(u64, kAstI64, uint64_t)     \
39   V(f32, kAstF32, float)        \
40   V(f64, kAstF64, double)
41 
42 // Representation of values within the interpreter.
43 struct WasmVal {
44   LocalType type;
45   union {
46 #define DECLARE_FIELD(field, localtype, ctype) ctype field;
47     FOREACH_UNION_MEMBER(DECLARE_FIELD)
48 #undef DECLARE_FIELD
49   } val;
50 
WasmValWasmVal51   WasmVal() : type(kAstStmt) {}
52 
53 #define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
54   explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
FOREACH_UNION_MEMBERWasmVal55   FOREACH_UNION_MEMBER(DECLARE_CONSTRUCTOR)
56 #undef DECLARE_CONSTRUCTOR
57 
58   template <typename T>
59   T to() {
60     UNREACHABLE();
61   }
62 };
63 
64 #define DECLARE_CAST(field, localtype, ctype) \
65   template <>                                 \
66   inline ctype WasmVal::to() {                \
67     CHECK_EQ(localtype, type);                \
68     return val.field;                         \
69   }
FOREACH_UNION_MEMBER(DECLARE_CAST)70 FOREACH_UNION_MEMBER(DECLARE_CAST)
71 #undef DECLARE_CAST
72 
73 template <>
74 inline void WasmVal::to() {
75   CHECK_EQ(kAstStmt, type);
76 }
77 
78 // Representation of frames within the interpreter.
79 class WasmFrame {
80  public:
function()81   const WasmFunction* function() const { return function_; }
pc()82   int pc() const { return pc_; }
83 
84  private:
85   friend class WasmInterpreter;
86 
WasmFrame(const WasmFunction * function,int pc,int fp,int sp)87   WasmFrame(const WasmFunction* function, int pc, int fp, int sp)
88       : function_(function), pc_(pc), fp_(fp), sp_(sp) {}
89 
90   const WasmFunction* function_;
91   int pc_;
92   int fp_;
93   int sp_;
94 };
95 
96 // An interpreter capable of executing WASM.
97 class V8_EXPORT_PRIVATE WasmInterpreter {
98  public:
99   // State machine for a Thread:
100   //                       +---------------Run()-----------+
101   //                       V                               |
102   // STOPPED ---Run()-->  RUNNING  ------Pause()-----+-> PAUSED  <------+
103   //                       | | |                    /      |            |
104   //                       | | +---- Breakpoint ---+       +-- Step() --+
105   //                       | |
106   //                       | +------------ Trap --------------> TRAPPED
107   //                       +------------- Finish -------------> FINISHED
108   enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
109 
110   // Representation of a thread in the interpreter.
111   class Thread {
112    public:
113     // Execution control.
114     virtual State state() = 0;
115     virtual void PushFrame(const WasmFunction* function, WasmVal* args) = 0;
116     virtual State Run() = 0;
117     virtual State Step() = 0;
118     virtual void Pause() = 0;
119     virtual void Reset() = 0;
~Thread()120     virtual ~Thread() {}
121 
122     // Stack inspection and modification.
123     virtual pc_t GetBreakpointPc() = 0;
124     virtual int GetFrameCount() = 0;
125     virtual const WasmFrame* GetFrame(int index) = 0;
126     virtual WasmFrame* GetMutableFrame(int index) = 0;
127     virtual WasmVal GetReturnValue(int index = 0) = 0;
128     // Returns true if the thread executed an instruction which may produce
129     // nondeterministic results, e.g. float div, float sqrt, and float mul,
130     // where the sign bit of a NaN is nondeterministic.
131     virtual bool PossibleNondeterminism() = 0;
132 
133     // Thread-specific breakpoints.
134     bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
135     bool GetBreakpoint(const WasmFunction* function, int pc);
136   };
137 
138   WasmInterpreter(WasmInstance* instance, AccountingAllocator* allocator);
139   ~WasmInterpreter();
140 
141   //==========================================================================
142   // Execution controls.
143   //==========================================================================
144   void Run();
145   void Pause();
146 
147   // Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
148   // previous state of the breakpoint at {pc}.
149   bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
150 
151   // Gets the current state of the breakpoint at {function}.
152   bool GetBreakpoint(const WasmFunction* function, pc_t pc);
153 
154   // Enable or disable tracing for {function}. Return the previous state.
155   bool SetTracing(const WasmFunction* function, bool enabled);
156 
157   //==========================================================================
158   // Thread iteration and inspection.
159   //==========================================================================
160   int GetThreadCount();
161   Thread* GetThread(int id);
162 
163   //==========================================================================
164   // Stack frame inspection.
165   //==========================================================================
166   WasmVal GetLocalVal(const WasmFrame* frame, int index);
167   WasmVal GetExprVal(const WasmFrame* frame, int pc);
168   void SetLocalVal(WasmFrame* frame, int index, WasmVal val);
169   void SetExprVal(WasmFrame* frame, int pc, WasmVal val);
170 
171   //==========================================================================
172   // Memory access.
173   //==========================================================================
174   size_t GetMemorySize();
175   WasmVal ReadMemory(size_t offset);
176   void WriteMemory(size_t offset, WasmVal val);
177 
178   //==========================================================================
179   // Testing functionality.
180   //==========================================================================
181   // Manually adds a function to this interpreter, returning the index of the
182   // function.
183   int AddFunctionForTesting(const WasmFunction* function);
184   // Manually adds code to the interpreter for the given function.
185   bool SetFunctionCodeForTesting(const WasmFunction* function,
186                                  const byte* start, const byte* end);
187 
188   // Computes the control transfers for the given bytecode. Used internally in
189   // the interpreter, but exposed for testing.
190   static ControlTransferMap ComputeControlTransfersForTesting(Zone* zone,
191                                                               const byte* start,
192                                                               const byte* end);
193 
194  private:
195   Zone zone_;
196   WasmInterpreterInternals* internals_;
197 };
198 
199 }  // namespace wasm
200 }  // namespace internal
201 }  // namespace v8
202 
203 #endif  // V8_WASM_INTERPRETER_H_
204