To make sure Dart values with typed data types like `Uint8List`, `List`,
`String` etc. hold the right type of JS values, check types of JS
references in boxing functions that return Dart typed data types.
To reflect what the functions actually do, and for consistency with
other functions, boxing factory names are changed from `fromJSArray` to
`fromRef`.
New boxing functions `fromRefUnchecked` added for the call sites that
already know the reference type to be the right type, for example in
`dartifyRaw`.
These unchecked functions will also be used in CL 424021 where we
replace some `dartifyRaw` calls with more precise "dartify" functions
that only converts when the type is right. (`dartifyRaw` always boxes
the argument regardless of the type)
Issue: https://github.com/dart-lang/sdk/issues/60357
Change-Id: Icdfb49b9b235d35af2af0c4be51b295ee68d99fc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429362
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
When we create a `Selector` we compute various information
based on all members belonging to that selector. Before this
CL this was split up: Some things like `ParameterInfo` was
calculated&updated while discovering members, others was
calculated after all members were discovered.
We now make all fields whose value depends on knowing all
members `late final` and initialize those fields after
having found all members of a selector.
When we compute the `ParameterInfo` of the selector we take
special care:
If there's non-abstract implementations and the selector is
not overridable by dynamic modules then we create the
`ParameterInfo` by looking only at the non-abstract members
=> This increases precision as we ignore the types and
default values of optional parameters for abstract members
If there's no implementations of the selector it may still be
referred to by instance invocation AST nodes (which are
unreachable). The current code generator still needs a
`Selector.signature` in order to evaluate arguments for such
nodes.
=> We calculate `ParameterInfo` based on the abstract member
and use `defaultSentinel` for optional parameters.
If a selector can have implementations in dynamic modules
then we cannot determine whether all implementations have
the same default value of optional parameters.
=> We calculate `ParameterInfo` using `defaultSentinel`
value for all optional parameters. Ensuring the caller
doesn't pass them but the callee will default to it's
default value if it wasn't passed by caller.
See added test case for when we (before this CL) may
use unreachable members in the param info / signature
calculation and how that could lead to a compiler bug
(before this CL) due to a missing
`VariableDeclaration.initializer`
TEST=web/wasm/unreachable_selector_implementation_test
Change-Id: I3628177f8e93c5d24ff0eb0ff8fee6121a4a08d1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/428541
Reviewed-by: Nate Biggs <natebiggs@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
In V8, the only way to pass a Wasm integer or float to JS without
allocation is by passing it as a 31-bit integer.
This can be done by:
1. Passing as `i32`. If the integer fits into 31 bits it's passed
without allocation.
2. Passing as externalized `i31ref`.
(1) requires importing the JS function with different signatures: for
each `int` argument we would need a signature with the `i32` as the Wasm
argument type, and another with `externref` (or `f64` if we want to pass
large integers as `f64`).
This is not feasible as with a JS function with N `int` arguments we
would need `2^N` imports. So we implement (2): we import each interop
function with one signature, passing `externref` as the argument, as
before. When the number fits into 31 bits we convert it to an `i31ref`
and externalize it. Otherwise we convert the number to `externref` as
before, by calling the JS function `(o) => o` imported with type `[f64]
-> [externref]`.
New benchmark checks `int` passing for small (31 bit) and large (larger
than 31 bit) integers. Results before:
WasmJSInterop.call.void.1ArgsSmi(RunTimeRaw): 0.020 ns.
WasmJSInterop.call.void.1ArgsInt(RunTimeRaw): 0.018 ns.
After:
WasmJSInterop.call.void.1ArgsSmi(RunTimeRaw): 0.014 ns.
WasmJSInterop.call.void.1ArgsInt(RunTimeRaw): 0.018 ns.
Issue: https://github.com/dart-lang/sdk/issues/60357
Change-Id: I749001e0e7e9784114415439298c2f3e0fb974b3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419880
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Transform factory calls to default map and set classes to the
constructor calls to the classes to improve kernel.
Also remove some redundant null checks in VM's transformer.
`source_map_simple_optimized_test.dart` is updated: with improved kernel
wasm-opt now eliminates the `testMain` function, so the stack trace
doesn't mention it.
Fixes https://github.com/dart-lang/sdk/issues/60343.
Tested: minor refactoring in VM doesn't need testing. Wasm tested with
existing tests.
Change-Id: Ie448d1374ff0e1b278859f22bc250899e0e4cfd0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/416640
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This test is a regression test for a dart2wasm compiler crash. It tests
that the compiler doesn't crash anymore but the error happens at
runtime.
The particular error that will happen at runtime is that `unreachable`
will be hit (in the place where a unboxed double is attempted to be cast
to an unboxed integer).
Since we run binaryen with `--traps-never-happen` it may optimize this
`unreachable` away and make the test accidentally pass.
So we force this to be run in `-O0` mode, which means we don't run
binaryen on it.
Change-Id: I6460982d4b32d773ee763e9687c8fec0bffa00f0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/415881
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
Currently we have 3 different string types (JS Strings, OneByteString
and TwoByteString)s. There's some advantages to this, mainly that
if strings are used purely inside Dart we have more control over
optimizing them. But it does come with some issues
* Operations on mixture of strings are slow
* We get JS strings from outside (in DevTools e.g. websocket messages)
* Any kind of DOM interaction requires copying strings
* Regular expression matches can result in O(N*N) instead of O(N)
* Encoding of string literals/constants is terrible, high size overhead
* ...
Now that there's a standardized way to access JS strings (via
the `js-string` builtin spec) and this standard is finalized and
enabled in Chrome & Firefox it makes sense for us to switch to it.
It reduces app size:
* Smaller size: hello world -25%, flute -5.5%
* Faster startup
The performance changes are nuanced, some workloads will improve
significantly, some workloads will regress.
Improvements will come especially in cases where
strings are concatenated (due to JS not actually allocating new
strings in this case). That impacts e.g. string interpolations,
string buffer, json-to-string encoding, ...
Regressions will come especially for cases where we have to
construct strings from bytes (e.g. in utf8 decoder, utf8+json
decoder) - mainly due to having to go through an intermediary
`WasmArray<WasmI16>` to allocate strings. Also in cases where we
access individual char codes from the strings.
There's some follow-up improvements we can do, but it's better to
not iterate on this CL even longer but get it landed.
This CL will make the benchmarking system use
`--require-js-string-builtin` as well as most of test CI
(in `pkg/dart2wasm/tool/compile_benchmark`)
Though we run some configurations via overriding with
`--no-require-js-string-builtin`
(in `tools/bots/test_matrix.json`)
Issue https://github.com/flutter/flutter/issues/159400#issuecomment-2538593980
Issue https://github.com/dart-lang/sdk/issues/59699
TEST=ci
Change-Id: I238ac65efe092de569da870f23134f889ac929f9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392903
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
The async state machine uses a single state in the heap to store the current exception and stacktrace when within a catch block in case they need to be rethrown. When catch blocks are nested this state can be overwritten.
With this new change, before entering a new catch we store the current value of the exception/stacktrace in a local that we can restore after exiting the associated catch blocks. A wasm catch can represent multiple Dart catch blocks so we only need to store the state per wasm catch.
Fixes: https://github.com/dart-lang/sdk/issues/59981
Change-Id: I738084fdecdf5aceac65c5d3698e40b791175171
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405920
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
In dart2wasm, when a comparison like `x == "hello"` is true, we can't
assume that the class of `x` is the same as the class of `"hello"`:
- If `x` is received from JS, it will be `JSStringImpl`.
- If it's a substring of a `TwoByteString`, it will be `TwoByteString`.
- Otherwise it will be `OneByteString`.
Update `Target` with the new method
```
bool get canInferStringClassAfterEqualityComparison => true;
```
to allow TFA to *not* infer classes of string values after comparisons.
Override the method to return `false` in dart2wasm's `Target`
implementation.
Fixes#59901.
Tested: web/wasm/issue_59901_test
Change-Id: I1a6c8deaf27c54240dd4e821dbd8160914502ad7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/404562
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
If the switch's expression has type 'dynamic' and all the case expressions have the same type, we compare them using '=='. This requires a cast to ensure all the types match for the dispatch to the '==' function. However, we don't check that the type of the switch expression matches the type of the case expressions. So the cast fails if they don't match.
This adds a guard to ensure the types match before running through the case expressions. If the guard fails, we either jump to the default case or if there isn't one, we skip the switch entirely.
Fixes: https://github.com/dart-lang/sdk/issues/59782
Change-Id: I12e81f98d1c2046ee47e8ca4371642fd40620636
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/402460
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
The struct type for closures requires the context value be a struct. If the tearoff is on an unboxed value, it first has to be boxed before being used to create the closure struct.
The new test currently fails at runtime (or via assertions at compile time) with this error:
"BoxedInt.abs tear-off" failed: struct.new[2] expected type (ref struct), found local.get of type i64
Change-Id: Ie861bc12a34b21f8b3415edadf55ce3d59f97580
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/402560
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
Some wasm engines have started to optimize the `js-string` builtin
proposal (e.g. V8) and those that haven't yet are probaly going to
do soon.
So we can start taking advantage of it in dart2wasm.
=> We make use of them in the JS<->Dart string copy code.
=> This will also provide a better baseline when evaluating whether
switching to JS stringes entirely makes sense.
A somewhat unrelated (but necessary for this CL) change is to tighten
the types we use in `@pragma('wasm:import')` and
`@pragma('wasm:export')` in some cases:
We should only use 'pure' wasm types (i.e. not wasm struct / function
types we define for dart classes & functions) and mostly non-composed
types in import/exports as the `--closed-world` optimizations from
binaryen rely on that (and error otherwise).
Overall this leads to significant improvements in Dart<->JS
string copies.
The `WasmDataTransfer.*{From,To}BrowserString` benchmarks
improve something between 50-100%.
Change-Id: I2048113c462ecb2047402c0616d2b3b1f45773f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400641
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
The new formatter supports opting a region of code out from being
formatted. I'm applying this marker to all of the multitests since
those tests are often very sensitive to formatting and easily broken.
This way, anyone touching a multitest (including me when I reformat
the tests) doesn't have to remember to not run the formatter on it.
Change-Id: I3d6346d31581772dc8e1701594bf9d919f28db7d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/396104
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
Commit-Queue: Srujan Gaddam <srujzs@google.com>
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Dart does not incorporate immutability into it's type system.
Though the WasmGC type system does have such a concept:
* mutable wasm arrays: they are invariant in the element type
* immutable wasm arrays: they are covariant in the element type
Currently we use the mutable wasm array types for e.g.
const foo = const WasmArray<WasmI32>.literal([0]);
which will be compiled to
(type $Array<WasmI32> () (array (field (mut i32))))
(global $globalFoo
(ref $Array<WasmI32>)
(i32.const 0)
(array.new_fixed $Array<WasmI32> 1
)
=> Notice the **mut** in `array (field (mut i32))`
This CL introduces a `ImmutableWasmArray` which is analogous to
`WasmArray`. The array supports only reading methods since the
contents of the array cannot be modified.
Future CLs will make use of this new array type in various places.
=> This will allow binaryen to optimize things better as it knows the
array contents cannot change.
=> So loads from a (final) global with immutable contents can be
folded away at compile time if the index is known at compile-time.
NOTE: The `WasmArray`& `ImmutableArray` classes are not related to
each other. The reason is that in WasmGC a mutable array isn't a
subtype of a immutable array.
Change-Id: I3a764b5aaa3ac47827332f3064035133ab01f1b2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392900
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
Collects files from `package:async_helper` and `tests/language`
that are generally useful, so that all test-related helpers are
in `package:expect`.
Moves the two libraries from `package:async_helper` into `package:expect`,
and the `tests/language/static_type_helper.dart` file too.
Deprecates `async_minitest.dart`, to follow `minitest.dart`,
expecting the Flutter use of it to have been fixed to not break
on deprecation (I believe Flutter no longer breaks builds on deprecations at all).
Patch 1 is the actual change.
Patch 2+4+8 is changing all existing references to the files.
Patch 6 ignores deprecation in files still using `async_minitest.dart`.
3+5+7+9 are updating this text to make the numbers match.
Then it's just test-expectations and small tweaks from there.
Change-Id: I1b665135b5fef9b9a0c3b340ffe9daf874d0174c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373120
Reviewed-by: Nate Bosch <nbosch@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
This allows tests that would fail in JS compatibility mode (e.g. tests that do a lot of string manipulation) to disable the mode for their own execution.
Also ensure dart2wasm-*-jscm-* builds do a "create_sdk" so that the dart2js platform dill is available for the test.
The alternative I considered was skipping the test but "--js-compatibility" is a dart2wasm-specific flag and the test infra is unaware of it so we can't skip the test via a status file.
Bug: https://github.com/dart-lang/sdk/issues/56858
Change-Id: I60179eaab2e4522acf1fe0b47c7c02ccb1ca957b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388644
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
Currently when the .wasm file path passed to run_wasm.js is a relative
path, `Uri.base` becomes something like `file://test.wasm`, which is not
a valid file URI, so it causes crashes in `Uri.toFilePath`.
When the file path is relative add a omit `file://` prefix.
`Uri.base` values before and after:
- Before, relative .wasm path: `file://test.wasm` (invalid)
- Before, absolute .wasm path: `file:///home/user/test.wasm`
- After, relative .wasm path: `test.wasm` (fixed)
- After, absolute .wasm path: `file:///home/user/test.wasm` (same as before)
Change-Id: I0d1c43716e07a9ee926e7feeeab514c2c66bac16
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385700
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
Adds a mode that puts every library (outside of the SDK) into its own wasm module. Each module is then loaded before the program executes.
This allows us to get better coverage on multi-module logic.
I chose to augment the SDK `_invokeMain` entry point because it allows us to push the user-defined main into a second module ensuring we always have at least 2 modules. The SDK alone is then the main module and all user-code is in deferred modules.
The next step is to make a test configuration for this and decide what frequency to execute it with.
Change-Id: I01bf3a5fee4604a890ef376ebd35113281a36a5c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384404
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
All other constant types include similar logic.
This caused a failure when testing deferred loading logic. Laziness of static tear offs are module sensitive. A record containing a constant static tear off needs to match the inner laziness. Though there are other ways to get lazy subconstants that would also cause this to fail (e.g. very large strings).
Change-Id: Ia55b4f24a15e57b9721383726e7afb5f39557d5d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384980
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This is a reland of commit fca5417d49
- Patchset 1 is the reland.
- Patchset 2 adds a regression test and fixes the bug.
Also tested engine chrome-dart2wasm-html-engine,chrome-dart2wasm-html-html,chrome-dart2wasm-html-ui,chrome-dart2wasm-canvaskit-canvaskit,chrome-dart2wasm-canvaskit-ui,chrome-dart2wasm-skwasm-ui tests manually.
Original change's description:
> Reapply "[dart2wasm] Allocate boxed bools once" and "[dart2wasm] Box `Pointer` values obtained from FFI calls"
>
> This reverts commit a4e9775a99.
>
> - Patchset 1 reverts the revert.
>
> - Patchset 2 adds regression tests. These tests fail.
>
> - Patchset 3 and the rest fixes the bug in `_loadPointer` and
> `_storePointer` intrinsics. Also adds some inline annotations to
> reduce the noise in unoptimized builds.
>
> Tested: updated test web/wasm/ffi/ffi_native_test
> Change-Id: I748a8aa8ff7cc663b1980d2bfab0d0da9f369e3b
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384760
> Reviewed-by: Martin Kustermann <kustermann@google.com>
> Commit-Queue: Ömer Ağacan <omersa@google.com>
Tested: web/wasm/ffi/ffi_native_test updated. Manual run of engine chrome-dart2wasm-html-engine,chrome-dart2wasm-html-html,chrome-dart2wasm-html-ui,chrome-dart2wasm-canvaskit-canvaskit,chrome-dart2wasm-canvaskit-ui,chrome-dart2wasm-skwasm-ui tests.
Change-Id: Ifcd5156b8a03228119b2146edcfc56db8ac6273b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384843
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This reverts commit a4e9775a99.
- Patchset 1 reverts the revert.
- Patchset 2 adds regression tests. These tests fail.
- Patchset 3 and the rest fixes the bug in `_loadPointer` and
`_storePointer` intrinsics. Also adds some inline annotations to
reduce the noise in unoptimized builds.
Tested: updated test web/wasm/ffi/ffi_native_test
Change-Id: I748a8aa8ff7cc663b1980d2bfab0d0da9f369e3b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384760
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
- Document which target needs to be built for the test
`web/wasm/ffi/ffi_native`.
- Add tests that passes and expects `double` and `float`s.
(The `sqrt` native function was previous unused)
- Define inputs in `wasm_module` gn template so that the
`ffi_native_test_wasm_module` target will rebuild the Wasm file when
`tests/web/wasm/ffi/ffi_native_test_module.c` changes.
Change-Id: Iff642ff2cdee48a617e8f2cf4cca4053122a7e05
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384263
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
When `-O3` / `-O4` / `--omit-implicit-checks` are turned on then the
runtime type of tear off functions with covariant parameters was
incorrect.
=> The runtime type of any kind of function or object should always be
the same, irrespective of whether we're dropping some implicit or
explicit `as` checks - as the runtime type can also be observed via e.g.
`is` checks.
The issue was originally introduced in [0].
Issue https://github.com/dart-lang/sdk/issues/56664
[0] https://dart-review.googlesource.com/c/sdk/+/279965
Change-Id: I5c64134e4735d73cf228e12b8eb3bd4767616e11
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/384285
Reviewed-by: Ömer Ağacan <omersa@google.com>
Currently `Pointer` argument and return types of `FfiNative` functions
are translated to Wasm as `i32`.
This causes problems when we need to box those `i32` values as we don't
track which Dart types Wasm types come from when converting a Dart type
like `Pointer` to a Wasm type like `i32`.
Currently this works somewhat accidentally. All `i32`s are boxed as
`BoxedBool`, including `i32`s that represent `Pointer`s.
This breaks when we need to get the type parameter of a `Pointer` (e.g.
in a `is` or `as` check), but more importantly it means that we can't
cache boxed `true` and `false` values and return those cached values
when converting an `i32` to a boxed type as we don't know whether the
`i32` represents a bool or pointer.
Ideally we would have some kind of intermediate layer between
`wasm_builder` and dart2wasm that allows types like "a Wasm i32
representing an unboxed T" (for some T).
Alternatively we could attach extra information to `ValueType`s, for
example using expandos or maybe by adding a `dynamic` field to the base
class.
However it's unclear whether it's worth doing a major refactoring, when
a simpler alternative exist: we box `Pointer` values obtained from an
import in the Dart wrapper for the imported function.
VM already boxes `Pointer`s, so the performance should be acceptable.
This CL implements this simpler alternative of boxing `Pointer` values.
Tested: web/wasm/ffi/ffi_native_test updated.
Change-Id: I02e5c07fdb021a7b51ed5db2a44123b1608c9aad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/383325
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
* Inline small `get iterator` & `get current` iterator methods
* Inline bodies that are small compared to arguments
* Make AST node counter more precise
* Manually mark ListIterator methods as prefer inline
CoreLibraryReviewExempt: Only adds annotation to existing functions
Change-Id: Ib6379e73713cd47a88e5cc67cecd4b5c8344adcb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382882
Reviewed-by: Slava Egorov <vegorov@google.com>
The fused utf8+json decoder ensures the bytes that it operates on are
U8List:
void parseChunk(List<int> value, int start, int end) {
if (value is U8List) {
chunk = value;
} else {
final bytes = U8List(end - start);
bytes.setRange(0, bytes.length, value, start);
...
}
...
}
This speeds up the `bytes.setRange()` call by using an optimized loop
that copies memory from JS arrays to wasm arrays.
=> This speeds up WasmDataTransfer.FromBrowserBytes.* by 10x
=> This speeds up Json*JS.*.FromBytes benchmarks by up to 3x
Issue https://github.com/dart-lang/sdk/issues/56494
Change-Id: I99fd1db280f503e91972c53537d7cd1fd4fd49ff
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382002
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
`Native.addressOf` is not implemented in dart2wasm (yet).
However, crashing the compiler means we cannot use packages which use
`Native.addressOf` even if these are not invoked.
This CL changes these expressions to a `throw` at runtime. This enables
using the subset of packages that use `@Native`s.
Implementation note: The existing FfiNative transformer doesn't
recurse into visitors. And it extends the transformer for the VM which
doesn't recurse. So I don't want to change it to recurse over the
whole AST. Instead, this introduces a new transformer that traverses
the whole AST.
TEST=tests/web/wasm/ffi/ffi_native_test.dart
TEST=existing tests with rolling `package:ffi` in via DEPS.
Closes: https://github.com/dart-lang/sdk/issues/56461
Change-Id: If8fab07a852939a4b519ae7cc47b4071adda8a3a
Cq-Include-Trybots: luci.dart.try:dart2wasm-linux-jscm-chrome-try,dart2wasm-linux-firefox-try,dart2wasm-linux-d8-try,dart2wasm-linux-chrome-try,dart2wasm-asserts-linux-chrome-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/380260
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
Partial instantiation constants are closures. Those closures have
vtables with all entries needed for the closure representation
corresponding to the instantiated closure.
The entries of those vtables have to either call the corresponding
method of the generic closure, or are unreachable dummy entries.
Dummy entries can be required due to clustering callees/callers together
where a particular target doesn't support the name combination.
The case that was incorrect is if the particular name combination did
not get clustered with anything for the generic closure representation.
Issue https://github.com/dart-lang/sdk/issues/56372
TEST=web/wasm/regress_56372_test
Change-Id: Ifbf624e10dd1162f4d5660b43914e5b34ba82294
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/380100
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
To be able to know when we are generating a source map, make `dart
compile wasm` aware of the `--no-source-maps` flag.
The "name" segments of source mappings are also made `null` with this
patch. Browsers don't use that segment and binaryen doesn't support it.
Change-Id: I7b52c8fb7cef92ed60547e97ad137e0cd3967f26
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378421
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
When omitting checks, casts between unboxed types currently cause a
compile-time crash when generating the conversion.
This compile-time crash is useful to catch compiler errors, but when the
checks are omitted it can be triggered on invalid casts, such as when
casting a `double` to `int`.
So when omitting checks, generate an `unreachable` (consistent with
other type cast failure when omitting checks) instead of crashing.
An alterantive implementation (see patchset 1) would be checking for
cast failures when compiling `as` expressions with omitted checks.
However it makes the code slightly more complicated, and more
importantly `unreachable` gets a wrong source span as it's generated
after the `wrap` to compile expression.
Fixes#56234.
Change-Id: Ia93a850d028a69320ff671efd8344843fa7c4388
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375640
Commit-Queue: Ömer Ağacan <omersa@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This implements generating source maps for the generated Wasm files.
Copying dart2js's command line interface, a source map file with the
name `<program name>.wasm.map` is generated unless `--no-source-maps` is
passed.
When a source map is generated, the generated .wasm file gets a new
section `sourceMappingURL` with the contents `<program name>.wasm.map`.
This section seems to be undocumented, but Chrome and binaryen recognize
it as the URI to the source map file. Chrome is then loads it
automatically in the DevTools.
## Implementation
- `wasm_builder` package is updated with the new `source_map` library,
which describes the source mapping entries.
- `wasm_builder`'s `InstructionsBuilder` is updated with the new public
members:
- `startSourceMapping`: starts mapping the instructions generated to
the given source code.
- `stopSourceMapping`: stops mapping the instructions generated to a
source code. These instructions won't have a mapping in the source
map.
- `CodeGenerator` sets the source file URI and location in the file
when:
- Starting compiling a new member
- Compiling an expression and statement
Change-Id: Ic8f723f7a154402c0d34710689db57d640b83b86
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370500
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This wasn't caught by default CI builders, because
default configurations use `pkg/dart2wasm/tool/compile_benchmark`
which passes all unknown flags to the compiler (for convenience
of local development) but `dart compile wasm` doesn't
Change-Id: I6a92d3f04848e027c92b1feee3d54e7efba9fd27
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/371661
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
Adds a flag users can use via
dart compile wasm \
--extra-compiler-option=--enable-experimental-wasm-interop
which allows code to import `dart:_wasm` and use import/export
pragmas.
Similar to how we have a way to import `dart:ffi`
dart compile wasm \
--extra-compiler-option=--enable-experimental-ffi
TEST=web/wasm/allow_import_export_pragmas_test (positive test)
TEST=web/wasm/reject_import_export_pragmas_test (negative test)
Change-Id: Ibdbbac6c3aa049b2759e96b7b749dd30ecc6aaed
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370063
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Jackson Gardner <jacksongardner@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>