mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 06:38:22 +00:00
test(c-api) Split the test suites (deprecated and wasm-c-api).
This commit is contained in:
@@ -1,570 +0,0 @@
|
||||
#include "wasm-bin.hh"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace wasm {
|
||||
namespace bin {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Encoding
|
||||
|
||||
void encode_header(char*& ptr) {
|
||||
std::memcpy(ptr, "\x00""asm\x01\x00\x00\x00", 8);
|
||||
ptr += 8;
|
||||
}
|
||||
|
||||
auto u64_size(uint64_t n) -> size_t {
|
||||
bool done = false;
|
||||
size_t size = 0;
|
||||
do {
|
||||
++size;
|
||||
done = n <= 0x7f;
|
||||
n = n >> 7;
|
||||
} while (!done);
|
||||
return size;
|
||||
}
|
||||
|
||||
auto u32_size(uint64_t n) -> size_t {
|
||||
return u64_size(n);
|
||||
}
|
||||
|
||||
void encode_u64(char*& ptr, uint64_t n) {
|
||||
bool done = false;
|
||||
do {
|
||||
done = n <= 0x7f;
|
||||
*ptr++ = (n & 0x7f) | (done ? 0x00 : 0x80);
|
||||
n = n >> 7;
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
void encode_u32(char*& ptr, uint32_t n) {
|
||||
encode_u64(ptr, n);
|
||||
}
|
||||
|
||||
void encode_size32(char*& ptr, size_t n) {
|
||||
assert(n <= 0xffffffff);
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
*ptr++ = (n & 0x7f) | (i == 4 ? 0x00 : 0x80);
|
||||
n = n >> 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void encode_valtype(char*& ptr, const ValType* type) {
|
||||
switch (type->kind()) {
|
||||
case ValKind::I32: *ptr++ = 0x7f; break;
|
||||
case ValKind::I64: *ptr++ = 0x7e; break;
|
||||
case ValKind::F32: *ptr++ = 0x7d; break;
|
||||
case ValKind::F64: *ptr++ = 0x7c; break;
|
||||
case ValKind::FUNCREF: *ptr++ = 0x70; break;
|
||||
case ValKind::ANYREF: *ptr++ = 0x6f; break;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto zero_size(const ValType* type) -> size_t {
|
||||
switch (type->kind()) {
|
||||
case ValKind::I32: return 1;
|
||||
case ValKind::I64: return 1;
|
||||
case ValKind::F32: return 4;
|
||||
case ValKind::F64: return 8;
|
||||
case ValKind::FUNCREF: return 0;
|
||||
case ValKind::ANYREF: return 0;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void encode_const_zero(char*& ptr, const ValType* type) {
|
||||
switch (type->kind()) {
|
||||
case ValKind::I32: *ptr++ = 0x41; break;
|
||||
case ValKind::I64: *ptr++ = 0x42; break;
|
||||
case ValKind::F32: *ptr++ = 0x43; break;
|
||||
case ValKind::F64: *ptr++ = 0x44; break;
|
||||
case ValKind::FUNCREF: *ptr++ = 0xd0; break;
|
||||
case ValKind::ANYREF: *ptr++ = 0xd0; break;
|
||||
default: assert(false);
|
||||
}
|
||||
for (int i = 0; i < zero_size(type); ++i) *ptr++ = 0;
|
||||
}
|
||||
|
||||
|
||||
auto wrapper(const FuncType* type) -> vec<byte_t> {
|
||||
auto in_arity = type->params().size();
|
||||
auto out_arity = type->results().size();
|
||||
auto size = 39 + in_arity + out_arity;
|
||||
auto binary = vec<byte_t>::make_uninitialized(size);
|
||||
auto ptr = binary.get();
|
||||
|
||||
encode_header(ptr);
|
||||
|
||||
*ptr++ = 0x01; // type section
|
||||
encode_size32(ptr, 12 + in_arity + out_arity); // size
|
||||
*ptr++ = 1; // length
|
||||
*ptr++ = 0x60; // function
|
||||
encode_size32(ptr, in_arity);
|
||||
for (size_t i = 0; i < in_arity; ++i) {
|
||||
encode_valtype(ptr, type->params()[i].get());
|
||||
}
|
||||
encode_size32(ptr, out_arity);
|
||||
for (size_t i = 0; i < out_arity; ++i) {
|
||||
encode_valtype(ptr, type->results()[i].get());
|
||||
}
|
||||
|
||||
*ptr++ = 0x02; // import section
|
||||
*ptr++ = 5; // size
|
||||
*ptr++ = 1; // length
|
||||
*ptr++ = 0; // module length
|
||||
*ptr++ = 0; // name length
|
||||
*ptr++ = 0x00; // func
|
||||
*ptr++ = 0; // type index
|
||||
|
||||
*ptr++ = 0x07; // export section
|
||||
*ptr++ = 4; // size
|
||||
*ptr++ = 1; // length
|
||||
*ptr++ = 0; // name length
|
||||
*ptr++ = 0x00; // func
|
||||
*ptr++ = 0; // func index
|
||||
|
||||
assert(ptr - binary.get() == size);
|
||||
return binary;
|
||||
}
|
||||
|
||||
auto wrapper(const GlobalType* type) -> vec<byte_t> {
|
||||
auto size = 25 + zero_size(type->content());
|
||||
auto binary = vec<byte_t>::make_uninitialized(size);
|
||||
auto ptr = binary.get();
|
||||
|
||||
encode_header(ptr);
|
||||
|
||||
*ptr++ = 0x06; // global section
|
||||
encode_size32(ptr, 5 + zero_size(type->content())); // size
|
||||
*ptr++ = 1; // length
|
||||
encode_valtype(ptr, type->content());
|
||||
*ptr++ = (type->mutability() == Mutability::VAR);
|
||||
encode_const_zero(ptr, type->content());
|
||||
*ptr++ = 0x0b; // end
|
||||
|
||||
*ptr++ = 0x07; // export section
|
||||
*ptr++ = 4; // size
|
||||
*ptr++ = 1; // length
|
||||
*ptr++ = 0; // name length
|
||||
*ptr++ = 0x03; // global
|
||||
*ptr++ = 0; // func index
|
||||
|
||||
assert(ptr - binary.get() == size);
|
||||
return binary;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Decoding
|
||||
|
||||
// Numbers
|
||||
|
||||
auto u32(const byte_t*& pos) -> uint32_t {
|
||||
uint32_t n = 0;
|
||||
uint32_t shift = 0;
|
||||
byte_t b;
|
||||
do {
|
||||
b = *pos++;
|
||||
n += (b & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while ((b & 0x80) != 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
auto u64(const byte_t*& pos) -> uint64_t {
|
||||
uint64_t n = 0;
|
||||
uint64_t shift = 0;
|
||||
byte_t b;
|
||||
do {
|
||||
b = *pos++;
|
||||
n += (b & 0x7f) << shift;
|
||||
shift += 7;
|
||||
} while ((b & 0x80) != 0);
|
||||
return n;
|
||||
}
|
||||
|
||||
void u32_skip(const byte_t*& pos) {
|
||||
bin::u32(pos);
|
||||
}
|
||||
|
||||
|
||||
// Names
|
||||
|
||||
auto name(const byte_t*& pos) -> Name {
|
||||
auto size = bin::u32(pos);
|
||||
auto start = pos;
|
||||
auto name = Name::make_uninitialized(size);
|
||||
std::memcpy(name.get(), start, size);
|
||||
pos += size;
|
||||
return name;
|
||||
}
|
||||
|
||||
void name_skip(const byte_t*& pos) {
|
||||
auto size = bin::u32(pos);
|
||||
pos += size;
|
||||
}
|
||||
|
||||
|
||||
// Types
|
||||
|
||||
auto valtype(const byte_t*& pos) -> own<wasm::ValType> {
|
||||
switch (*pos++) {
|
||||
case 0x7f: return ValType::make(ValKind::I32);
|
||||
case 0x7e: return ValType::make(ValKind::I64);
|
||||
case 0x7d: return ValType::make(ValKind::F32);
|
||||
case 0x7c: return ValType::make(ValKind::F64);
|
||||
case 0x70: return ValType::make(ValKind::FUNCREF);
|
||||
case 0x6f: return ValType::make(ValKind::ANYREF);
|
||||
default:
|
||||
// TODO(wasm+): support new value types
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto mutability(const byte_t*& pos) -> Mutability {
|
||||
return *pos++ ? Mutability::VAR : Mutability::CONST;
|
||||
}
|
||||
|
||||
auto limits(const byte_t*& pos) -> Limits {
|
||||
auto tag = *pos++;
|
||||
auto min = bin::u32(pos);
|
||||
if ((tag & 0x01) == 0) {
|
||||
return Limits(min);
|
||||
} else {
|
||||
auto max = bin::u32(pos);
|
||||
return Limits(min, max);
|
||||
}
|
||||
}
|
||||
|
||||
auto stacktype(const byte_t*& pos) -> ownvec<ValType> {
|
||||
size_t size = bin::u32(pos);
|
||||
auto v = ownvec<ValType>::make_uninitialized(size);
|
||||
for (uint32_t i = 0; i < size; ++i) v[i] = bin::valtype(pos);
|
||||
return v;
|
||||
}
|
||||
|
||||
auto functype(const byte_t*& pos) -> own<FuncType> {
|
||||
assert(*pos == 0x60);
|
||||
++pos;
|
||||
auto params = bin::stacktype(pos);
|
||||
auto results = bin::stacktype(pos);
|
||||
return FuncType::make(std::move(params), std::move(results));
|
||||
}
|
||||
|
||||
auto globaltype(const byte_t*& pos) -> own<GlobalType> {
|
||||
auto content = bin::valtype(pos);
|
||||
auto mutability = bin::mutability(pos);
|
||||
return GlobalType::make(std::move(content), mutability);
|
||||
}
|
||||
|
||||
auto tabletype(const byte_t*& pos) -> own<TableType> {
|
||||
auto elem = bin::valtype(pos);
|
||||
auto limits = bin::limits(pos);
|
||||
return TableType::make(std::move(elem), limits);
|
||||
}
|
||||
|
||||
auto memorytype(const byte_t*& pos) -> own<MemoryType> {
|
||||
auto limits = bin::limits(pos);
|
||||
return MemoryType::make(limits);
|
||||
}
|
||||
|
||||
|
||||
void mutability_skip(const byte_t*& pos) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
void limits_skip(const byte_t*& pos) {
|
||||
auto tag = *pos++;
|
||||
bin::u32_skip(pos);
|
||||
if ((tag & 0x01) != 0) bin::u32_skip(pos);
|
||||
}
|
||||
|
||||
void valtype_skip(const byte_t*& pos) {
|
||||
// TODO(wasm+): support new value types
|
||||
++pos;
|
||||
}
|
||||
|
||||
void globaltype_skip(const byte_t*& pos) {
|
||||
bin::valtype_skip(pos);
|
||||
bin::mutability_skip(pos);
|
||||
}
|
||||
|
||||
void tabletype_skip(const byte_t*& pos) {
|
||||
bin::valtype_skip(pos);
|
||||
bin::limits_skip(pos);
|
||||
}
|
||||
|
||||
void memorytype_skip(const byte_t*& pos) {
|
||||
bin::limits_skip(pos);
|
||||
}
|
||||
|
||||
|
||||
// Expressions
|
||||
|
||||
void expr_skip(const byte_t*& pos) {
|
||||
switch (*pos++ & 0xff) {
|
||||
case 0x41: // i32.const
|
||||
case 0x42: // i64.const
|
||||
case 0x23: // get_global
|
||||
case 0xd2: { // ref.func
|
||||
bin::u32_skip(pos);
|
||||
} break;
|
||||
case 0x43: { // f32.const
|
||||
pos += 4;
|
||||
} break;
|
||||
case 0x44: { // f64.const
|
||||
pos += 8;
|
||||
} break;
|
||||
case 0xd0: { // ref.null
|
||||
} break;
|
||||
default: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
++pos; // end
|
||||
}
|
||||
|
||||
|
||||
// Sections
|
||||
|
||||
enum sec_t : byte_t {
|
||||
SEC_TYPE = 1,
|
||||
SEC_IMPORT = 2,
|
||||
SEC_FUNC = 3,
|
||||
SEC_TABLE = 4,
|
||||
SEC_MEMORY = 5,
|
||||
SEC_GLOBAL = 6,
|
||||
SEC_EXPORT = 7
|
||||
};
|
||||
|
||||
auto section(const vec<byte_t>& binary, bin::sec_t sec) -> const byte_t* {
|
||||
const byte_t* end = binary.get() + binary.size();
|
||||
const byte_t* pos = binary.get() + 8; // skip header
|
||||
while (pos < end && *pos++ != sec) {
|
||||
auto size = bin::u32(pos);
|
||||
pos += size;
|
||||
}
|
||||
if (pos == end) return nullptr;
|
||||
bin::u32_skip(pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
auto section_end(const vec<byte_t>& binary, bin::sec_t sec) -> const byte_t* {
|
||||
const byte_t* end = binary.get() + binary.size();
|
||||
const byte_t* pos = binary.get() + 8; // skip header
|
||||
while (pos < end && *pos != sec) {
|
||||
++pos;
|
||||
auto size = bin::u32(pos);
|
||||
pos += size;
|
||||
}
|
||||
if (pos == end) return nullptr;
|
||||
++pos;
|
||||
auto size = bin::u32(pos);
|
||||
return pos + size;
|
||||
}
|
||||
|
||||
|
||||
// Type section
|
||||
|
||||
auto types(const vec<byte_t>& binary) -> ownvec<FuncType> {
|
||||
auto pos = bin::section(binary, SEC_TYPE);
|
||||
if (pos == nullptr) return ownvec<FuncType>::make();
|
||||
size_t size = bin::u32(pos);
|
||||
// TODO(wasm+): support new deftypes
|
||||
auto v = ownvec<FuncType>::make_uninitialized(size);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
v[i] = bin::functype(pos);
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_TYPE));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Import section
|
||||
|
||||
auto imports(
|
||||
const vec<byte_t>& binary, const ownvec<FuncType>& types
|
||||
) -> ownvec<ImportType> {
|
||||
auto pos = bin::section(binary, SEC_IMPORT);
|
||||
if (pos == nullptr) return ownvec<ImportType>::make();
|
||||
size_t size = bin::u32(pos);
|
||||
auto v = ownvec<ImportType>::make_uninitialized(size);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
auto module = bin::name(pos);
|
||||
auto name = bin::name(pos);
|
||||
own<ExternType> type;
|
||||
switch (*pos++) {
|
||||
case 0x00: type = types[bin::u32(pos)]->copy(); break;
|
||||
case 0x01: type = bin::tabletype(pos); break;
|
||||
case 0x02: type = bin::memorytype(pos); break;
|
||||
case 0x03: type = bin::globaltype(pos); break;
|
||||
default: assert(false);
|
||||
}
|
||||
v[i] = ImportType::make(
|
||||
std::move(module), std::move(name), std::move(type));
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_IMPORT));
|
||||
return v;
|
||||
}
|
||||
|
||||
auto count(const ownvec<ImportType>& imports, ExternKind kind) -> uint32_t {
|
||||
uint32_t n = 0;
|
||||
for (uint32_t i = 0; i < imports.size(); ++i) {
|
||||
if (imports[i]->type()->kind() == kind) ++n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// Function section
|
||||
|
||||
auto funcs(
|
||||
const vec<byte_t>& binary,
|
||||
const ownvec<ImportType>& imports, const ownvec<FuncType>& types
|
||||
) -> ownvec<FuncType> {
|
||||
auto pos = bin::section(binary, SEC_FUNC);
|
||||
size_t size = pos != nullptr ? bin::u32(pos) : 0;
|
||||
auto v = ownvec<FuncType>::make_uninitialized(
|
||||
size + count(imports, ExternKind::FUNC));
|
||||
size_t j = 0;
|
||||
for (uint32_t i = 0; i < imports.size(); ++i) {
|
||||
auto et = imports[i]->type();
|
||||
if (et->kind() == ExternKind::FUNC) {
|
||||
v[j++] = et->func()->copy();
|
||||
}
|
||||
}
|
||||
if (pos != nullptr) {
|
||||
for (; j < v.size(); ++j) {
|
||||
v[j] = types[bin::u32(pos)]->copy();
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_FUNC));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Global section
|
||||
|
||||
auto globals(
|
||||
const vec<byte_t>& binary, const ownvec<ImportType>& imports
|
||||
) -> ownvec<GlobalType> {
|
||||
auto pos = bin::section(binary, SEC_GLOBAL);
|
||||
size_t size = pos != nullptr ? bin::u32(pos) : 0;
|
||||
auto v = ownvec<GlobalType>::make_uninitialized(
|
||||
size + count(imports, ExternKind::GLOBAL));
|
||||
size_t j = 0;
|
||||
for (uint32_t i = 0; i < imports.size(); ++i) {
|
||||
auto et = imports[i]->type();
|
||||
if (et->kind() == ExternKind::GLOBAL) {
|
||||
v[j++] = et->global()->copy();
|
||||
}
|
||||
}
|
||||
if (pos != nullptr) {
|
||||
for (; j < v.size(); ++j) {
|
||||
v[j] = bin::globaltype(pos);
|
||||
expr_skip(pos);
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_GLOBAL));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Table section
|
||||
|
||||
auto tables(
|
||||
const vec<byte_t>& binary, const ownvec<ImportType>& imports
|
||||
) -> ownvec<TableType> {
|
||||
auto pos = bin::section(binary, SEC_TABLE);
|
||||
size_t size = pos != nullptr ? bin::u32(pos) : 0;
|
||||
auto v = ownvec<TableType>::make_uninitialized(
|
||||
size + count(imports, ExternKind::TABLE));
|
||||
size_t j = 0;
|
||||
for (uint32_t i = 0; i < imports.size(); ++i) {
|
||||
auto et = imports[i]->type();
|
||||
if (et->kind() == ExternKind::TABLE) {
|
||||
v[j++] = et->table()->copy();
|
||||
}
|
||||
}
|
||||
if (pos != nullptr) {
|
||||
for (; j < v.size(); ++j) {
|
||||
v[j] = bin::tabletype(pos);
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_TABLE));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Memory section
|
||||
|
||||
auto memories(
|
||||
const vec<byte_t>& binary, const ownvec<ImportType>& imports
|
||||
) -> ownvec<MemoryType> {
|
||||
auto pos = bin::section(binary, SEC_MEMORY);
|
||||
size_t size = pos != nullptr ? bin::u32(pos) : 0;
|
||||
auto v = ownvec<MemoryType>::make_uninitialized(
|
||||
size + count(imports, ExternKind::MEMORY));
|
||||
size_t j = 0;
|
||||
for (uint32_t i = 0; i < imports.size(); ++i) {
|
||||
auto et = imports[i]->type();
|
||||
if (et->kind() == ExternKind::MEMORY) {
|
||||
v[j++] = et->memory()->copy();
|
||||
}
|
||||
}
|
||||
if (pos != nullptr) {
|
||||
for (; j < v.size(); ++j) {
|
||||
v[j] = bin::memorytype(pos);
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_MEMORY));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// Export section
|
||||
|
||||
auto exports(const vec<byte_t>& binary,
|
||||
const ownvec<FuncType>& funcs, const ownvec<GlobalType>& globals,
|
||||
const ownvec<TableType>& tables, const ownvec<MemoryType>& memories
|
||||
) -> ownvec<ExportType> {
|
||||
auto pos = bin::section(binary, SEC_EXPORT);
|
||||
if (pos == nullptr) return ownvec<ExportType>::make();
|
||||
size_t size = bin::u32(pos);
|
||||
auto exports = ownvec<ExportType>::make_uninitialized(size);
|
||||
for (uint32_t i = 0; i < size; ++i) {
|
||||
auto name = bin::name(pos);
|
||||
auto tag = *pos++;
|
||||
auto index = bin::u32(pos);
|
||||
own<ExternType> type;
|
||||
switch (tag) {
|
||||
case 0x00: type = funcs[index]->copy(); break;
|
||||
case 0x01: type = tables[index]->copy(); break;
|
||||
case 0x02: type = memories[index]->copy(); break;
|
||||
case 0x03: type = globals[index]->copy(); break;
|
||||
default: assert(false);
|
||||
}
|
||||
exports[i] = ExportType::make(std::move(name), std::move(type));
|
||||
}
|
||||
assert(pos = bin::section_end(binary, SEC_EXPORT));
|
||||
return exports;
|
||||
}
|
||||
|
||||
auto imports(const vec<byte_t>& binary) -> ownvec<ImportType> {
|
||||
return bin::imports(binary, bin::types(binary));
|
||||
}
|
||||
|
||||
auto exports(const vec<byte_t>& binary) -> ownvec<ExportType> {
|
||||
auto types = bin::types(binary);
|
||||
auto imports = bin::imports(binary, types);
|
||||
auto funcs = bin::funcs(binary, imports, types);
|
||||
auto globals = bin::globals(binary, imports);
|
||||
auto tables = bin::tables(binary, imports);
|
||||
auto memories = bin::memories(binary, imports);
|
||||
return bin::exports(binary, funcs, globals, tables, memories);
|
||||
}
|
||||
|
||||
} // namespace bin
|
||||
} // namespace wasm
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef __WASM_BIN_HH
|
||||
#define __WASM_BIN_HH
|
||||
|
||||
#include "wasm.hh"
|
||||
|
||||
namespace wasm {
|
||||
namespace bin {
|
||||
|
||||
auto u32_size(uint32_t) -> size_t;
|
||||
auto u64_size(uint64_t) -> size_t;
|
||||
void encode_u32(char*& ptr, uint32_t n);
|
||||
void encode_u64(char*& ptr, uint64_t n);
|
||||
auto u32(const byte_t*& pos) -> uint32_t;
|
||||
auto u64(const byte_t*& pos) -> uint64_t;
|
||||
|
||||
auto wrapper(const FuncType*) -> vec<byte_t>;
|
||||
auto wrapper(const GlobalType*) -> vec<byte_t>;
|
||||
|
||||
auto imports(const vec<byte_t>& binary) -> ownvec<ImportType>;
|
||||
auto exports(const vec<byte_t>& binary) -> ownvec<ExportType>;
|
||||
|
||||
} // namespace bin
|
||||
} // namespace wasm
|
||||
|
||||
#endif // #ifdef __WASM_BIN_HH
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,443 +0,0 @@
|
||||
#include "wasm-v8-lowlevel.hh"
|
||||
|
||||
// TODO(v8): if we don't include these, api.h does not compile
|
||||
#include "objects/objects.h"
|
||||
#include "objects/bigint.h"
|
||||
#include "objects/managed.h"
|
||||
#include "objects/module.h"
|
||||
#include "objects/shared-function-info.h"
|
||||
#include "objects/templates.h"
|
||||
#include "objects/fixed-array.h"
|
||||
#include "objects/ordered-hash-table.h"
|
||||
#include "objects/js-promise.h"
|
||||
#include "objects/js-collection.h"
|
||||
|
||||
#include "api/api.h"
|
||||
#include "api/api-inl.h"
|
||||
#include "wasm/wasm-objects.h"
|
||||
#include "wasm/wasm-objects-inl.h"
|
||||
#include "wasm/wasm-serialization.h"
|
||||
|
||||
|
||||
namespace v8 {
|
||||
namespace wasm {
|
||||
|
||||
|
||||
// Objects
|
||||
|
||||
auto object_isolate(v8::Local<v8::Object> obj) -> v8::Isolate* {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return reinterpret_cast<v8::Isolate*>(v8_obj->GetIsolate());
|
||||
}
|
||||
|
||||
auto object_isolate(const v8::Persistent<v8::Object>& obj) -> v8::Isolate* {
|
||||
struct FakePersistent { v8::Object* val; };
|
||||
auto v8_obj = reinterpret_cast<const FakePersistent*>(&obj)->val;
|
||||
return v8_obj->GetIsolate();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
auto object_handle(T v8_obj) -> v8::internal::Handle<T> {
|
||||
return handle(v8_obj, v8_obj.GetIsolate());
|
||||
}
|
||||
|
||||
|
||||
auto object_is_module(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsWasmModuleObject();
|
||||
}
|
||||
|
||||
auto object_is_instance(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsWasmInstanceObject();
|
||||
}
|
||||
|
||||
auto object_is_func(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_obj);
|
||||
}
|
||||
|
||||
auto object_is_global(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsWasmGlobalObject();
|
||||
}
|
||||
|
||||
auto object_is_table(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsWasmTableObject();
|
||||
}
|
||||
|
||||
auto object_is_memory(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsWasmMemoryObject();
|
||||
}
|
||||
|
||||
auto object_is_error(v8::Local<v8::Object> obj) -> bool {
|
||||
auto v8_obj = v8::Utils::OpenHandle(*obj);
|
||||
return v8_obj->IsJSError();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Foreign pointers
|
||||
|
||||
auto foreign_new(v8::Isolate* isolate, void* ptr) -> v8::Local<v8::Value> {
|
||||
auto foreign = v8::FromCData(
|
||||
reinterpret_cast<v8::internal::Isolate*>(isolate),
|
||||
reinterpret_cast<v8::internal::Address>(ptr)
|
||||
);
|
||||
return v8::Utils::ToLocal(foreign);
|
||||
}
|
||||
|
||||
auto foreign_get(v8::Local<v8::Value> val) -> void* {
|
||||
auto foreign = v8::Utils::OpenHandle(*val);
|
||||
if (!foreign->IsForeign()) return nullptr;
|
||||
auto addr = v8::ToCData<v8::internal::Address>(*foreign);
|
||||
return reinterpret_cast<void*>(addr);
|
||||
}
|
||||
|
||||
|
||||
struct ManagedData {
|
||||
ManagedData(void* info, void (*finalizer)(void*)) :
|
||||
info(info), finalizer(finalizer) {}
|
||||
|
||||
~ManagedData() {
|
||||
if (finalizer) (*finalizer)(info);
|
||||
}
|
||||
|
||||
void* info;
|
||||
void (*finalizer)(void*);
|
||||
};
|
||||
|
||||
auto managed_new(v8::Isolate* isolate, void* ptr, void (*finalizer)(void*)) -> v8::Local<v8::Value> {
|
||||
assert(ptr);
|
||||
auto managed = v8::internal::Managed<ManagedData>::FromUniquePtr(
|
||||
reinterpret_cast<v8::internal::Isolate*>(isolate), sizeof(ManagedData),
|
||||
std::unique_ptr<ManagedData>(new ManagedData(ptr, finalizer))
|
||||
);
|
||||
return v8::Utils::ToLocal(managed);
|
||||
}
|
||||
|
||||
auto managed_get(v8::Local<v8::Value> val) -> void* {
|
||||
auto v8_val = v8::Utils::OpenHandle(*val);
|
||||
if (!v8_val->IsForeign()) return nullptr;
|
||||
auto managed =
|
||||
v8::internal::Handle<v8::internal::Managed<ManagedData>>::cast(v8_val);
|
||||
return managed->raw()->info;
|
||||
}
|
||||
|
||||
|
||||
// Types
|
||||
|
||||
auto v8_valtype_to_wasm(v8::internal::wasm::ValueType v8_valtype) -> val_kind_t {
|
||||
switch (v8_valtype) {
|
||||
case v8::internal::wasm::kWasmI32: return I32;
|
||||
case v8::internal::wasm::kWasmI64: return I64;
|
||||
case v8::internal::wasm::kWasmF32: return F32;
|
||||
case v8::internal::wasm::kWasmF64: return F64;
|
||||
case v8::internal::wasm::kWasmAnyRef: return ANYREF;
|
||||
case v8::internal::wasm::kWasmAnyFunc: return FUNCREF;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
auto func_type_param_arity(v8::Local<v8::Object> function) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
|
||||
auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
|
||||
v8::internal::wasm::FunctionSig* sig =
|
||||
v8_function->instance().module()->functions[v8_function->function_index()].sig;
|
||||
return static_cast<uint32_t>(sig->parameter_count());
|
||||
}
|
||||
|
||||
auto func_type_result_arity(v8::Local<v8::Object> function) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
|
||||
auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
|
||||
v8::internal::wasm::FunctionSig* sig =
|
||||
v8_function->instance().module()->functions[v8_function->function_index()].sig;
|
||||
return static_cast<uint32_t>(sig->return_count());
|
||||
}
|
||||
|
||||
auto func_type_param(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
|
||||
auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
|
||||
v8::internal::wasm::FunctionSig* sig =
|
||||
v8_function->instance().module()->functions[v8_function->function_index()].sig;
|
||||
return v8_valtype_to_wasm(sig->GetParam(i));
|
||||
}
|
||||
|
||||
auto func_type_result(v8::Local<v8::Object> function, size_t i) -> val_kind_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(function);
|
||||
auto v8_function = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_object);
|
||||
v8::internal::wasm::FunctionSig* sig =
|
||||
v8_function->instance().module()->functions[v8_function->function_index()].sig;
|
||||
return v8_valtype_to_wasm(sig->GetReturn(i));
|
||||
}
|
||||
|
||||
auto global_type_content(v8::Local<v8::Object> global) -> val_kind_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_valtype_to_wasm(v8_global->type());
|
||||
}
|
||||
|
||||
auto global_type_mutable(v8::Local<v8::Object> global) -> bool {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_global->is_mutable();
|
||||
}
|
||||
|
||||
auto table_type_min(v8::Local<v8::Object> table) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
return v8_table->current_length();
|
||||
}
|
||||
|
||||
auto table_type_max(v8::Local<v8::Object> table) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
auto v8_max_obj = v8_table->maximum_length();
|
||||
uint32_t max;
|
||||
return v8_max_obj.ToUint32(&max) ? max : 0xffffffffu;
|
||||
}
|
||||
|
||||
auto memory_type_min(v8::Local<v8::Object> memory) -> uint32_t {
|
||||
return memory_size(memory);
|
||||
}
|
||||
|
||||
auto memory_type_max(v8::Local<v8::Object> memory) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
|
||||
auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
|
||||
return v8_memory->has_maximum_pages() ? v8_memory->maximum_pages() : 0xffffffffu;
|
||||
}
|
||||
|
||||
|
||||
// Modules
|
||||
|
||||
auto module_binary_size(v8::Local<v8::Object> module) -> size_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
|
||||
auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
|
||||
return v8_module->native_module()->wire_bytes().size();
|
||||
}
|
||||
|
||||
auto module_binary(v8::Local<v8::Object> module) -> const char* {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
|
||||
auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
|
||||
return reinterpret_cast<const char*>(v8_module->native_module()->wire_bytes().begin());
|
||||
}
|
||||
|
||||
auto module_serialize_size(v8::Local<v8::Object> module) -> size_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
|
||||
auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
|
||||
v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
|
||||
return serializer.GetSerializedNativeModuleSize();
|
||||
}
|
||||
|
||||
auto module_serialize(v8::Local<v8::Object> module, char* buffer, size_t size) -> bool {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(module);
|
||||
auto v8_module = v8::internal::Handle<v8::internal::WasmModuleObject>::cast(v8_object);
|
||||
v8::internal::wasm::WasmSerializer serializer(v8_module->native_module());
|
||||
return serializer.SerializeNativeModule({reinterpret_cast<uint8_t*>(buffer), size});
|
||||
}
|
||||
|
||||
auto module_deserialize(
|
||||
v8::Isolate* isolate,
|
||||
const char* binary, size_t binary_size,
|
||||
const char* buffer, size_t buffer_size
|
||||
) -> v8::MaybeLocal<v8::Object> {
|
||||
auto v8_isolate = reinterpret_cast<v8::internal::Isolate*>(isolate);
|
||||
auto maybe_v8_module =
|
||||
v8::internal::wasm::DeserializeNativeModule(v8_isolate,
|
||||
{reinterpret_cast<const uint8_t*>(buffer), buffer_size},
|
||||
{reinterpret_cast<const uint8_t*>(binary), binary_size});
|
||||
if (maybe_v8_module.is_null()) return v8::MaybeLocal<v8::Object>();
|
||||
auto v8_module = v8::internal::Handle<v8::internal::JSObject>::cast(maybe_v8_module.ToHandleChecked());
|
||||
return v8::MaybeLocal<v8::Object>(v8::Utils::ToLocal(v8_module));
|
||||
}
|
||||
|
||||
|
||||
// Instances
|
||||
|
||||
auto instance_module(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
|
||||
auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
|
||||
auto v8_module = object_handle(v8::internal::JSObject::cast(v8_instance->module_object()));
|
||||
return v8::Utils::ToLocal(v8_module);
|
||||
}
|
||||
|
||||
auto instance_exports(v8::Local<v8::Object> instance) -> v8::Local<v8::Object> {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(instance);
|
||||
auto v8_instance = v8::internal::Handle<v8::internal::WasmInstanceObject>::cast(v8_object);
|
||||
auto v8_exports = object_handle(v8_instance->exports_object());
|
||||
return v8::Utils::ToLocal(v8_exports);
|
||||
}
|
||||
|
||||
|
||||
// Externals
|
||||
|
||||
auto extern_kind(v8::Local<v8::Object> external) -> extern_kind_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(external);
|
||||
|
||||
if (v8::internal::WasmExportedFunction::IsWasmExportedFunction(*v8_object)) return EXTERN_FUNC;
|
||||
if (v8_object->IsWasmGlobalObject()) return EXTERN_GLOBAL;
|
||||
if (v8_object->IsWasmTableObject()) return EXTERN_TABLE;
|
||||
if (v8_object->IsWasmMemoryObject()) return EXTERN_MEMORY;
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
// Functions
|
||||
|
||||
auto func_instance(v8::Local<v8::Function> function) -> v8::Local<v8::Object> {
|
||||
auto v8_function = v8::Utils::OpenHandle(*function);
|
||||
auto v8_func = v8::internal::Handle<v8::internal::WasmExportedFunction>::cast(v8_function);
|
||||
auto v8_instance = object_handle(v8::internal::JSObject::cast(v8_func->instance()));
|
||||
return v8::Utils::ToLocal(v8_instance);
|
||||
}
|
||||
|
||||
|
||||
// Globals
|
||||
|
||||
auto global_get_i32(v8::Local<v8::Object> global) -> int32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_global->GetI32();
|
||||
}
|
||||
auto global_get_i64(v8::Local<v8::Object> global) -> int64_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_global->GetI64();
|
||||
}
|
||||
auto global_get_f32(v8::Local<v8::Object> global) -> float {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_global->GetF32();
|
||||
}
|
||||
auto global_get_f64(v8::Local<v8::Object> global) -> double {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8_global->GetF64();
|
||||
}
|
||||
auto global_get_ref(v8::Local<v8::Object> global) -> v8::Local<v8::Value> {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
return v8::Utils::ToLocal(v8_global->GetRef());
|
||||
}
|
||||
|
||||
void global_set_i32(v8::Local<v8::Object> global, int32_t val) {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
v8_global->SetI32(val);
|
||||
}
|
||||
void global_set_i64(v8::Local<v8::Object> global, int64_t val) {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
v8_global->SetI64(val);
|
||||
}
|
||||
void global_set_f32(v8::Local<v8::Object> global, float val) {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
v8_global->SetF32(val);
|
||||
}
|
||||
void global_set_f64(v8::Local<v8::Object> global, double val) {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
v8_global->SetF64(val);
|
||||
}
|
||||
void global_set_ref(v8::Local<v8::Object> global, v8::Local<v8::Value> val) {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(global);
|
||||
auto v8_global = v8::internal::Handle<v8::internal::WasmGlobalObject>::cast(v8_object);
|
||||
v8_global->SetAnyRef(v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(val));
|
||||
}
|
||||
|
||||
|
||||
// Tables
|
||||
|
||||
auto table_get(v8::Local<v8::Object> table, size_t index) -> v8::MaybeLocal<v8::Value> {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
// TODO(v8): This should happen in WasmTableObject::Get.
|
||||
if (index > v8_table->current_length()) return v8::MaybeLocal<v8::Value>();
|
||||
|
||||
v8::internal::Handle<v8::internal::Object> v8_value =
|
||||
v8::internal::WasmTableObject::Get(
|
||||
v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(index));
|
||||
return v8::Utils::ToLocal(v8::internal::Handle<v8::internal::Object>::cast(v8_value));
|
||||
}
|
||||
|
||||
auto table_set(
|
||||
v8::Local<v8::Object> table, size_t index, v8::Local<v8::Value> value
|
||||
) -> bool {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
auto v8_value = v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(value);
|
||||
// TODO(v8): This should happen in WasmTableObject::Set.
|
||||
if (index >= v8_table->current_length()) return false;
|
||||
|
||||
{ v8::TryCatch handler(table->GetIsolate());
|
||||
v8::internal::WasmTableObject::Set(v8_table->GetIsolate(), v8_table,
|
||||
static_cast<uint32_t>(index), v8_value);
|
||||
if (handler.HasCaught()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto table_size(v8::Local<v8::Object> table) -> size_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
return v8_table->current_length();
|
||||
}
|
||||
|
||||
auto table_grow(
|
||||
v8::Local<v8::Object> table, size_t delta, v8::Local<v8::Value> init
|
||||
) -> bool {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(table);
|
||||
auto v8_table = v8::internal::Handle<v8::internal::WasmTableObject>::cast(v8_object);
|
||||
if (delta > 0xfffffffflu) return false;
|
||||
auto old_size = v8_table->current_length();
|
||||
auto new_size = old_size + static_cast<uint32_t>(delta);
|
||||
// TODO(v8): This should happen in WasmTableObject::Grow.
|
||||
if (new_size > table_type_max(table)) return false;
|
||||
|
||||
{ v8::TryCatch handler(table->GetIsolate());
|
||||
v8::internal::WasmTableObject::Grow(
|
||||
v8_table->GetIsolate(), v8_table, static_cast<uint32_t>(delta),
|
||||
v8::Utils::OpenHandle<v8::Value, v8::internal::Object>(init));
|
||||
if (handler.HasCaught()) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Memory
|
||||
|
||||
auto memory_data(v8::Local<v8::Object> memory) -> char* {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
|
||||
auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
|
||||
return reinterpret_cast<char*>(v8_memory->array_buffer().backing_store());
|
||||
}
|
||||
|
||||
auto memory_data_size(v8::Local<v8::Object> memory)-> size_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
|
||||
auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
|
||||
return v8_memory->array_buffer().byte_length();
|
||||
}
|
||||
|
||||
auto memory_size(v8::Local<v8::Object> memory) -> uint32_t {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
|
||||
auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
|
||||
return static_cast<uint32_t>(
|
||||
v8_memory->array_buffer().byte_length() / v8::internal::wasm::kWasmPageSize);
|
||||
}
|
||||
|
||||
auto memory_grow(v8::Local<v8::Object> memory, uint32_t delta) -> bool {
|
||||
auto v8_object = v8::Utils::OpenHandle<v8::Object, v8::internal::JSReceiver>(memory);
|
||||
auto v8_memory = v8::internal::Handle<v8::internal::WasmMemoryObject>::cast(v8_object);
|
||||
auto old = v8::internal::WasmMemoryObject::Grow(
|
||||
v8_memory->GetIsolate(), v8_memory, delta);
|
||||
return old != -1;
|
||||
}
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace v8
|
||||
@@ -1,79 +0,0 @@
|
||||
#ifndef __WASM_V8_LOWLEVEL_HH
|
||||
#define __WASM_V8_LOWLEVEL_HH
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace wasm {
|
||||
|
||||
auto object_isolate(v8::Local<v8::Object>) -> v8::Isolate*;
|
||||
auto object_isolate(const v8::Persistent<v8::Object>&) -> v8::Isolate*;
|
||||
|
||||
auto object_is_module(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_instance(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_func(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_global(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_table(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_memory(v8::Local<v8::Object>) -> bool;
|
||||
auto object_is_error(v8::Local<v8::Object>) -> bool;
|
||||
|
||||
auto foreign_new(v8::Isolate*, void*) -> v8::Local<v8::Value>;
|
||||
auto foreign_get(v8::Local<v8::Value>) -> void*;
|
||||
|
||||
auto managed_new(v8::Isolate*, void*, void (*)(void*)) -> v8::Local<v8::Value>;
|
||||
auto managed_get(v8::Local<v8::Value>) -> void*;
|
||||
|
||||
enum val_kind_t { I32, I64, F32, F64, ANYREF = 128, FUNCREF };
|
||||
auto func_type_param_arity(v8::Local<v8::Object> global) -> uint32_t;
|
||||
auto func_type_result_arity(v8::Local<v8::Object> global) -> uint32_t;
|
||||
auto func_type_param(v8::Local<v8::Object> global, size_t) -> val_kind_t;
|
||||
auto func_type_result(v8::Local<v8::Object> global, size_t) -> val_kind_t;
|
||||
|
||||
auto global_type_content(v8::Local<v8::Object> global) -> val_kind_t;
|
||||
auto global_type_mutable(v8::Local<v8::Object> global) -> bool;
|
||||
|
||||
auto table_type_min(v8::Local<v8::Object> table) -> uint32_t;
|
||||
auto table_type_max(v8::Local<v8::Object> table) -> uint32_t;
|
||||
|
||||
auto memory_type_min(v8::Local<v8::Object> memory) -> uint32_t;
|
||||
auto memory_type_max(v8::Local<v8::Object> memory) -> uint32_t;
|
||||
|
||||
auto module_binary_size(v8::Local<v8::Object> module) -> size_t;
|
||||
auto module_binary(v8::Local<v8::Object> module) -> const char*;
|
||||
auto module_serialize_size(v8::Local<v8::Object> module) -> size_t;
|
||||
auto module_serialize(v8::Local<v8::Object> module, char*, size_t) -> bool;
|
||||
auto module_deserialize(v8::Isolate*, const char*, size_t, const char*, size_t) -> v8::MaybeLocal<v8::Object>;
|
||||
|
||||
auto instance_module(v8::Local<v8::Object> instance) -> v8::Local<v8::Object>;
|
||||
auto instance_exports(v8::Local<v8::Object> instance) -> v8::Local<v8::Object>;
|
||||
|
||||
enum extern_kind_t { EXTERN_FUNC, EXTERN_GLOBAL, EXTERN_TABLE, EXTERN_MEMORY };
|
||||
auto extern_kind(v8::Local<v8::Object> external) -> extern_kind_t;
|
||||
|
||||
auto func_instance(v8::Local<v8::Function>) -> v8::Local<v8::Object>;
|
||||
|
||||
auto global_get_i32(v8::Local<v8::Object> global) -> int32_t;
|
||||
auto global_get_i64(v8::Local<v8::Object> global) -> int64_t;
|
||||
auto global_get_f32(v8::Local<v8::Object> global) -> float;
|
||||
auto global_get_f64(v8::Local<v8::Object> global) -> double;
|
||||
auto global_get_ref(v8::Local<v8::Object> global) -> v8::Local<v8::Value>;
|
||||
void global_set_i32(v8::Local<v8::Object> global, int32_t);
|
||||
void global_set_i64(v8::Local<v8::Object> global, int64_t);
|
||||
void global_set_f32(v8::Local<v8::Object> global, float);
|
||||
void global_set_f64(v8::Local<v8::Object> global, double);
|
||||
void global_set_ref(v8::Local<v8::Object> global, v8::Local<v8::Value>);
|
||||
|
||||
auto table_get(v8::Local<v8::Object> table, size_t index) -> v8::MaybeLocal<v8::Value>;
|
||||
auto table_set(v8::Local<v8::Object> table, size_t index, v8::Local<v8::Value>) -> bool;
|
||||
auto table_size(v8::Local<v8::Object> table) -> size_t;
|
||||
auto table_grow(v8::Local<v8::Object> table, size_t delta, v8::Local<v8::Value>) -> bool;
|
||||
|
||||
auto memory_data(v8::Local<v8::Object> memory) -> char*;
|
||||
auto memory_data_size(v8::Local<v8::Object> memory)-> size_t;
|
||||
auto memory_size(v8::Local<v8::Object> memory) -> uint32_t;
|
||||
auto memory_grow(v8::Local<v8::Object> memory, uint32_t delta) -> bool;
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace v8
|
||||
|
||||
#endif // #define __WASM_V8_LOWLEVEL_HH
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user