Revert "[vm] Wasm function imports"

This reverts commit 7a24aec8f4.

Reason for revert: debug-mode gen_snapshot crashes on all programs

Original change's description:
> [vm] Wasm function imports
> 
> Bug: https://github.com/dart-lang/sdk/issues/37882
> Change-Id: Ia8aa9a87803d5e8b899ddab5479b8cd93e03fd71
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118204
> Commit-Queue: Liam Appelbe <liama@google.com>
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>

TBR=rmacnak@google.com,alexmarkov@google.com,liama@google.com

Change-Id: Ib5d348e25854af010b1d8a64a87406da443981df
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: https://github.com/dart-lang/sdk/issues/37882
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119143
Reviewed-by: Samir Jindel <sjindel@google.com>
Commit-Queue: Samir Jindel <sjindel@google.com>
This commit is contained in:
Samir Jindel 2019-09-27 12:22:58 +00:00 committed by commit-bot@chromium.org
parent ee1ab89987
commit a7cb8ee88b
11 changed files with 17 additions and 478 deletions

View file

@ -85,54 +85,6 @@ static bool ToWasmValue(const Number& value,
}
}
static Dart_Handle ToWasmValue(Dart_Handle value,
wasmer_value_tag type,
wasmer_value* out) {
switch (type) {
case wasmer_value_tag::WASM_I32: {
int64_t i64;
Dart_Handle result = Dart_IntegerToInt64(value, &i64);
out->I32 = i64;
if (out->I32 != i64) {
return Dart_NewApiError("Int doesn't fit into 32-bits");
}
return result;
}
case wasmer_value_tag::WASM_I64:
return Dart_IntegerToInt64(value, &out->I64);
case wasmer_value_tag::WASM_F32: {
double f64;
Dart_Handle result = Dart_DoubleValue(value, &f64);
out->F32 = f64;
return result;
}
case wasmer_value_tag::WASM_F64:
return Dart_DoubleValue(value, &out->F64);
default:
FATAL("Unknown WASM type");
return nullptr;
}
}
static bool ToWasmValueTag(classid_t type, wasmer_value_tag* out) {
switch (type) {
case kWasmInt32Cid:
*out = wasmer_value_tag::WASM_I32;
return true;
case kWasmInt64Cid:
*out = wasmer_value_tag::WASM_I64;
return true;
case kWasmFloatCid:
*out = wasmer_value_tag::WASM_F32;
return true;
case kWasmDoubleCid:
*out = wasmer_value_tag::WASM_F64;
return true;
default:
return false;
}
}
static RawObject* ToDartObject(wasmer_value_t ret) {
switch (ret.tag) {
case wasmer_value_tag::WASM_I32:
@ -149,22 +101,6 @@ static RawObject* ToDartObject(wasmer_value_t ret) {
}
}
static Dart_Handle ToDartApiObject(wasmer_value value, wasmer_value_tag type) {
switch (type) {
case wasmer_value_tag::WASM_I32:
return Dart_NewInteger(value.I32);
case wasmer_value_tag::WASM_I64:
return Dart_NewInteger(value.I64);
case wasmer_value_tag::WASM_F32:
return Dart_NewDouble(value.F32);
case wasmer_value_tag::WASM_F64:
return Dart_NewDouble(value.F64);
default:
FATAL("Unknown WASM type");
return nullptr;
}
}
RawExternalTypedData* WasmMemoryToExternalTypedData(wasmer_memory_t* memory) {
uint8_t* data = wasmer_memory_data(memory);
uint32_t size = wasmer_memory_data_length(memory);
@ -222,41 +158,6 @@ RawString* DescribeModule(const wasmer_module_t* module) {
return String::New(desc.str().c_str());
}
class WasmImports;
struct WasmFunctionImport {
WasmImports* imports;
std::unique_ptr<wasmer_value_tag[]> args;
intptr_t num_args;
wasmer_value_tag ret;
intptr_t num_rets;
int64_t fn_id;
wasmer_import_func_t* wasm_fn;
wasmer_trampoline_buffer_t* buffer;
WasmFunctionImport(WasmImports* imports_,
std::unique_ptr<wasmer_value_tag[]> args_,
intptr_t num_args_,
wasmer_value_tag ret_,
intptr_t num_rets_,
int64_t fn_id_)
: imports(imports_),
args(std::move(args_)),
num_args(num_args_),
ret(ret_),
num_rets(num_rets_),
fn_id(fn_id),
wasm_fn(nullptr),
buffer(nullptr) {}
~WasmFunctionImport() {
wasmer_trampoline_buffer_destroy(buffer);
wasmer_import_func_destroy(wasm_fn);
}
};
extern "C" {
int64_t Trampoline(void* context, int64_t* args);
}
class WasmImports {
public:
explicit WasmImports(std::unique_ptr<char[]> module_name)
@ -266,15 +167,11 @@ class WasmImports {
for (wasmer_global_t* global : _globals) {
wasmer_global_destroy(global);
}
for (WasmFunctionImport* fn_imp : _functions) {
delete fn_imp;
}
for (const char* name : _import_names) {
delete[] name;
}
}
void SetHandle(FinalizablePersistentHandle* handle) { _handle = handle; }
size_t NumImports() const { return _imports.length(); }
wasmer_import_t* RawImports() { return _imports.data(); }
@ -292,82 +189,10 @@ class WasmImports {
global;
}
void AddFunction(std::unique_ptr<char[]> name,
int64_t fn_id,
std::unique_ptr<wasmer_value_tag[]> args,
intptr_t num_args,
wasmer_value_tag ret,
intptr_t num_rets) {
// Trampoline args include the context pointer.
const intptr_t num_trampoline_args = num_args + 1;
WasmFunctionImport* fn_imp = new WasmFunctionImport(
this, std::move(args), num_args, ret, num_rets, fn_id);
_functions.Add(fn_imp);
wasmer_trampoline_buffer_builder_t* builder =
wasmer_trampoline_buffer_builder_new();
uintptr_t trampoline_id =
wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
builder,
reinterpret_cast<wasmer_trampoline_callable_t*>(Trampoline),
reinterpret_cast<void*>(fn_imp), num_trampoline_args);
fn_imp->buffer = wasmer_trampoline_buffer_builder_build(builder);
const wasmer_trampoline_callable_t* trampoline =
wasmer_trampoline_buffer_get_trampoline(fn_imp->buffer, trampoline_id);
fn_imp->wasm_fn = wasmer_import_func_new(
reinterpret_cast<void (*)(void*)>(
const_cast<wasmer_trampoline_callable_t*>(trampoline)),
fn_imp->args.get(), num_args, &ret, num_rets);
AddImport(std::move(name), wasmer_import_export_kind::WASM_FUNCTION)->func =
fn_imp->wasm_fn;
}
int64_t CallImportedFunction(WasmFunctionImport* fn_imp, int64_t* raw_args) {
wasmer_value* wasm_args = reinterpret_cast<wasmer_value*>(raw_args);
Dart_Handle fn_id = Dart_NewInteger(fn_imp->fn_id);
Dart_Handle closure =
Dart_Invoke(Dart_HandleFromWeakPersistent(_handle->apiHandle()),
Dart_NewStringFromCString("getFunction"), 1, &fn_id);
if (Dart_IsError(closure)) {
Dart_ThrowException(closure);
UNREACHABLE();
}
Dart_Handle result;
{
auto args =
std::unique_ptr<Dart_Handle[]>(new Dart_Handle[fn_imp->num_args]);
for (intptr_t i = 0; i < fn_imp->num_args; ++i) {
args[i] = ToDartApiObject(wasm_args[i], fn_imp->args[i]);
}
result = Dart_InvokeClosure(closure, fn_imp->num_args, args.get());
}
if (Dart_IsError(result)) {
Dart_ThrowException(result);
UNREACHABLE();
}
if (fn_imp->num_rets == 0) {
// Wasmer ignores the result of this function if it expects no results,
// so skip the converters below (we get errors if we run them).
return 0;
}
wasmer_value wasm_result;
result = ToWasmValue(result, fn_imp->ret, &wasm_result);
if (Dart_IsError(result)) {
Dart_ThrowException(result);
UNREACHABLE();
}
return wasm_result.I64;
}
private:
FinalizablePersistentHandle* _handle;
std::unique_ptr<char[]> _module_name;
MallocGrowableArray<const char*> _import_names;
MallocGrowableArray<wasmer_global_t*> _globals;
MallocGrowableArray<WasmFunctionImport*> _functions;
MallocGrowableArray<wasmer_import_t> _imports;
wasmer_import_export_value* AddImport(std::unique_ptr<char[]> name,
@ -387,14 +212,6 @@ class WasmImports {
DISALLOW_COPY_AND_ASSIGN(WasmImports);
};
extern "C" {
int64_t Trampoline(void* context, int64_t* args) {
WasmFunctionImport* fn_imp = reinterpret_cast<WasmFunctionImport*>(context);
// Skip the first arg (it's another context pointer).
return fn_imp->imports->CallImportedFunction(fn_imp, args + 1);
}
}
class WasmFunction {
public:
WasmFunction(MallocGrowableArray<classid_t> args,
@ -651,9 +468,8 @@ DEFINE_NATIVE_ENTRY(Wasm_initImports, 0, 2) {
WasmImports* imports = new WasmImports(ToUTF8(module_name));
imp_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(imports));
imports->SetHandle(FinalizablePersistentHandle::New(
thread->isolate(), imp_wrap, imports, Finalize<WasmImports>,
sizeof(WasmImports)));
FinalizablePersistentHandle::New(thread->isolate(), imp_wrap, imports,
Finalize<WasmImports>, sizeof(WasmImports));
return Object::null();
}
@ -689,9 +505,8 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
wasmer_value_t wasm_value;
if (!ToWasmValue(value, type.type_class_id(), &wasm_value)) {
Exceptions::ThrowArgumentError(String::Handle(
zone, String::NewFormatted(
"Can't convert dart value to WASM global variable")));
Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
"Can't convert dart value to WASM global variable")));
UNREACHABLE();
}
@ -700,53 +515,6 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
return Object::null();
}
DEFINE_NATIVE_ENTRY(Wasm_addFunctionImport, 0, 4) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, imp_wrap, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, fn_id, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Type, fn_type, arguments->NativeArgAt(3));
ASSERT(imp_wrap.NumNativeFields() == 1);
Function& sig = Function::Handle(zone, fn_type.signature());
classid_t ret = AbstractType::Handle(zone, sig.result_type()).type_class_id();
intptr_t num_rets = ret == kWasmVoidCid ? 0 : 1;
wasmer_value_tag wasm_ret = wasmer_value_tag::WASM_I64;
if (num_rets != 0) {
if (!ToWasmValueTag(ret, &wasm_ret)) {
Exceptions::ThrowArgumentError(String::Handle(
zone, String::NewFormatted("Return type is not a valid WASM type")));
UNREACHABLE();
}
}
Array& args = Array::Handle(zone, sig.parameter_types());
AbstractType& arg_type = AbstractType::Handle(zone);
intptr_t first_arg_index = sig.NumImplicitParameters();
intptr_t num_args = args.Length() - first_arg_index;
auto wasm_args =
std::unique_ptr<wasmer_value_tag[]>(new wasmer_value_tag[num_args]);
for (intptr_t i = 0; i < num_args; ++i) {
arg_type ^= args.At(i + first_arg_index);
classid_t dart_arg = arg_type.type_class_id();
if (!ToWasmValueTag(dart_arg, &wasm_args[i])) {
wasm_args.reset();
Exceptions::ThrowArgumentError(String::Handle(
zone, String::NewFormatted(
"Type of arg %" Pd " is not a valid WASM type", i)));
UNREACHABLE();
}
}
WasmImports* imports =
reinterpret_cast<WasmImports*>(imp_wrap.GetNativeField(0));
imports->AddFunction(ToUTF8(name), fn_id.AsInt64Value(), std::move(wasm_args),
num_args, wasm_ret, num_rets);
return Object::null();
}
DEFINE_NATIVE_ENTRY(Wasm_initMemory, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, init, arguments->NativeArgAt(1));
@ -842,16 +610,15 @@ DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
String& error = String::Handle(zone);
{
Function& sig = Function::Handle(zone, fn_type.signature());
Array& args = Array::Handle(zone, sig.parameter_types());
AbstractType& arg_type = AbstractType::Handle(zone);
Function& sig = Function::Handle(fn_type.signature());
Array& args = Array::Handle(sig.parameter_types());
MallocGrowableArray<classid_t> dart_args;
for (intptr_t i = sig.NumImplicitParameters(); i < args.Length(); ++i) {
arg_type ^= args.At(i);
dart_args.Add(arg_type.type_class_id());
dart_args.Add(
AbstractType::Cast(Object::Handle(args.At(i))).type_class_id());
}
classid_t dart_ret =
AbstractType::Handle(zone, sig.result_type()).type_class_id();
AbstractType::Handle(sig.result_type()).type_class_id();
std::unique_ptr<char[]> name_raw = ToUTF8(name);
fn = inst->GetFunction(name_raw.get(), dart_args, dart_ret, &error);
@ -876,21 +643,19 @@ DEFINE_NATIVE_ENTRY(Wasm_callFunction, 0, 2) {
WasmFunction* fn = reinterpret_cast<WasmFunction*>(fn_wrap.GetNativeField(0));
if (args.Length() != fn->args().length()) {
Exceptions::ThrowArgumentError(String::Handle(
zone, String::NewFormatted("Wrong number of args. Expected %" Pu
" but found %" Pd ".",
fn->args().length(), args.Length())));
Exceptions::ThrowArgumentError(String::Handle(String::NewFormatted(
"Wrong number of args. Expected %" Pu " but found %" Pd ".",
fn->args().length(), args.Length())));
UNREACHABLE();
}
auto params = std::unique_ptr<wasmer_value_t[]>(
new wasmer_value_t[fn->args().length()]);
Number& arg_num = Number::Handle(zone);
for (intptr_t i = 0; i < args.Length(); ++i) {
arg_num ^= args.At(i);
if (!ToWasmValue(arg_num, fn->args()[i], &params[i])) {
if (!ToWasmValue(Number::Cast(Object::Handle(args.At(i))), fn->args()[i],
&params[i])) {
params.reset();
Exceptions::ThrowArgumentError(String::Handle(
zone, String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
String::NewFormatted("Arg %" Pd " is the wrong type.", i)));
UNREACHABLE();
}
}
@ -944,11 +709,6 @@ DEFINE_NATIVE_ENTRY(Wasm_addGlobalImport, 0, 5) {
return nullptr;
}
DEFINE_NATIVE_ENTRY(Wasm_addFunctionImport, 0, 4) {
Exceptions::ThrowUnsupportedError("WASM is disabled");
return nullptr;
}
DEFINE_NATIVE_ENTRY(Wasm_initMemory, 0, 3) {
Exceptions::ThrowUnsupportedError("WASM is disabled");
return nullptr;

View file

@ -396,7 +396,6 @@ namespace dart {
V(Wasm_initImports, 2) \
V(Wasm_addMemoryImport, 3) \
V(Wasm_addGlobalImport, 5) \
V(Wasm_addFunctionImport, 4) \
V(Wasm_initMemory, 3) \
V(Wasm_growMemory, 2) \
V(Wasm_initInstance, 3) \

View file

@ -66,11 +66,8 @@ class _NativeWasmModule extends NativeFieldWrapperClass1 implements WasmModule {
class _NativeWasmImports extends NativeFieldWrapperClass1
implements WasmImports {
List<WasmMemory> _memories;
List<Function> _fns;
_NativeWasmImports(String moduleName)
: _memories = [],
_fns = [] {
_NativeWasmImports(String moduleName) : _memories = [] {
_init(moduleName);
}
@ -83,23 +80,10 @@ class _NativeWasmImports extends NativeFieldWrapperClass1
_addGlobal(name, value, T, mutable);
}
void addFunction<T extends Function>(String name, Function fn) {
int id = _fns.length;
_fns.add(fn);
_addFunction(name, id, T);
}
@pragma("vm:entry-point")
Function getFunction(int id) {
return _fns[id];
}
void _init(String moduleName) native 'Wasm_initImports';
void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
void _addGlobal(String name, num value, Type type, bool mutable)
native 'Wasm_addGlobalImport';
void _addFunction(String name, int id, Type type)
native 'Wasm_addFunctionImport';
}
class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {

View file

@ -45,9 +45,6 @@ abstract class WasmImports {
// Add a memory to the imports.
void addMemory(String name, WasmMemory memory);
// Add a function to the imports.
void addFunction<T extends Function>(String name, Function fn);
}
// WasmMemory is a sandbox for a WasmInstance to run in.

View file

@ -68,11 +68,8 @@ class _NativeWasmModule extends NativeFieldWrapperClass1 implements WasmModule {
class _NativeWasmImports extends NativeFieldWrapperClass1
implements WasmImports {
List<WasmMemory> _memories;
List<Function> _fns;
_NativeWasmImports(String moduleName)
: _memories = [],
_fns = [] {
_NativeWasmImports(String moduleName) : _memories = [] {
_init(moduleName);
}
@ -85,23 +82,10 @@ class _NativeWasmImports extends NativeFieldWrapperClass1
_addGlobal(name, value, T, mutable);
}
void addFunction<T extends Function>(String name, Function fn) {
int id = _fns.length;
_fns.add(fn);
_addFunction(name, id, T);
}
@pragma("vm:entry-point")
Function getFunction(int id) {
return _fns[id];
}
void _init(String moduleName) native 'Wasm_initImports';
void _addMemory(String name, WasmMemory memory) native 'Wasm_addMemoryImport';
void _addGlobal(String name, num value, Type type, bool mutable)
native 'Wasm_addGlobalImport';
void _addFunction(String name, int id, Type type)
native 'Wasm_addFunctionImport';
}
class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {

View file

@ -47,9 +47,6 @@ abstract class WasmImports {
// Add a memory to the imports.
void addMemory(String name, WasmMemory memory);
// Add a function to the imports.
void addFunction<T extends Function>(String name, Function fn);
}
// WasmMemory is a sandbox for a WasmInstance to run in.

View file

@ -1,77 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test errors thrown by function imports.
import "package:expect/expect.dart";
import "dart:wasm";
import "dart:typed_data";
void main() {
// This module expects a function import like:
// int64_t someFn(int32_t a, int64_t b, float c, double d);
var data = Uint8List.fromList([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x02, 0x60,
0x04, 0x7f, 0x7e, 0x7d, 0x7c, 0x01, 0x7e, 0x60, 0x00, 0x00, 0x02, 0x0e,
0x01, 0x03, 0x65, 0x6e, 0x76, 0x06, 0x73, 0x6f, 0x6d, 0x65, 0x46, 0x6e,
0x00, 0x00, 0x03, 0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
0x80, 0x88, 0x04, 0x0b, 0x07, 0x11, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
0x72, 0x79, 0x02, 0x00, 0x04, 0x62, 0x6c, 0x61, 0x68, 0x00, 0x01, 0x0a,
0x1d, 0x01, 0x1b, 0x00, 0x41, 0x01, 0x42, 0x02, 0x43, 0x00, 0x00, 0x40,
0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x10, 0x80,
0x80, 0x80, 0x80, 0x00, 0x1a, 0x0b,
]);
WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Int64 Function(Int32, Int64, Float, Double)>(
"someFn", (num a, num b, num c, num d) => 123));
Expect.throwsArgumentError(
() => WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)));
Expect.throwsArgumentError(
() => WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Int64 Function(Int32)>("someFn", (num a) => 123)));
Expect.throwsArgumentError(() => WasmModule(data).instantiate(
WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Double Function(Int32, Int64, Float, Double)>(
"someFn", (num a, num b, num c, num d) => 123)));
Expect.throwsArgumentError(() => WasmModule(data).instantiate(
WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Int64 Function(Int32, Int64, Float, Float)>(
"someFn", (num a, num b, num c, num d) => 123)));
Expect.throwsArgumentError(() => WasmModule(data).instantiate(
WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<dynamic Function(Int32, Int64, Float, Double)>(
"someFn", (num a, num b, num c, num d) => 123)));
Expect.throwsArgumentError(() => WasmModule(data).instantiate(
WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Int64 Function(Int32, Int64, dynamic, Double)>(
"someFn", (num a, num b, num c, num d) => 123)));
Expect.throwsArgumentError(
() => WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addGlobal<Int64>("someFn", 123, false)));
}

View file

@ -1,47 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test throwing exceptions from an imported function.
import "package:expect/expect.dart";
import "dart:wasm";
import "dart:typed_data";
void main() {
// int64_t fn(int64_t x) { return throwIfNegative(x); }
var data = Uint8List.fromList([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
0x01, 0x7e, 0x01, 0x7e, 0x02, 0x17, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x0f,
0x74, 0x68, 0x72, 0x6f, 0x77, 0x49, 0x66, 0x4e, 0x65, 0x67, 0x61, 0x74,
0x69, 0x76, 0x65, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01,
0x70, 0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01,
0x7f, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x0f, 0x02, 0x06, 0x6d,
0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x02, 0x66, 0x6e, 0x00, 0x01,
0x0a, 0x0c, 0x01, 0x0a, 0x00, 0x20, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80,
0x00, 0x0b,
]);
dynamic override = null;
var inst = WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Int64 Function(Int64)>("throwIfNegative", (int x) {
if (x < 0) {
throw Exception(x);
}
if (override != null) {
return override;
}
return x;
}));
var fn = inst.lookupFunction<Int64 Function(Int64)>("fn");
Expect.equals(123, fn.call([123]));
Expect.throws(() => fn.call([-456]), (Exception e) => "$e".contains("-456"));
override = "Not an integer";
Expect.throwsArgumentError(() => fn.call([789]));
override = 0.123;
Expect.throwsArgumentError(() => fn.call([789]));
}

View file

@ -1,39 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test that we can load a wasm module, find a function, and call it.
import "package:expect/expect.dart";
import "dart:wasm";
import "dart:typed_data";
void main() {
// void reportStuff() { report(123, 456); }
var data = Uint8List.fromList([
0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x09, 0x02, 0x60,
0x02, 0x7e, 0x7e, 0x00, 0x60, 0x00, 0x00, 0x02, 0x0e, 0x01, 0x03, 0x65,
0x6e, 0x76, 0x06, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x00, 0x00, 0x03,
0x02, 0x01, 0x01, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01, 0x01, 0x05, 0x03,
0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41, 0x80, 0x88, 0x04,
0x0b, 0x07, 0x18, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02,
0x00, 0x0b, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x75, 0x66,
0x66, 0x00, 0x01, 0x0a, 0x10, 0x01, 0x0e, 0x00, 0x42, 0xfb, 0x00, 0x42,
0xc8, 0x03, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x0b,
]);
int report_x = -1;
int report_y = -1;
var inst = WasmModule(data).instantiate(WasmImports("env")
..addMemory("memory", WasmMemory(256, 1024))
..addGlobal<Int32>("__memory_base", 1024, false)
..addFunction<Void Function(Int64, Int64)>("report", (int x, int y) {
report_x = x;
report_y = y;
}));
var fn = inst.lookupFunction<Void Function()>("reportStuff");
fn.call([]);
Expect.equals(report_x, 123);
Expect.equals(report_y, 456);
}

View file

@ -1,16 +0,0 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test errors thrown by WasmImports.
import "package:expect/expect.dart";
import "dart:wasm";
import "dart:typed_data";
void main() {
var imp = WasmImports("env");
Expect.throwsArgumentError(() => imp.addGlobal<int>("a", 1, true));
Expect.throwsArgumentError(() => imp.addGlobal<double>("b", 2, true));
Expect.throwsArgumentError(() => imp.addGlobal<dynamic>("c", 3, true));
}

View file

@ -20,7 +20,4 @@ void main() {
Expect.equals(1100, mem.lengthInPages);
Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
Expect.equals(45, mem[123]);
Expect.throwsArgumentError(() => WasmMemory(1000000000));
Expect.throwsArgumentError(() => mem.grow(1000000000));
}