01d77d0356
Also roll 0705a10: Comments Change-Id: I9802283fa68093839286779503b6073122cbc8d7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1739369 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#63108}
775 lines
17 KiB
C++
775 lines
17 KiB
C++
// WebAssembly C++ API
|
|
|
|
#ifndef __WASM_HH
|
|
#define __WASM_HH
|
|
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <memory>
|
|
#include <limits>
|
|
#include <string>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Auxiliaries
|
|
|
|
// Machine types
|
|
|
|
static_assert(sizeof(float) == sizeof(int32_t), "incompatible float type");
|
|
static_assert(sizeof(double) == sizeof(int64_t), "incompatible double type");
|
|
static_assert(sizeof(intptr_t) == sizeof(int32_t) ||
|
|
sizeof(intptr_t) == sizeof(int64_t), "incompatible pointer type");
|
|
|
|
using byte_t = char;
|
|
using float32_t = float;
|
|
using float64_t = double;
|
|
|
|
|
|
namespace wasm {
|
|
|
|
// Ownership
|
|
|
|
template<class T> struct owner { using type = T; };
|
|
template<class T> struct owner<T*> { using type = std::unique_ptr<T>; };
|
|
|
|
template<class T>
|
|
using own = typename owner<T>::type;
|
|
|
|
template<class T>
|
|
auto make_own(T x) -> own<T> { return own<T>(std::move(x)); }
|
|
|
|
|
|
// Vectors
|
|
|
|
template<class T>
|
|
struct vec_traits {
|
|
static void construct(size_t size, T data[]) {}
|
|
static void destruct(size_t size, T data[]) {}
|
|
static void move(size_t size, T* data, T init[]) {
|
|
for (size_t i = 0; i < size; ++i) data[i] = std::move(init[i]);
|
|
}
|
|
static void copy(size_t size, T data[], const T init[]) {
|
|
for (size_t i = 0; i < size; ++i) data[i] = init[i];
|
|
}
|
|
|
|
using proxy = T&;
|
|
};
|
|
|
|
template<class T>
|
|
struct vec_traits<T*> {
|
|
static void construct(size_t size, T* data[]) {
|
|
for (size_t i = 0; i < size; ++i) data[i] = nullptr;
|
|
}
|
|
static void destruct(size_t size, T* data[]) {
|
|
for (size_t i = 0; i < size; ++i) {
|
|
if (data[i]) delete data[i];
|
|
}
|
|
}
|
|
static void move(size_t size, T* data[], own<T*> init[]) {
|
|
for (size_t i = 0; i < size; ++i) data[i] = init[i].release();
|
|
}
|
|
static void copy(size_t size, T* data[], const T* const init[]) {
|
|
for (size_t i = 0; i < size; ++i) {
|
|
if (init[i]) data[i] = init[i]->copy().release();
|
|
}
|
|
}
|
|
|
|
class proxy {
|
|
T*& elem_;
|
|
public:
|
|
proxy(T*& elem) : elem_(elem) {}
|
|
operator T*() { return elem_; }
|
|
operator const T*() const { return elem_; }
|
|
auto operator=(own<T*>&& elem) -> proxy& {
|
|
reset(std::move(elem));
|
|
return *this;
|
|
}
|
|
void reset(own<T*>&& val = own<T*>()) {
|
|
if (elem_) delete elem_;
|
|
elem_ = val.release();
|
|
}
|
|
auto release() -> T* {
|
|
auto elem = elem_;
|
|
elem_ = nullptr;
|
|
return elem;
|
|
}
|
|
auto move() -> own<T*> { return make_own(release()); }
|
|
auto get() -> T* { return elem_; }
|
|
auto get() const -> const T* { return elem_; }
|
|
auto operator->() -> T* { return elem_; }
|
|
auto operator->() const -> const T* { return elem_; }
|
|
};
|
|
};
|
|
|
|
|
|
template<class T>
|
|
class vec {
|
|
static const size_t invalid_size = SIZE_MAX;
|
|
|
|
size_t size_;
|
|
std::unique_ptr<T[]> data_;
|
|
|
|
#ifdef DEBUG
|
|
void make_data();
|
|
void free_data();
|
|
#else
|
|
void make_data() {}
|
|
void free_data() {}
|
|
#endif
|
|
|
|
vec(size_t size) : vec(size, size ? new(std::nothrow) T[size] : nullptr) {
|
|
make_data();
|
|
}
|
|
|
|
vec(size_t size, T* data) : size_(size), data_(data) {
|
|
assert(!!size_ == !!data_ || size_ == invalid_size);
|
|
}
|
|
|
|
public:
|
|
template<class U>
|
|
vec(vec<U>&& that) : vec(that.size_, that.data_.release()) {}
|
|
|
|
~vec() {
|
|
if (data_) vec_traits<T>::destruct(size_, data_.get());
|
|
free_data();
|
|
}
|
|
|
|
operator bool() const {
|
|
return bool(size_ != invalid_size);
|
|
}
|
|
|
|
auto size() const -> size_t {
|
|
return size_;
|
|
}
|
|
|
|
auto get() const -> const T* {
|
|
return data_.get();
|
|
}
|
|
|
|
auto get() -> T* {
|
|
return data_.get();
|
|
}
|
|
|
|
auto release() -> T* {
|
|
return data_.release();
|
|
}
|
|
|
|
void reset() {
|
|
if (data_) vec_traits<T>::destruct(size_, data_.get());
|
|
free_data();
|
|
size_ = 0;
|
|
data_.reset();
|
|
}
|
|
|
|
void reset(vec& that) {
|
|
reset();
|
|
size_ = that.size_;
|
|
data_.reset(that.data_.release());
|
|
}
|
|
|
|
auto operator=(vec&& that) -> vec& {
|
|
reset(that);
|
|
return *this;
|
|
}
|
|
|
|
auto operator[](size_t i) -> typename vec_traits<T>::proxy {
|
|
assert(i < size_);
|
|
return typename vec_traits<T>::proxy(data_[i]);
|
|
}
|
|
|
|
auto operator[](size_t i) const -> const typename vec_traits<T>::proxy {
|
|
assert(i < size_);
|
|
return typename vec_traits<T>::proxy(data_[i]);
|
|
}
|
|
|
|
auto copy() const -> vec {
|
|
auto v = vec(size_);
|
|
if (v) vec_traits<T>::copy(size_, v.data_.get(), data_.get());
|
|
return v;
|
|
}
|
|
|
|
static auto make_uninitialized(size_t size = 0) -> vec {
|
|
auto v = vec(size);
|
|
if (v) vec_traits<T>::construct(size, v.data_.get());
|
|
return v;
|
|
}
|
|
|
|
static auto make(size_t size, own<T> init[]) -> vec {
|
|
auto v = vec(size);
|
|
if (v) vec_traits<T>::move(size, v.data_.get(), init);
|
|
return v;
|
|
}
|
|
|
|
static auto make(std::string s) -> vec<char> {
|
|
auto v = vec(s.length() + 1);
|
|
if (v) std::strcpy(v.get(), s.data());
|
|
return v;
|
|
}
|
|
|
|
// TODO(mvsc): MVSC requires this special case:
|
|
static auto make() -> vec {
|
|
return vec(0);
|
|
}
|
|
|
|
template<class... Ts>
|
|
static auto make(Ts&&... args) -> vec {
|
|
own<T> data[] = { make_own(std::move(args))... };
|
|
return make(sizeof...(Ts), data);
|
|
}
|
|
|
|
static auto adopt(size_t size, T data[]) -> vec {
|
|
return vec(size, data);
|
|
}
|
|
|
|
static auto invalid() -> vec {
|
|
return vec(invalid_size, nullptr);
|
|
}
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Runtime Environment
|
|
|
|
// Configuration
|
|
|
|
class Config {
|
|
public:
|
|
Config() = delete;
|
|
~Config();
|
|
void operator delete(void*);
|
|
|
|
static auto make() -> own<Config*>;
|
|
|
|
// Implementations may provide custom methods for manipulating Configs.
|
|
};
|
|
|
|
|
|
// Engine
|
|
|
|
class Engine {
|
|
public:
|
|
Engine() = delete;
|
|
~Engine();
|
|
void operator delete(void*);
|
|
|
|
static auto make(own<Config*>&& = Config::make()) -> own<Engine*>;
|
|
};
|
|
|
|
|
|
// Store
|
|
|
|
class Store {
|
|
public:
|
|
Store() = delete;
|
|
~Store();
|
|
void operator delete(void*);
|
|
|
|
static auto make(Engine*) -> own<Store*>;
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Type Representations
|
|
|
|
// Type attributes
|
|
|
|
enum Mutability { CONST, VAR };
|
|
|
|
struct Limits {
|
|
uint32_t min;
|
|
uint32_t max;
|
|
|
|
Limits(uint32_t min, uint32_t max = std::numeric_limits<uint32_t>::max()) :
|
|
min(min), max(max) {}
|
|
};
|
|
|
|
|
|
// Value Types
|
|
|
|
enum ValKind { I32, I64, F32, F64, ANYREF, FUNCREF };
|
|
|
|
inline bool is_num(ValKind k) { return k < ANYREF; }
|
|
inline bool is_ref(ValKind k) { return k >= ANYREF; }
|
|
|
|
|
|
class ValType {
|
|
public:
|
|
ValType() = delete;
|
|
~ValType();
|
|
void operator delete(void*);
|
|
|
|
static auto make(ValKind) -> own<ValType*>;
|
|
auto copy() const -> own<ValType*>;
|
|
|
|
auto kind() const -> ValKind;
|
|
auto is_num() const -> bool { return wasm::is_num(kind()); }
|
|
auto is_ref() const -> bool { return wasm::is_ref(kind()); }
|
|
};
|
|
|
|
|
|
// External Types
|
|
|
|
enum ExternKind {
|
|
EXTERN_FUNC, EXTERN_GLOBAL, EXTERN_TABLE, EXTERN_MEMORY
|
|
};
|
|
|
|
class FuncType;
|
|
class GlobalType;
|
|
class TableType;
|
|
class MemoryType;
|
|
|
|
class ExternType {
|
|
public:
|
|
ExternType() = delete;
|
|
~ExternType();
|
|
void operator delete(void*);
|
|
|
|
auto copy() const-> own<ExternType*>;
|
|
|
|
auto kind() const -> ExternKind;
|
|
|
|
auto func() -> FuncType*;
|
|
auto global() -> GlobalType*;
|
|
auto table() -> TableType*;
|
|
auto memory() -> MemoryType*;
|
|
|
|
auto func() const -> const FuncType*;
|
|
auto global() const -> const GlobalType*;
|
|
auto table() const -> const TableType*;
|
|
auto memory() const -> const MemoryType*;
|
|
};
|
|
|
|
|
|
// Function Types
|
|
|
|
enum class arrow { ARROW };
|
|
|
|
class FuncType : public ExternType {
|
|
public:
|
|
FuncType() = delete;
|
|
~FuncType();
|
|
|
|
static auto make(
|
|
vec<ValType*>&& params = vec<ValType*>::make(),
|
|
vec<ValType*>&& results = vec<ValType*>::make()
|
|
) -> own<FuncType*>;
|
|
|
|
auto copy() const -> own<FuncType*>;
|
|
|
|
auto params() const -> const vec<ValType*>&;
|
|
auto results() const -> const vec<ValType*>&;
|
|
};
|
|
|
|
|
|
// Global Types
|
|
|
|
class GlobalType : public ExternType {
|
|
public:
|
|
GlobalType() = delete;
|
|
~GlobalType();
|
|
|
|
static auto make(own<ValType*>&&, Mutability) -> own<GlobalType*>;
|
|
auto copy() const -> own<GlobalType*>;
|
|
|
|
auto content() const -> const ValType*;
|
|
auto mutability() const -> Mutability;
|
|
};
|
|
|
|
|
|
// Table Types
|
|
|
|
class TableType : public ExternType {
|
|
public:
|
|
TableType() = delete;
|
|
~TableType();
|
|
|
|
static auto make(own<ValType*>&&, Limits) -> own<TableType*>;
|
|
auto copy() const -> own<TableType*>;
|
|
|
|
auto element() const -> const ValType*;
|
|
auto limits() const -> const Limits&;
|
|
};
|
|
|
|
|
|
// Memory Types
|
|
|
|
class MemoryType : public ExternType {
|
|
public:
|
|
MemoryType() = delete;
|
|
~MemoryType();
|
|
|
|
static auto make(Limits) -> own<MemoryType*>;
|
|
auto copy() const -> own<MemoryType*>;
|
|
|
|
auto limits() const -> const Limits&;
|
|
};
|
|
|
|
|
|
// Import Types
|
|
|
|
using Name = vec<byte_t>;
|
|
|
|
class ImportType {
|
|
public:
|
|
ImportType() = delete;
|
|
~ImportType();
|
|
void operator delete(void*);
|
|
|
|
static auto make(Name&& module, Name&& name, own<ExternType*>&&) ->
|
|
own<ImportType*>;
|
|
auto copy() const -> own<ImportType*>;
|
|
|
|
auto module() const -> const Name&;
|
|
auto name() const -> const Name&;
|
|
auto type() const -> const ExternType*;
|
|
};
|
|
|
|
|
|
// Export Types
|
|
|
|
class ExportType {
|
|
public:
|
|
ExportType() = delete;
|
|
~ExportType();
|
|
void operator delete(void*);
|
|
|
|
static auto make(Name&&, own<ExternType*>&&) -> own<ExportType*>;
|
|
auto copy() const -> own<ExportType*>;
|
|
|
|
auto name() const -> const Name&;
|
|
auto type() const -> const ExternType*;
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Runtime Objects
|
|
|
|
// References
|
|
|
|
class Ref {
|
|
public:
|
|
Ref() = delete;
|
|
~Ref();
|
|
void operator delete(void*);
|
|
|
|
auto copy() const -> own<Ref*>;
|
|
auto same(const Ref*) const -> bool;
|
|
|
|
auto get_host_info() const -> void*;
|
|
void set_host_info(void* info, void (*finalizer)(void*) = nullptr);
|
|
};
|
|
|
|
|
|
// Values
|
|
|
|
class Val {
|
|
ValKind kind_;
|
|
union impl {
|
|
int32_t i32;
|
|
int64_t i64;
|
|
float32_t f32;
|
|
float64_t f64;
|
|
Ref* ref;
|
|
} impl_;
|
|
|
|
Val(ValKind kind, impl impl) : kind_(kind), impl_(impl) {}
|
|
|
|
public:
|
|
Val() : kind_(ANYREF) { impl_.ref = nullptr; }
|
|
Val(int32_t i) : kind_(I32) { impl_.i32 = i; }
|
|
Val(int64_t i) : kind_(I64) { impl_.i64 = i; }
|
|
Val(float32_t z) : kind_(F32) { impl_.f32 = z; }
|
|
Val(float64_t z) : kind_(F64) { impl_.f64 = z; }
|
|
Val(own<Ref*>&& r) : kind_(ANYREF) { impl_.ref = r.release(); }
|
|
|
|
Val(Val&& that) : kind_(that.kind_), impl_(that.impl_) {
|
|
if (is_ref()) that.impl_.ref = nullptr;
|
|
}
|
|
|
|
~Val() {
|
|
reset();
|
|
}
|
|
|
|
auto is_num() const -> bool { return wasm::is_num(kind_); }
|
|
auto is_ref() const -> bool { return wasm::is_ref(kind_); }
|
|
|
|
static auto i32(int32_t x) -> Val { return Val(x); }
|
|
static auto i64(int64_t x) -> Val { return Val(x); }
|
|
static auto f32(float32_t x) -> Val { return Val(x); }
|
|
static auto f64(float64_t x) -> Val { return Val(x); }
|
|
static auto ref(own<Ref*>&& x) -> Val { return Val(std::move(x)); }
|
|
template<class T> inline static auto make(T x) -> Val;
|
|
template<class T> inline static auto make(own<T>&& x) -> Val;
|
|
|
|
void reset() {
|
|
if (is_ref() && impl_.ref) {
|
|
delete impl_.ref;
|
|
impl_.ref = nullptr;
|
|
}
|
|
}
|
|
|
|
void reset(Val& that) {
|
|
reset();
|
|
kind_ = that.kind_;
|
|
impl_ = that.impl_;
|
|
if (is_ref()) that.impl_.ref = nullptr;
|
|
}
|
|
|
|
auto operator=(Val&& that) -> Val& {
|
|
reset(that);
|
|
return *this;
|
|
}
|
|
|
|
auto kind() const -> ValKind { return kind_; }
|
|
auto i32() const -> int32_t { assert(kind_ == I32); return impl_.i32; }
|
|
auto i64() const -> int64_t { assert(kind_ == I64); return impl_.i64; }
|
|
auto f32() const -> float32_t { assert(kind_ == F32); return impl_.f32; }
|
|
auto f64() const -> float64_t { assert(kind_ == F64); return impl_.f64; }
|
|
auto ref() const -> Ref* { assert(is_ref()); return impl_.ref; }
|
|
template<class T> inline auto get() const -> T;
|
|
|
|
auto release_ref() -> own<Ref*> {
|
|
assert(is_ref());
|
|
auto ref = impl_.ref;
|
|
ref = nullptr;
|
|
return own<Ref*>(ref);
|
|
}
|
|
|
|
auto copy() const -> Val {
|
|
if (is_ref() && impl_.ref != nullptr) {
|
|
// TODO(mvsc): MVSC cannot handle this:
|
|
// impl impl = {.ref = impl_.ref->copy().release()};
|
|
impl impl;
|
|
impl.ref = impl_.ref->copy().release();
|
|
return Val(kind_, impl);
|
|
} else {
|
|
return Val(kind_, impl_);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
template<> inline auto Val::make<int32_t>(int32_t x) -> Val { return Val(x); }
|
|
template<> inline auto Val::make<int64_t>(int64_t x) -> Val { return Val(x); }
|
|
template<> inline auto Val::make<float32_t>(float32_t x) -> Val { return Val(x); }
|
|
template<> inline auto Val::make<float64_t>(float64_t x) -> Val { return Val(x); }
|
|
template<> inline auto Val::make<Ref*>(own<Ref*>&& x) -> Val {
|
|
return Val(std::move(x));
|
|
}
|
|
|
|
template<> inline auto Val::make<uint32_t>(uint32_t x) -> Val {
|
|
return Val(static_cast<int32_t>(x));
|
|
}
|
|
template<> inline auto Val::make<uint64_t>(uint64_t x) -> Val {
|
|
return Val(static_cast<int64_t>(x));
|
|
}
|
|
|
|
template<> inline auto Val::get<int32_t>() const -> int32_t { return i32(); }
|
|
template<> inline auto Val::get<int64_t>() const -> int64_t { return i64(); }
|
|
template<> inline auto Val::get<float32_t>() const -> float32_t { return f32(); }
|
|
template<> inline auto Val::get<float64_t>() const -> float64_t { return f64(); }
|
|
template<> inline auto Val::get<Ref*>() const -> Ref* { return ref(); }
|
|
|
|
template<> inline auto Val::get<uint32_t>() const -> uint32_t {
|
|
return static_cast<uint32_t>(i32());
|
|
}
|
|
template<> inline auto Val::get<uint64_t>() const -> uint64_t {
|
|
return static_cast<uint64_t>(i64());
|
|
}
|
|
|
|
|
|
// Traps
|
|
|
|
using Message = vec<byte_t>; // null terminated
|
|
|
|
class Trap : public Ref {
|
|
public:
|
|
Trap() = delete;
|
|
~Trap();
|
|
|
|
static auto make(Store*, const Message& msg) -> own<Trap*>;
|
|
auto copy() const -> own<Trap*>;
|
|
|
|
auto message() const -> Message;
|
|
};
|
|
|
|
|
|
// Shared objects
|
|
|
|
template<class T>
|
|
class Shared {
|
|
public:
|
|
Shared() = delete;
|
|
~Shared();
|
|
void operator delete(void*);
|
|
};
|
|
|
|
|
|
// Modules
|
|
|
|
class Module : public Ref {
|
|
public:
|
|
Module() = delete;
|
|
~Module();
|
|
|
|
static auto validate(Store*, const vec<byte_t>& binary) -> bool;
|
|
static auto make(Store*, const vec<byte_t>& binary) -> own<Module*>;
|
|
auto copy() const -> own<Module*>;
|
|
|
|
auto imports() const -> vec<ImportType*>;
|
|
auto exports() const -> vec<ExportType*>;
|
|
|
|
auto share() const -> own<Shared<Module>*>;
|
|
static auto obtain(Store*, const Shared<Module>*) -> own<Module*>;
|
|
|
|
auto serialize() const -> vec<byte_t>;
|
|
static auto deserialize(Store*, const vec<byte_t>&) -> own<Module*>;
|
|
};
|
|
|
|
|
|
// Foreign Objects
|
|
|
|
class Foreign : public Ref {
|
|
public:
|
|
Foreign() = delete;
|
|
~Foreign();
|
|
|
|
static auto make(Store*) -> own<Foreign*>;
|
|
auto copy() const -> own<Foreign*>;
|
|
};
|
|
|
|
|
|
// Externals
|
|
|
|
class Func;
|
|
class Global;
|
|
class Table;
|
|
class Memory;
|
|
|
|
class Extern : public Ref {
|
|
public:
|
|
Extern() = delete;
|
|
~Extern();
|
|
|
|
auto copy() const -> own<Extern*>;
|
|
|
|
auto kind() const -> ExternKind;
|
|
auto type() const -> own<ExternType*>;
|
|
|
|
auto func() -> Func*;
|
|
auto global() -> Global*;
|
|
auto table() -> Table*;
|
|
auto memory() -> Memory*;
|
|
|
|
auto func() const -> const Func*;
|
|
auto global() const -> const Global*;
|
|
auto table() const -> const Table*;
|
|
auto memory() const -> const Memory*;
|
|
};
|
|
|
|
|
|
// Function Instances
|
|
|
|
class Func : public Extern {
|
|
public:
|
|
Func() = delete;
|
|
~Func();
|
|
|
|
using callback = auto (*)(const Val[], Val[]) -> own<Trap*>;
|
|
using callback_with_env = auto (*)(void*, const Val[], Val[]) -> own<Trap*>;
|
|
|
|
static auto make(Store*, const FuncType*, callback) -> own<Func*>;
|
|
static auto make(Store*, const FuncType*, callback_with_env,
|
|
void*, void (*finalizer)(void*) = nullptr) -> own<Func*>;
|
|
auto copy() const -> own<Func*>;
|
|
|
|
auto type() const -> own<FuncType*>;
|
|
auto param_arity() const -> size_t;
|
|
auto result_arity() const -> size_t;
|
|
|
|
auto call(const Val[] = nullptr, Val[] = nullptr) const -> own<Trap*>;
|
|
};
|
|
|
|
|
|
// Global Instances
|
|
|
|
class Global : public Extern {
|
|
public:
|
|
Global() = delete;
|
|
~Global();
|
|
|
|
static auto make(Store*, const GlobalType*, const Val&) -> own<Global*>;
|
|
auto copy() const -> own<Global*>;
|
|
|
|
auto type() const -> own<GlobalType*>;
|
|
auto get() const -> Val;
|
|
void set(const Val&);
|
|
};
|
|
|
|
|
|
// Table Instances
|
|
|
|
class Table : public Extern {
|
|
public:
|
|
Table() = delete;
|
|
~Table();
|
|
|
|
using size_t = uint32_t;
|
|
|
|
static auto make(
|
|
Store*, const TableType*, const Ref* init = nullptr) -> own<Table*>;
|
|
auto copy() const -> own<Table*>;
|
|
|
|
auto type() const -> own<TableType*>;
|
|
auto get(size_t index) const -> own<Ref*>;
|
|
auto set(size_t index, const Ref*) -> bool;
|
|
auto size() const -> size_t;
|
|
auto grow(size_t delta, const Ref* init = nullptr) -> bool;
|
|
};
|
|
|
|
|
|
// Memory Instances
|
|
|
|
class Memory : public Extern {
|
|
public:
|
|
Memory() = delete;
|
|
~Memory();
|
|
|
|
static auto make(Store*, const MemoryType*) -> own<Memory*>;
|
|
auto copy() const -> own<Memory*>;
|
|
|
|
using pages_t = uint32_t;
|
|
|
|
static const size_t page_size = 0x10000;
|
|
|
|
auto type() const -> own<MemoryType*>;
|
|
auto data() const -> byte_t*;
|
|
auto data_size() const -> size_t;
|
|
auto size() const -> pages_t;
|
|
auto grow(pages_t delta) -> bool;
|
|
};
|
|
|
|
|
|
// Module Instances
|
|
|
|
class Instance : public Ref {
|
|
public:
|
|
Instance() = delete;
|
|
~Instance();
|
|
|
|
static auto make(
|
|
Store*, const Module*, const Extern* const[]) -> own<Instance*>;
|
|
auto copy() const -> own<Instance*>;
|
|
|
|
auto exports() const -> vec<Extern*>;
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
} // namespave wasm
|
|
|
|
#endif // #ifdef __WASM_HH
|