mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:41:41 +00:00
Add support for importing shared memory as per wasm threading proposal.
Change-Id: I077b8d3a60f543c3e54cd3e6d024260adcb8ed83 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241420 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Jackson Gardner <jacksongardner@google.com>
This commit is contained in:
parent
e5f4b85066
commit
6466bac7cd
|
@ -13,6 +13,7 @@ import 'package:dart2wasm/translator.dart';
|
|||
|
||||
final Map<String, void Function(TranslatorOptions, bool)> boolOptionMap = {
|
||||
"export-all": (o, value) => o.exportAll = value,
|
||||
"import-shared-memory": (o, value) => o.importSharedMemory = value,
|
||||
"inlining": (o, value) => o.inlining = value,
|
||||
"lazy-constants": (o, value) => o.lazyConstants = value,
|
||||
"local-nullability": (o, value) => o.localNullability = value,
|
||||
|
@ -27,6 +28,7 @@ final Map<String, void Function(TranslatorOptions, bool)> boolOptionMap = {
|
|||
"string-data-segments": (o, value) => o.stringDataSegments = value,
|
||||
};
|
||||
final Map<String, void Function(TranslatorOptions, int)> intOptionMap = {
|
||||
"shared-memory-max-pages": (o, value) => o.sharedMemoryMaxPages = value,
|
||||
"watch": (o, value) => (o.watchPoints ??= []).add(value),
|
||||
};
|
||||
|
||||
|
@ -83,6 +85,11 @@ Future<int> main(List<String> args) async {
|
|||
usage("Missing argument to ${args.last}");
|
||||
}
|
||||
|
||||
if (options.importSharedMemory && options.sharedMemoryMaxPages == null) {
|
||||
usage("--shared-memory-max-pages must be "
|
||||
"specified if --import-shared-memory is used.");
|
||||
}
|
||||
|
||||
if (nonOptions.length != 2) usage("Requires two file arguments");
|
||||
String input = nonOptions[0];
|
||||
String output = nonOptions[1];
|
||||
|
|
|
@ -12,6 +12,7 @@ where *options* include:
|
|||
| --------------------------------------- | ------- | ----------- |
|
||||
| `--dart-sdk=`*path* | relative to script | The location of the `sdk` directory inside the Dart SDK, containing the core library sources.
|
||||
| `--`[`no-`]`export-all` | no | Export all functions; otherwise, just export `main`.
|
||||
| `--`[`no-`]`import-shared-memory` | no | Import a shared memory buffer. If this is on, `--shared-memory-max-pages` must also be specified.
|
||||
| `--`[`no-`]`inlining` | no | Inline small functions.
|
||||
| `--`[`no-`]`lazy-constants` | no | Instantiate constants lazily.
|
||||
| `--`[`no-`]`local-nullability` | no | Use non-nullable types for non-nullable locals and temporaries.
|
||||
|
@ -22,6 +23,7 @@ where *options* include:
|
|||
| `--`[`no-`]`print-kernel` | no | Print IR for each function before compiling it.
|
||||
| `--`[`no-`]`print-wasm` | no | Print Wasm instructions of each compiled function.
|
||||
| `--`[`no-`]`runtime-types` | no | Use RTTs for allocations and casts.
|
||||
| `--shared-memory-max-pages` *pagecount* | | Max size of the imported memory buffer. If `--shared-import-memory` is specified, this must also be specified.
|
||||
| `--`[`no-`]`string-data-segments` | no | Use experimental array init from data segment for string constants.
|
||||
| `--watch` *offset* | | Print stack trace leading to the byte at offset *offset* in the `.wasm` output file. Can be specified multiple times.
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ class Constants {
|
|||
.toBytes();
|
||||
|
||||
w.Memory stringMemory =
|
||||
m.addMemory(stringsAsBytes.length, stringsAsBytes.length);
|
||||
m.addMemory(false, stringsAsBytes.length, stringsAsBytes.length);
|
||||
m.addDataSegment(stringsAsBytes, stringMemory, 0);
|
||||
makeStringFunctionBody(translator.oneByteStringClass, oneByteStringFunction,
|
||||
(b) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import 'package:wasm_builder/wasm_builder.dart' as w;
|
|||
/// Options controlling the translation.
|
||||
class TranslatorOptions {
|
||||
bool exportAll = false;
|
||||
bool importSharedMemory = false;
|
||||
bool inlining = false;
|
||||
int inliningLimit = 3;
|
||||
bool lazyConstants = false;
|
||||
|
@ -38,6 +39,7 @@ class TranslatorOptions {
|
|||
bool printKernel = false;
|
||||
bool printWasm = false;
|
||||
bool runtimeTypes = false;
|
||||
int? sharedMemoryMaxPages;
|
||||
bool stringDataSegments = false;
|
||||
List<int>? watchPoints = null;
|
||||
|
||||
|
@ -127,7 +129,8 @@ class Translator {
|
|||
// Lazily create exception tag if used.
|
||||
late final w.Tag exceptionTag = createExceptionTag();
|
||||
// Lazily import FFI memory if used.
|
||||
late final w.Memory ffiMemory = m.importMemory("ffi", "memory", 0);
|
||||
late final w.Memory ffiMemory = m.importMemory("ffi", "memory",
|
||||
options.importSharedMemory, 0, options.sharedMemoryMaxPages);
|
||||
|
||||
// Caches for when identical source constructs need a common representation.
|
||||
final Map<w.StorageType, w.ArrayType> arrayTypeCache = {};
|
||||
|
|
|
@ -130,9 +130,9 @@ class Module with SerializerMixin {
|
|||
}
|
||||
|
||||
/// Add a new memory to the module.
|
||||
DefinedMemory addMemory(int minSize, [int? maxSize]) {
|
||||
DefinedMemory addMemory(bool shared, int minSize, [int? maxSize]) {
|
||||
anyMemoriesDefined = true;
|
||||
final memory = DefinedMemory(memories.length, minSize, maxSize);
|
||||
final memory = DefinedMemory(memories.length, shared, minSize, maxSize);
|
||||
memories.add(memory);
|
||||
return memory;
|
||||
}
|
||||
|
@ -195,13 +195,14 @@ class Module with SerializerMixin {
|
|||
///
|
||||
/// All imported memories must be specified before any memories are declared
|
||||
/// using [Module.addMemory].
|
||||
ImportedMemory importMemory(String module, String name, int minSize,
|
||||
ImportedMemory importMemory(
|
||||
String module, String name, bool shared, int minSize,
|
||||
[int? maxSize]) {
|
||||
if (anyMemoriesDefined) {
|
||||
throw "All memory imports must be specified before any definitions.";
|
||||
}
|
||||
final memory =
|
||||
ImportedMemory(module, name, memories.length, minSize, maxSize);
|
||||
ImportedMemory(module, name, memories.length, shared, minSize, maxSize);
|
||||
memories.add(memory);
|
||||
return memory;
|
||||
}
|
||||
|
@ -410,13 +411,23 @@ class Table implements Serializable {
|
|||
/// A memory in a module.
|
||||
class Memory {
|
||||
final int index;
|
||||
final bool shared;
|
||||
final int minSize;
|
||||
final int? maxSize;
|
||||
|
||||
Memory(this.index, this.minSize, [this.maxSize]);
|
||||
Memory(this.index, this.shared, this.minSize, [this.maxSize]) {
|
||||
if (shared && maxSize == null) {
|
||||
throw "Shared memory must specify a maximum size.";
|
||||
}
|
||||
}
|
||||
|
||||
void _serializeLimits(Serializer s) {
|
||||
if (maxSize == null) {
|
||||
if (shared) {
|
||||
assert(maxSize != null);
|
||||
s.writeByte(0x03);
|
||||
s.writeUnsigned(minSize);
|
||||
s.writeUnsigned(maxSize!);
|
||||
} else if (maxSize == null) {
|
||||
s.writeByte(0x00);
|
||||
s.writeUnsigned(minSize);
|
||||
} else {
|
||||
|
@ -428,8 +439,8 @@ class Memory {
|
|||
}
|
||||
|
||||
class DefinedMemory extends Memory implements Serializable {
|
||||
DefinedMemory(int index, int minSize, int? maxSize)
|
||||
: super(index, minSize, maxSize);
|
||||
DefinedMemory(int index, bool shared, int minSize, int? maxSize)
|
||||
: super(index, shared, minSize, maxSize);
|
||||
|
||||
@override
|
||||
void serialize(Serializer s) => _serializeLimits(s);
|
||||
|
@ -556,8 +567,9 @@ class ImportedMemory extends Memory implements Import {
|
|||
final String module;
|
||||
final String name;
|
||||
|
||||
ImportedMemory(this.module, this.name, int index, int minSize, int? maxSize)
|
||||
: super(index, minSize, maxSize);
|
||||
ImportedMemory(
|
||||
this.module, this.name, int index, bool shared, int minSize, int? maxSize)
|
||||
: super(index, shared, minSize, maxSize);
|
||||
|
||||
@override
|
||||
void serialize(Serializer s) {
|
||||
|
|
|
@ -38,7 +38,7 @@ void main() {
|
|||
|
||||
// Wrong kind of import.
|
||||
Expect.throws(
|
||||
() => mod.instantiate().addMemory("env", "someFn", mod.createMemory(10)),
|
||||
() => mod.instantiate().addMemory(false, "env", "someFn", mod.createMemory(10)),
|
||||
(Exception e) => "$e".contains("Import is not a memory"));
|
||||
|
||||
// Wrong namespace.
|
||||
|
|
|
@ -40,7 +40,7 @@ void main() {
|
|||
|
||||
// Wrong kind of import.
|
||||
Expect.throws(
|
||||
() => mod.instantiate().addMemory("env", "someFn", mod.createMemory(10)),
|
||||
() => mod.instantiate().addMemory(false, "env", "someFn", mod.createMemory(10)),
|
||||
(Exception e) => "$e".contains("Import is not a memory"));
|
||||
|
||||
// Wrong namespace.
|
||||
|
|
Loading…
Reference in a new issue