Home | History | Annotate | Download | only in wasm
      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 
     51   WasmVal() : type(kWasmStmt) {}
     52 
     53 #define DECLARE_CONSTRUCTOR(field, localtype, ctype) \
     54   explicit WasmVal(ctype v) : type(localtype) { val.field = v; }
     55   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>
     64   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   }
     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