summaryrefslogtreecommitdiff
path: root/deps/v8/test/common/wasm/wasm-interpreter.h
blob: 10d6f745933fc342281f32f6ed2b46c701993a6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// 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_WASM_INTERPRETER_H_
#define V8_WASM_WASM_INTERPRETER_H_

#include <memory>

#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-value.h"
#include "src/zone/zone-containers.h"

namespace v8 {

namespace internal {
class WasmInstanceObject;

namespace wasm {

// Forward declarations.
struct ModuleWireBytes;
struct WasmFunction;
struct WasmModule;
class WasmInterpreterInternals;

using pc_t = size_t;
using sp_t = size_t;
using pcdiff_t = int32_t;
using spdiff_t = uint32_t;

struct ControlTransferEntry {
  // Distance from the instruction to the label to jump to (forward, but can be
  // negative).
  pcdiff_t pc_diff;
  // Delta by which to decrease the stack height.
  spdiff_t sp_diff;
  // Arity of the block we jump to.
  uint32_t target_arity;
};

struct CatchControlTransferEntry : public ControlTransferEntry {
  int tag_index;
  int target_control_index;
};

struct ControlTransferMap {
  explicit ControlTransferMap(Zone* zone) : map(zone), catch_map(zone) {}

  ZoneMap<pc_t, ControlTransferEntry> map;
  ZoneMap<pc_t, ZoneVector<CatchControlTransferEntry>> catch_map;
};

// An interpreter capable of executing WebAssembly.
class WasmInterpreter {
 public:
  WasmInterpreter(const WasmInterpreter&) = delete;
  WasmInterpreter& operator=(const WasmInterpreter&) = delete;

  // State machine for the interpreter:
  //    +----------------------------------------------------------+
  //    |                    +--------Run()/Step()---------+       |
  //    V                    V                             |       |
  // STOPPED ---Run()-->  RUNNING  ------Pause()-----+-> PAUSED <--+
  //    ^                 | | | |                   /
  //    +--- Exception ---+ | | +--- Breakpoint ---+
  //                        | +---------- Trap --------------> TRAPPED
  //                        +----------- Finish -------------> FINISHED
  enum State { STOPPED, RUNNING, PAUSED, FINISHED, TRAPPED };

  enum ExceptionHandlingResult { HANDLED, UNWOUND };

  WasmInterpreter(Isolate* isolate, const WasmModule* module,
                  const ModuleWireBytes& wire_bytes,
                  Handle<WasmInstanceObject> instance);

  ~WasmInterpreter();

  //==========================================================================
  // Execution controls.
  //==========================================================================
  State state() const;
  void InitFrame(const WasmFunction* function, WasmValue* args);
  // Pass -1 as num_steps to run till completion, pause or breakpoint.
  State Run(int num_steps = -1);
  State Step() { return Run(1); }
  void Pause();
  void Reset();

  // Stack inspection and modification.
  WasmValue GetReturnValue(int index = 0) const;
  TrapReason GetTrapReason() const;

  // 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() const;

  // Returns the number of calls / function frames executed on this thread.
  uint64_t NumInterpretedCalls() const;

  //==========================================================================
  // Testing functionality.
  //==========================================================================
  // Manually adds a function to this interpreter. The func_index of the
  // function must match the current number of functions.
  void AddFunctionForTesting(const WasmFunction* function);
  // Manually adds code to the interpreter for the given function.
  void 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_;
  std::unique_ptr<WasmInterpreterInternals> internals_;
};

}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_WASM_INTERPRETER_H_