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_WASM_INTERPRETER_H_
6 #define V8_WASM_WASM_INTERPRETER_H_
7 
8 #include <memory>
9 
10 #include "src/wasm/wasm-opcodes.h"
11 #include "src/wasm/wasm-value.h"
12 #include "src/zone/zone-containers.h"
13 
14 namespace v8 {
15 
16 namespace internal {
17 class WasmInstanceObject;
18 
19 namespace wasm {
20 
21 // Forward declarations.
22 struct ModuleWireBytes;
23 struct WasmFunction;
24 struct WasmModule;
25 class WasmInterpreterInternals;
26 
27 using pc_t = size_t;
28 using sp_t = size_t;
29 using pcdiff_t = int32_t;
30 using spdiff_t = uint32_t;
31 
32 struct ControlTransferEntry {
33   // Distance from the instruction to the label to jump to (forward, but can be
34   // negative).
35   pcdiff_t pc_diff;
36   // Delta by which to decrease the stack height.
37   spdiff_t sp_diff;
38   // Arity of the block we jump to.
39   uint32_t target_arity;
40 };
41 
42 struct CatchControlTransferEntry : public ControlTransferEntry {
43   int tag_index;
44   int target_control_index;
45 };
46 
47 struct ControlTransferMap {
ControlTransferMapControlTransferMap48   explicit ControlTransferMap(Zone* zone) : map(zone), catch_map(zone) {}
49 
50   ZoneMap<pc_t, ControlTransferEntry> map;
51   ZoneMap<pc_t, ZoneVector<CatchControlTransferEntry>> catch_map;
52 };
53 
54 // An interpreter capable of executing WebAssembly.
55 class WasmInterpreter {
56  public:
57   WasmInterpreter(const WasmInterpreter&) = delete;
58   WasmInterpreter& operator=(const WasmInterpreter&) = delete;
59 
60   // State machine for the interpreter:
61   //    +----------------------------------------------------------+
62   //    |                    +--------Run()/Step()---------+       |
63   //    V                    V                             |       |
64   // STOPPED ---Run()-->  RUNNING  ------Pause()-----+-> PAUSED <--+
65   //    ^                 | | | |                   /
66   //    +--- Exception ---+ | | +--- Breakpoint ---+
67   //                        | +---------- Trap --------------> TRAPPED
68   //                        +----------- Finish -------------> FINISHED
69   enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };
70 
71   enum ExceptionHandlingResult { HANDLED, UNWOUND };
72 
73   WasmInterpreter(Isolate* isolate, const WasmModule* module,
74                   const ModuleWireBytes& wire_bytes,
75                   Handle<WasmInstanceObject> instance);
76 
77   ~WasmInterpreter();
78 
79   //==========================================================================
80   // Execution controls.
81   //==========================================================================
82   State state() const;
83   void InitFrame(const WasmFunction* function, WasmValue* args);
84   // Pass -1 as num_steps to run till completion, pause or breakpoint.
85   State Run(int num_steps = -1);
Step()86   State Step() { return Run(1); }
87   void Pause();
88   void Reset();
89 
90   // Stack inspection and modification.
91   WasmValue GetReturnValue(int index = 0) const;
92   TrapReason GetTrapReason() const;
93 
94   // Returns true if the thread executed an instruction which may produce
95   // nondeterministic results, e.g. float div, float sqrt, and float mul,
96   // where the sign bit of a NaN is nondeterministic.
97   bool PossibleNondeterminism() const;
98 
99   // Returns the number of calls / function frames executed on this thread.
100   uint64_t NumInterpretedCalls() const;
101 
102   //==========================================================================
103   // Testing functionality.
104   //==========================================================================
105   // Manually adds a function to this interpreter. The func_index of the
106   // function must match the current number of functions.
107   void AddFunctionForTesting(const WasmFunction* function);
108   // Manually adds code to the interpreter for the given function.
109   void SetFunctionCodeForTesting(const WasmFunction* function,
110                                  const byte* start, const byte* end);
111 
112   // Computes the control transfers for the given bytecode. Used internally in
113   // the interpreter, but exposed for testing.
114   static ControlTransferMap ComputeControlTransfersForTesting(
115       Zone* zone, const WasmModule* module, const byte* start, const byte* end);
116 
117  private:
118   Zone zone_;
119   std::unique_ptr<WasmInterpreterInternals> internals_;
120 };
121 
122 }  // namespace wasm
123 }  // namespace internal
124 }  // namespace v8
125 
126 #endif  // V8_WASM_WASM_INTERPRETER_H_
127