v8/test/common/wasm/wasm-interpreter.h
Thibaud Michaud 88ba828575 [wasm][interpreter][eh] Add rethrow with immediate
When there are multiple nested catch blocks, the rethrow immediate
disambiguates which catch block to take the exception from. We
add a FixedArray to keep track of exceptions that are currently
in scope, and compute the mappings between rethrow/catch instructions
and the index to fetch/store the exception from/to in the FixedArray
during pre-processing.

R=clemensb@chromium.org

Bug: v8:8091
Change-Id: If55242c551f42262c790b5bf3f1543a003280623
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2695388
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72768}
2021-02-16 12:48:48 +00:00

127 lines
4.2 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 exception_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 WasmModule* module, 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_