blob: b106a202d218fb153dea168b1ef8f91bb748da19 [file] [log] [blame]
Ben Murdoch61f157c2016-09-16 13:49:30 +01001// 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-containers.h"
10
11namespace v8 {
12namespace base {
13class AccountingAllocator;
14}
15
16namespace internal {
17namespace wasm {
18
19// forward declarations.
20struct WasmFunction;
21struct WasmModuleInstance;
22class WasmInterpreterInternals;
23
24typedef size_t pc_t;
25typedef size_t sp_t;
26typedef int32_t pcdiff_t;
27typedef uint32_t spdiff_t;
28
29const pc_t kInvalidPc = 0x80000000;
30
31// Visible for testing. A {ControlTransfer} helps the interpreter figure out
32// the target program counter and stack manipulations for a branch.
33struct ControlTransfer {
34 enum StackAction { kNoAction, kPopAndRepush, kPushVoid };
35 pcdiff_t pcdiff; // adjustment to the program counter (positive or negative).
36 spdiff_t spdiff; // number of elements to pop off the stack.
37 StackAction action; // action to perform on the stack.
38};
39typedef ZoneMap<pc_t, ControlTransfer> ControlTransferMap;
40
41// Macro for defining union members.
42#define FOREACH_UNION_MEMBER(V) \
43 V(i32, kAstI32, int32_t) \
44 V(u32, kAstI32, uint32_t) \
45 V(i64, kAstI64, int64_t) \
46 V(u64, kAstI64, uint64_t) \
47 V(f32, kAstF32, float) \
48 V(f64, kAstF64, double)
49
50// Representation of values within the interpreter.
51struct WasmVal {
52 LocalType type;
53 union {
54#define DECLARE_FIELD(field, localtype, ctype) ctype field;
55 FOREACH_UNION_MEMBER(DECLARE_FIELD)
56#undef DECLARE_FIELD
57 } val;
58
59 WasmVal() : type(kAstStmt) {}
60
61#define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
62 explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
63 FOREACH_UNION_MEMBER(DECLARE_CONSTRUCTOR)
64#undef DECLARE_CONSTRUCTOR
65
66 template <typename T>
67 T to() {
68 UNREACHABLE();
69 }
70};
71
72#define DECLARE_CAST(field, localtype, ctype) \
73 template <> \
74 inline ctype WasmVal::to() { \
75 CHECK_EQ(localtype, type); \
76 return val.field; \
77 }
78FOREACH_UNION_MEMBER(DECLARE_CAST)
79#undef DECLARE_CAST
80
81template <>
82inline void WasmVal::to() {
83 CHECK_EQ(kAstStmt, type);
84}
85
86// Representation of frames within the interpreter.
87class WasmFrame {
88 public:
89 const WasmFunction* function() const { return function_; }
90 int pc() const { return pc_; }
91
92 private:
93 friend class WasmInterpreter;
94
95 WasmFrame(const WasmFunction* function, int pc, int fp, int sp)
96 : function_(function), pc_(pc), fp_(fp), sp_(sp) {}
97
98 const WasmFunction* function_;
99 int pc_;
100 int fp_;
101 int sp_;
102};
103
104// An interpreter capable of executing WASM.
105class WasmInterpreter {
106 public:
107 // State machine for a Thread:
108 // +---------------Run()-----------+
109 // V |
110 // STOPPED ---Run()--> RUNNING ------Pause()-----+-> PAUSED <------+
111 // | | | / | |
112 // | | +---- Breakpoint ---+ +-- Step() --+
113 // | |
114 // | +------------ Trap --------------> TRAPPED
115 // +------------- Finish -------------> FINISHED
116 enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
117
118 // Representation of a thread in the interpreter.
119 class Thread {
120 public:
121 // Execution control.
122 virtual State state() = 0;
123 virtual void PushFrame(const WasmFunction* function, WasmVal* args) = 0;
124 virtual State Run() = 0;
125 virtual State Step() = 0;
126 virtual void Pause() = 0;
127 virtual void Reset() = 0;
128 virtual ~Thread() {}
129
130 // Stack inspection and modification.
131 virtual pc_t GetBreakpointPc() = 0;
132 virtual int GetFrameCount() = 0;
133 virtual const WasmFrame* GetFrame(int index) = 0;
134 virtual WasmFrame* GetMutableFrame(int index) = 0;
135 virtual WasmVal GetReturnValue() = 0;
136
137 // Thread-specific breakpoints.
138 bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
139 bool GetBreakpoint(const WasmFunction* function, int pc);
140 };
141
142 WasmInterpreter(WasmModuleInstance* instance,
143 base::AccountingAllocator* allocator);
144 ~WasmInterpreter();
145
146 //==========================================================================
147 // Execution controls.
148 //==========================================================================
149 void Run();
150 void Pause();
151
152 // Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
153 // previous state of the breakpoint at {pc}.
154 bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
155
156 // Gets the current state of the breakpoint at {function}.
157 bool GetBreakpoint(const WasmFunction* function, pc_t pc);
158
159 // Enable or disable tracing for {function}. Return the previous state.
160 bool SetTracing(const WasmFunction* function, bool enabled);
161
162 //==========================================================================
163 // Thread iteration and inspection.
164 //==========================================================================
165 int GetThreadCount();
166 Thread* GetThread(int id);
167
168 //==========================================================================
169 // Stack frame inspection.
170 //==========================================================================
171 WasmVal GetLocalVal(const WasmFrame* frame, int index);
172 WasmVal GetExprVal(const WasmFrame* frame, int pc);
173 void SetLocalVal(WasmFrame* frame, int index, WasmVal val);
174 void SetExprVal(WasmFrame* frame, int pc, WasmVal val);
175
176 //==========================================================================
177 // Memory access.
178 //==========================================================================
179 size_t GetMemorySize();
180 WasmVal ReadMemory(size_t offset);
181 void WriteMemory(size_t offset, WasmVal val);
182
183 //==========================================================================
184 // Testing functionality.
185 //==========================================================================
186 // Manually adds a function to this interpreter, returning the index of the
187 // function.
188 int AddFunctionForTesting(const WasmFunction* function);
189 // Manually adds code to the interpreter for the given function.
190 bool SetFunctionCodeForTesting(const WasmFunction* function,
191 const byte* start, const byte* end);
192
193 // Computes the control targets for the given bytecode as {pc offset, sp
194 // offset}
195 // pairs. Used internally in the interpreter, but exposed for testing.
196 static ControlTransferMap ComputeControlTransfersForTesting(Zone* zone,
197 const byte* start,
198 const byte* end);
199
200 private:
201 Zone zone_;
202 WasmInterpreterInternals* internals_;
203};
204
205} // namespace wasm
206} // namespace internal
207} // namespace v8
208
209#endif // V8_WASM_INTERPRETER_H_