| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
Fixes #5629
|
| |
|
|
|
|
|
|
|
|
| |
Previously, the pointer type for newly emitted instructions was determined by
the type of the destination pointer on a memory.init instruction, but that did
not take into account that the destination pointer may be unreachable. Properly
look up the pointer type on the memory instead to fix the problem.
Fixes #5620.
|
|
|
|
|
|
|
|
|
| |
Repurpose makeBasicRef, makeCompoundRef to generate not just "constant"
refs but any reference, and use those to create StructNew/ArrayNew.
The key changes are to add makeCompoundRef to make(), and to make
the function call make() for children, where possible, instead of just
makeTrivial(). We also replace the i31-specific path with a call to
makeBasicRef which handles i31 among other things.
|
|
|
|
|
|
|
|
| |
Add support for memory and data segment module elements and treat them uniformly
with other module elements rather than as special cases. There is a cyclic
dependency between memories (or tables) and their active segments because
exported or accessed memories (or tables) keep their active segments alive, but
active segments for imported memories (or tables) keep their memories (or
tables) alive as well.
|
|
|
| |
When we remove a tee there, we must not change the type at all.
|
|
|
|
|
|
|
|
|
|
| |
All top-level Module elements are identified and referred to by Name, but for
historical reasons element and data segments were referred to by index instead.
Fix this inconsistency by using Names to refer to segments from expressions that
use them. Also parse and print segment names like we do for other elements.
The C API is partially converted to use names instead of indices, but there are
still many functions that refer to data segments by index. Finishing the
conversion can be done in the future once it becomes necessary.
|
|
|
|
| |
When removing a local.get we must replace it with something of the
identical type, and not make it non-nullable.
|
| |
|
|
|
|
|
| |
That code should only propagate unreachability, and not refine. If it refines when
we call finalize() then other code around it might end up invalid (as it could be
partially refined; see testcase).
|
|
|
|
| |
The pretty-printer will still serialize these using the old
func_subtype, array_subtype, and struct_subtype syntax, though.
|
|
|
|
|
|
|
|
|
| |
* Do not treat `atomic.fence` as using a memory
Update RemoveUnusedModuleElements so that it no longer keeps the memory alive
due to an `atomic.fence` instruction and update validation to allow modules to
use `atomic.fence` without a memory.
* update wasm2js tests
|
|
|
|
|
|
|
|
|
| |
* [NFC] Simplify initialization in RemoveUnusedModuleElements.cpp
Use copy-list-initialization to shorten the code and reduce visual redundancy.
* [NFC] Port remove-unused-module-elements_all-features.wast to lit
Port the test automatically using scripts/port_passes_tests_to_lit.py.
|
|
|
|
|
|
| |
Fix the relevant pointer and size expressions produced by MemoryPacking to be
i64s when working with 64-bit memories.
Fixes #5578.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Both isValidInConstantExpression and isSingleConstantExpression must look
recursively at the internals of a RefAs that externalizes and internalizes, or else
we might do something like externalize a local.get, which is not constant.
getLiteral must handle externalize/internalize as well, and return a properly-
modified literal.
Without these fixes the testcase hits different internal assertions, and we either
fail to recognize something is constant or not, or think that it is but fail to
produce a literal for it.
|
|
|
|
|
|
|
|
|
| |
Before this PR we iterated over an unordered set. Replace that with an
iteration on a vector. (Also, the value in the set was not even used, so
this should even be faster.)
Add random names in the fuzzer to types, the lack of which is I believe
the reason this was not detected before.
|
|
|
|
| |
Fixes #5584
|
|
|
|
|
|
|
|
|
|
| |
This fixes wasm-ctor-eval on evalling a GC data structure that contains a
field initialized with an externalized value.
Per the spec this is a constant instruction and I verified that V8 allows this.
Also add missing validation in wasm-ctor-eval of the output (which makes
debugging this kind of thing a little easier).
|
| |
|
|
|
|
| |
Fixes #5580
|
| |
|
|
|
|
|
|
|
|
|
| |
Add spec/bulk-array.wast, which contains an outline of the tests that will be
necessary for the upcoming bulk array instructions: array.copy (already
implemented), array.fill, array.init_data, and array.init_elem. Although the
test file does not actually contain any tests yet, it contains some setup code
defining types, globals, and element segments that the tests will use. Fix
miscellaneous bugs in parsing, validation, and printing to allow this setup code
to run without issues.
|
|
|
|
|
|
|
| |
To allow the external and internal reference values to be differentiated yet
round-trippable, set the `Literal` type to externref on external references, but
keep the gcData the same for both. The only exception is for i31 references, for
which the externalized version gets a `gcData` that contains a copy of the
original i31 literal.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
TypeMerging previously tried to merge types with their supertypes and siblings
in a single step, but this could cause a misoptimization in which a type was
merged with its parent's sibling without being merged with its parent, breaking
subtyping.
Fix the bug by merging with supertypes and siblings separately. Since we now
have multiple merging steps, also take the opportunity to run the sibling
merging step multiple times to exploit more merging opportunities.
Fixes #5556.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
The nesting limit of around 20 was enough to cause exponential blowup. A 20K
input file lead to a 2GB wasm in one case I saw (!) which takes many seconds to
fuzz.
Instead, reduce the limit, and also check if random tells us that the random
input is done; when that's done we should stop, which limits us to O(input size).
Also do this for non-nullable types, and handle that in globals (we cannot emit a
RefAsNulNull there, so switch the global type if necessary).
|
|
|
|
|
|
| |
Even with a 1% chance of a huge array, there is a second problem aside from
hitting an allocation failure, which is DoS - building such a huge array of
Literals takes noticeable time in the fuzzer. Instead, just limit array max sizes,
which is consistent with what we do for struct sizes etc.
|
|
|
|
|
|
|
|
|
|
| |
Previously we treated global.get as a constant expression and only
additionally verified that the target globals were immutable in some cases. But
global.get of a mutable global is never a constant expression, and further,
only imported globals are available in constant expressions unless GC is
enabled.
Fix constant expression validation to only allow global.get of immutable,
imported globals, and fix all the invalid tests.
|
|
|
|
| |
Only rarely return an uninhabitable subtype of an inhabitable one. This
avoids a major source of uninhabitability and immediate traps.
|
|
|
|
| |
In particular, the removed code path here that did a RefAsNonNull of a null
was causing a lot of code to just trap.
|
|
|
|
|
|
|
|
|
|
| |
Previously we emitted it early, and would then modify it in random ways
like other initial content. But this function is called frequently during
execution, so if we were unlucky and modded that function to trap then
basically all other functions would trap as well.
After fixing this, some places assert on not having any functions or types
to pick a random one from, so fix those places too.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
With this we generate random GC types that may be used in creating
instructions later.
We don't create many instructions yet, which will be the next step after
this.
Also add some trivial assertions in some places, that have helped
debugging in the past.
Stop fuzzing TypeMerging for now due to #5556 , which this PR
uncovers.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This became an issue because the timeline was this:
* We added non-nullable locals support. At the time, obviously
CodePushing did not require any fixups for that, since it just moved
code forward in a single block (and not past any uses). So we marked
the pass as not needing such fixups.
* We added pushing of code into ifs. But moving code into an if
can affect non-nullable validation since it is based on block scoping.
So we need to remove the mark on the pass, which will make it check and
apply fixups as necessary. See the testcase for an example.
|
|
|
| |
We'd need to handle contravariance to optimize them.
|
|
|
|
|
|
|
| |
For now just skip them, to avoid problems. In the future we should look
into modifying their children, when possible.
Fixes #5463
|
|
|
|
|
|
|
|
| |
As with #5535, this was not noticed because it can only happen on very
small modules where the param/result type appears nowhere else but
in a function signature.
Use generic heap type scanning, which also scans into struct and array
types etc.
|
|
|
|
|
|
| |
In #5437 we updated type printing so that printing a heap type would print its
name in addition to its contents. We had already been separately printing type
names in the type fuzzer, so after that change we were printing each type name
twice. Remove the redundant printing in the fuzzer to fix the error.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some valid GC types, such as non-nullable references to bottom heap types and
types that contain non-nullable references to themselves, are uninhabitable,
meaning it is not possible to construct values of those types. This can cause
problems for the fuzzer, which generally needs to be able to construct values of
arbitrary types.
To simplify things for the fuzzer, introduce a utility for transforming type
graphs such that all their types are inhabitable. The utility performs a DFS to
find cycles of non-nullable references and breaks those cycles by introducing
nullability.
The new utility is itself fuzzed in the type fuzzer.
|
|
|
|
| |
Without this we hit an assertion on trying to write the binary, on a missing
heap type.
|
|
|
|
|
| |
We can't just skip host limits (#5534) but must also ignore execution at that
point, as optimizations can change the results if they change whether we reach
a host limit.
|
|
|
|
|
|
| |
This was not noticed before because normally if there is a function type
with multiple results then there is also a function with that property. But
it is possible to make small testcases without such a function, and one might
be imported etc., so we do need to validate this.
|
|
|
|
| |
This makes it possible to get the JSPI'ed version of the function from the
function table.
|
|
|
|
|
|
|
|
|
| |
This is a (more) standard name for `array.init_static`. (The full upstream name
in the spec repo is `array.new_canon_fixed`, but I'm still hoping we can drop
`canon` from all the instruction names and it doesn't appear elsewhere in
Binaryen).
Update all the existing tests to use the new name and add a test specifically to
ensure the old name continues parsing.
|
|
|
|
|
|
|
|
| |
To match the standard instruction name, rename the expression class without
changing any parsing or printing behavior. A follow-on PR will take care of the
functional side of this change while keeping support for parsing the old name.
This change will allow `ArrayInit` to be used as the expression class for the
upcoming `array.init_data` and `array.init_elem` instructions.
|
|
|
|
|
| |
With this, the sourcemap testcase outputs the exact same thing as the input.
Followup to #5504
|
|
|
|
|
| |
Without this fix, the common idiom of using `INT_MAX` in C source to mean an
unlimited number of waiters should be woken up actually compiled down to an
argument of -1 in JS, causing zero waiters to be woken.
|
|
|
|
|
|
|
|
|
|
| |
Before, a single ctor with GC worked, but any subsequent ones simply dropped
the globals from the previous ones, because we were missing an addGlobal in
an important place.
Also, we can get confused about which global names are in use in the module, so fix
that as well by storing them directly (we keep removing and re-adding globals, so
we can't use the normal module mechanism to find which names are in use).
|