bbcf8b6c3a
The {BytecodeIterator} that also read locals declarations had a weird fallback path to allow decoding of locals to fail, and just assume no locals, decoding all bytes as code. This CL removes that, and modifies the test that needs this functionality to prepend a zero byte for encoding "0 locals". R=jkummerow@chromium.org Change-Id: I609e2bf6986eeb6380d65b03bf8512f0b09af764 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4003078 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#84088}
128 lines
4.3 KiB
C++
128 lines
4.3 KiB
C++
// 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_
|