Skip to content

Commit 26c49d5

Browse files
liamappelbecommit-bot@chromium.org
authored andcommitted
[vm] Wasm memory exports, and emscripten hello world
I got the hello world wasm file from the emscripten team and got it running using a fake implementation of WASI's fd_write function. This necessitated adding support for memory exports. Bug: #37882 Change-Id: I139a4e868d437e2232bf4260e5cc26d8c598ac2c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119061 Commit-Queue: Liam Appelbe <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 1b91195 commit 26c49d5

14 files changed

+299
-20
lines changed

runtime/lib/wasm.cc

+55-3
Original file line numberDiff line numberDiff line change
@@ -471,25 +471,34 @@ class WasmFunction {
471471

472472
class WasmInstance {
473473
public:
474-
WasmInstance() : _instance(nullptr), _exports(nullptr) {}
474+
WasmInstance() : _instance(nullptr), _exports(nullptr), _memory(nullptr) {}
475475

476476
bool Instantiate(wasmer_module_t* module, WasmImports* imports) {
477+
ASSERT(_instance == nullptr);
478+
477479
// Instantiate module.
478480
if (wasmer_module_instantiate(module, &_instance, imports->RawImports(),
479481
imports->NumImports()) !=
480482
wasmer_result_t::WASMER_OK) {
481483
return false;
482484
}
483485

484-
// Load all functions.
486+
// Load all exports.
485487
wasmer_instance_exports(_instance, &_exports);
486488
intptr_t num_exports = wasmer_exports_len(_exports);
487489
for (intptr_t i = 0; i < num_exports; ++i) {
488490
wasmer_export_t* exp = wasmer_exports_get(_exports, i);
489-
if (wasmer_export_kind(exp) == wasmer_import_export_kind::WASM_FUNCTION) {
491+
wasmer_import_export_kind kind = wasmer_export_kind(exp);
492+
if (kind == wasmer_import_export_kind::WASM_FUNCTION) {
490493
if (!AddFunction(exp)) {
491494
return false;
492495
}
496+
} else if (kind == wasmer_import_export_kind::WASM_MEMORY) {
497+
ASSERT(_memory == nullptr);
498+
if (wasmer_export_to_memory(exp, &_memory) !=
499+
wasmer_result_t::WASMER_OK) {
500+
return false;
501+
}
493502
}
494503
}
495504

@@ -541,10 +550,13 @@ class WasmInstance {
541550
o << '}' << std::endl;
542551
}
543552

553+
wasmer_memory_t* memory() { return _memory; }
554+
544555
private:
545556
wasmer_instance_t* _instance;
546557
wasmer_exports_t* _exports;
547558
MallocDirectChainedHashMap<CStringKeyValueTrait<WasmFunction*>> _functions;
559+
wasmer_memory_t* _memory;
548560

549561
static classid_t ToDartType(wasmer_value_tag wasm_type) {
550562
switch (wasm_type) {
@@ -840,6 +852,36 @@ DEFINE_NATIVE_ENTRY(Wasm_initInstance, 0, 3) {
840852
return Object::null();
841853
}
842854

855+
DEFINE_NATIVE_ENTRY(Wasm_initMemoryFromInstance, 0, 2) {
856+
GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(0));
857+
GET_NON_NULL_NATIVE_ARGUMENT(Instance, inst_wrap, arguments->NativeArgAt(1));
858+
859+
ASSERT(mem_wrap.NumNativeFields() == 1);
860+
ASSERT(inst_wrap.NumNativeFields() == 1);
861+
862+
WasmInstance* inst =
863+
reinterpret_cast<WasmInstance*>(inst_wrap.GetNativeField(0));
864+
865+
wasmer_memory_t* memory = inst->memory();
866+
867+
mem_wrap.SetNativeField(0, reinterpret_cast<intptr_t>(memory));
868+
FinalizablePersistentHandle::New(thread->isolate(), mem_wrap, memory,
869+
FinalizeWasmMemory,
870+
wasmer_memory_length(memory));
871+
return WasmMemoryToExternalTypedData(memory);
872+
}
873+
874+
DEFINE_NATIVE_ENTRY(Wasm_getMemoryPages, 0, 1) {
875+
GET_NON_NULL_NATIVE_ARGUMENT(Instance, mem_wrap, arguments->NativeArgAt(0));
876+
877+
ASSERT(mem_wrap.NumNativeFields() == 1);
878+
879+
wasmer_memory_t* memory =
880+
reinterpret_cast<wasmer_memory_t*>(mem_wrap.GetNativeField(0));
881+
882+
return Integer::New(wasmer_memory_length(memory));
883+
}
884+
843885
DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
844886
GET_NON_NULL_NATIVE_ARGUMENT(Instance, fn_wrap, arguments->NativeArgAt(0));
845887
GET_NON_NULL_NATIVE_ARGUMENT(Instance, inst_wrap, arguments->NativeArgAt(1));
@@ -978,6 +1020,16 @@ DEFINE_NATIVE_ENTRY(Wasm_initInstance, 0, 3) {
9781020
return nullptr;
9791021
}
9801022

1023+
DEFINE_NATIVE_ENTRY(Wasm_initMemoryFromInstance, 0, 2) {
1024+
Exceptions::ThrowUnsupportedError("WASM is disabled");
1025+
return nullptr;
1026+
}
1027+
1028+
DEFINE_NATIVE_ENTRY(Wasm_getMemoryPages, 0, 1) {
1029+
Exceptions::ThrowUnsupportedError("WASM is disabled");
1030+
return nullptr;
1031+
}
1032+
9811033
DEFINE_NATIVE_ENTRY(Wasm_initFunction, 0, 4) {
9821034
Exceptions::ThrowUnsupportedError("WASM is disabled");
9831035
return nullptr;

runtime/vm/bootstrap_natives.h

+2
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ namespace dart {
400400
V(Wasm_initMemory, 3) \
401401
V(Wasm_growMemory, 2) \
402402
V(Wasm_initInstance, 3) \
403+
V(Wasm_initMemoryFromInstance, 2) \
404+
V(Wasm_getMemoryPages, 1) \
403405
V(Wasm_initFunction, 4) \
404406
V(Wasm_callFunction, 2)
405407

sdk/lib/_internal/vm/lib/wasm_patch.dart

+12
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
112112
_buffer = _init(initialPages, maxPages);
113113
}
114114

115+
_NativeWasmMemory.fromInstance(_NativeWasmInstance inst) {
116+
_buffer = _initFromInstance(inst);
117+
_pages = _getPages();
118+
}
119+
115120
int get lengthInPages => _pages;
116121
int get lengthInBytes => _buffer.lengthInBytes;
117122
int operator [](int index) => _buffer[index];
@@ -128,6 +133,9 @@ class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
128133

129134
Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
130135
Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
136+
Uint8List _initFromInstance(_NativeWasmInstance inst)
137+
native 'Wasm_initMemoryFromInstance';
138+
int _getPages() native 'Wasm_getMemoryPages';
131139
}
132140

133141
class _NativeWasmInstance extends NativeFieldWrapperClass1
@@ -145,6 +153,10 @@ class _NativeWasmInstance extends NativeFieldWrapperClass1
145153
return _NativeWasmFunction<T>(this, name);
146154
}
147155

156+
WasmMemory get memory {
157+
return _NativeWasmMemory.fromInstance(this);
158+
}
159+
148160
void _init(_NativeWasmModule module, _NativeWasmImports imports)
149161
native 'Wasm_initInstance';
150162
}

sdk/lib/wasm/wasm.dart

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ abstract class WasmMemory {
8080
abstract class WasmInstance {
8181
// Find an exported function with the given signature.
8282
WasmFunction<T> lookupFunction<T extends Function>(String name);
83+
84+
// Returns this instances's memory.
85+
WasmMemory get memory;
8386
}
8487

8588
// WasmFunction is a callable function in a WasmInstance.

sdk_nnbd/lib/_internal/vm/lib/wasm_patch.dart

+12
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
114114
_buffer = _init(initialPages, maxPages);
115115
}
116116

117+
_NativeWasmMemory.fromInstance(_NativeWasmInstance inst) {
118+
_buffer = _initFromInstance(inst);
119+
_pages = _getPages();
120+
}
121+
117122
int get lengthInPages => _pages;
118123
int get lengthInBytes => _buffer.lengthInBytes;
119124
int operator [](int index) => _buffer[index];
@@ -130,6 +135,9 @@ class _NativeWasmMemory extends NativeFieldWrapperClass1 implements WasmMemory {
130135

131136
Uint8List _init(int initialPages, int maxPages) native 'Wasm_initMemory';
132137
Uint8List _grow(int deltaPages) native 'Wasm_growMemory';
138+
Uint8List _initFromInstance(_NativeWasmInstance inst)
139+
native 'Wasm_initMemoryFromInstance';
140+
int _getPages() native 'Wasm_getMemoryPages';
133141
}
134142

135143
class _NativeWasmInstance extends NativeFieldWrapperClass1
@@ -147,6 +155,10 @@ class _NativeWasmInstance extends NativeFieldWrapperClass1
147155
return _NativeWasmFunction<T>(this, name);
148156
}
149157

158+
WasmMemory get memory {
159+
return _NativeWasmMemory.fromInstance(this);
160+
}
161+
150162
void _init(_NativeWasmModule module, _NativeWasmImports imports)
151163
native 'Wasm_initInstance';
152164
}

sdk_nnbd/lib/wasm/wasm.dart

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ abstract class WasmMemory {
8282
abstract class WasmInstance {
8383
// Find an exported function with the given signature.
8484
WasmFunction<T> lookupFunction<T extends Function>(String name);
85+
86+
// Returns this instance's memory.
87+
WasmMemory get memory;
8588
}
8689

8790
// WasmFunction is a callable function in a WasmInstance.

tests/lib_2/wasm/basic_test.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ void main() {
2020
0x7e, 0x0b,
2121
]);
2222

23-
var inst = WasmModule(data).instantiate(WasmImports()
24-
..addMemory("env", "memory", WasmMemory(256, 1024))
25-
..addGlobal<Int32>("env", "__memory_base", 1024, false));
23+
var inst = WasmModule(data).instantiate(WasmImports());
2624
var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
2725
int n = fn.call([1234]);
2826

tests/lib_2/wasm/fn_call_error_test.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ void main() {
2020
0x7e, 0x0b,
2121
]);
2222

23-
var inst = WasmModule(data).instantiate(WasmImports()
24-
..addMemory("env", "memory", WasmMemory(256, 1024))
25-
..addGlobal<Int32>("env", "__memory_base", 1024, false));
23+
var inst = WasmModule(data).instantiate(WasmImports());
2624
var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
2725

2826
Expect.throwsArgumentError(() => fn.call([]));

tests/lib_2/wasm/fn_import_test.dart

-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ void main() {
2626
int report_y = -1;
2727

2828
var inst = WasmModule(data).instantiate(WasmImports()
29-
..addMemory("env", "memory", WasmMemory(256, 1024))
30-
..addGlobal<Int32>("env", "__memory_base", 1024, false)
3129
..addFunction<Void Function(Int64, Int64)>("env", "report", (int x, int y) {
3230
report_x = x;
3331
report_y = y;

tests/lib_2/wasm/fn_mismatch_error_test.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ void main() {
2020
0x7e, 0x0b,
2121
]);
2222

23-
var inst = WasmModule(data).instantiate(WasmImports()
24-
..addMemory("env", "memory", WasmMemory(256, 1024))
25-
..addGlobal<Int32>("env", "__memory_base", 1024, false));
23+
var inst = WasmModule(data).instantiate(WasmImports());
2624
Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
2725
Expect.throwsArgumentError(
2826
() => inst.lookupFunction<Int64 Function(Int64)>("blah"));

0 commit comments

Comments
 (0)