• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ModuleBytesEnv;
21 struct WasmFunction;
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, kWasmI32, int32_t)     \
36   V(u32, kWasmI32, uint32_t)    \
37   V(i64, kWasmI64, int64_t)     \
38   V(u64, kWasmI64, uint64_t)    \
39   V(f32, kWasmF32, float)       \
40   V(f64, kWasmF64, double)
41 
42 // Representation of values within the interpreter.
43 struct WasmVal {
44   ValueType 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(kWasmStmt) {}
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   inline T to() {
60     UNREACHABLE();
61   }
62 
63   template <typename T>
to_uncheckedWasmVal64   inline T to_unchecked() {
65     UNREACHABLE();
66   }
67 };
68 
69 #define DECLARE_CAST(field, localtype, ctype) \
70   template <>                                 \
71   inline ctype WasmVal::to_unchecked() {      \
72     return val.field;                         \
73   }                                           \
74   template <>                                 \
75   inline ctype WasmVal::to() {                \
76     CHECK_EQ(localtype, type);                \
77     return val.field;                         \
78   }
FOREACH_UNION_MEMBER(DECLARE_CAST)79 FOREACH_UNION_MEMBER(DECLARE_CAST)
80 #undef DECLARE_CAST
81 
82 // Representation of frames within the interpreter.
83 class InterpretedFrame {
84  public:
85   const WasmFunction* function() const { return function_; }
86   int pc() const { return pc_; }
87 
88   //==========================================================================
89   // Stack frame inspection.
90   //==========================================================================
91   int GetParameterCount() const;
92   WasmVal GetLocalVal(int index) const;
93   WasmVal GetExprVal(int pc) const;
94   void SetLocalVal(int index, WasmVal val);
95   void SetExprVal(int pc, WasmVal val);
96 
97  private:
98   friend class WasmInterpreter;
99 
100   InterpretedFrame(const WasmFunction* function, int pc, int fp, int sp)
101       : function_(function), pc_(pc), fp_(fp), sp_(sp) {}
102 
103   const WasmFunction* function_;
104   int pc_;
105   int fp_;
106   int sp_;
107 };
108 
109 // An interpreter capable of executing WASM.
110 class V8_EXPORT_PRIVATE WasmInterpreter {
111  public:
112   // State machine for a Thread:
113   //                       +---------------Run()-----------+
114   //                       V                               |
115   // STOPPED ---Run()-->  RUNNING  ------Pause()-----+-> PAUSED  <------+
116   //                       | | |                    /      |            |
117   //                       | | +---- Breakpoint ---+       +-- Step() --+
118   //                       | |
119   //                       | +------------ Trap --------------> TRAPPED
120   //                       +------------- Finish -------------> FINISHED
121   enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
122 
123   // Tells a thread to pause after certain instructions.
124   enum BreakFlag : uint8_t {
125     None = 0,
126     AfterReturn = 1 << 0,
127     AfterCall = 1 << 1
128   };
129 
130   // Representation of a thread in the interpreter.
131   class V8_EXPORT_PRIVATE Thread {
132     // Don't instante Threads; they will be allocated as ThreadImpl in the
133     // interpreter implementation.
134     Thread() = delete;
135 
136    public:
137     // Execution control.
138     State state();
139     void PushFrame(const WasmFunction* function, WasmVal* args);
140     State Run();
141     State Step();
142     void Pause();
143     void Reset();
144 
145     // Stack inspection and modification.
146     pc_t GetBreakpointPc();
147     int GetFrameCount();
148     const InterpretedFrame GetFrame(int index);
149     InterpretedFrame GetMutableFrame(int index);
150     WasmVal GetReturnValue(int index = 0);
151 
152     // Returns true if the thread executed an instruction which may produce
153     // nondeterministic results, e.g. float div, float sqrt, and float mul,
154     // where the sign bit of a NaN is nondeterministic.
155     bool PossibleNondeterminism();
156 
157     // Returns the number of calls / function frames executed on this thread.
158     uint64_t NumInterpretedCalls();
159 
160     // Thread-specific breakpoints.
161     // TODO(wasm): Implement this once we support multiple threads.
162     // bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
163     // bool GetBreakpoint(const WasmFunction* function, int pc);
164 
165     void AddBreakFlags(uint8_t flags);
166     void ClearBreakFlags();
167   };
168 
169   WasmInterpreter(const ModuleBytesEnv& env, AccountingAllocator* allocator);
170   ~WasmInterpreter();
171 
172   //==========================================================================
173   // Execution controls.
174   //==========================================================================
175   void Run();
176   void Pause();
177 
178   // Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
179   // previous state of the breakpoint at {pc}.
180   bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
181 
182   // Gets the current state of the breakpoint at {function}.
183   bool GetBreakpoint(const WasmFunction* function, pc_t pc);
184 
185   // Enable or disable tracing for {function}. Return the previous state.
186   bool SetTracing(const WasmFunction* function, bool enabled);
187 
188   //==========================================================================
189   // Thread iteration and inspection.
190   //==========================================================================
191   int GetThreadCount();
192   Thread* GetThread(int id);
193 
194   //==========================================================================
195   // Memory access.
196   //==========================================================================
197   size_t GetMemorySize();
198   WasmVal ReadMemory(size_t offset);
199   void WriteMemory(size_t offset, WasmVal val);
200 
201   //==========================================================================
202   // Testing functionality.
203   //==========================================================================
204   // Manually adds a function to this interpreter, returning the index of the
205   // function.
206   int AddFunctionForTesting(const WasmFunction* function);
207   // Manually adds code to the interpreter for the given function.
208   bool SetFunctionCodeForTesting(const WasmFunction* function,
209                                  const byte* start, const byte* end);
210 
211   // Computes the control transfers for the given bytecode. Used internally in
212   // the interpreter, but exposed for testing.
213   static ControlTransferMap ComputeControlTransfersForTesting(Zone* zone,
214                                                               const byte* start,
215                                                               const byte* end);
216 
217  private:
218   Zone zone_;
219   WasmInterpreterInternals* internals_;
220 };
221 
222 }  // namespace wasm
223 }  // namespace internal
224 }  // namespace v8
225 
226 #endif  // V8_WASM_INTERPRETER_H_
227