IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an
email to Administrator. User accounts are meant only to access repo
and report issues and/or generate pull requests.
This is a purpose-specific Git hosting for
BaseALT
projects. Thank you for your understanding!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
The Google Test which binaryen uses is a commit sometime after version
1.10.0 looking at the readme. This PR updates the submodule to the
latest release version, and pins it to the 1.15.2 release.
We previously avoided optimizing acquire-release operations in
ConstantFieldPropagation to avoid having to replace them with
acquire-release fences, which are potentially more expensive than normal
acquire-release operations. However, in #7168 we reasoned that optimized
acquire gets of constant fields do not need to be replaced with fences
because they never necessarily synchronize with a set on another thread;
a get can be considered to read the same constant value from before the
set. Apply that reasoning to CFP and start optimizing acquire-release
operations without replacing them with fences.
RMW operations generally modify the field they access, so they inhibit
constant field propagation. The exceptions are xchg and cmpxchg
operations, which are like sets (conditional sets in the case of
cmpxchg) that happen to do gets as well. Just like for sets, we can
still optimize when the value written by xchg or cmpxchg happens to be
either the same constant value we know is already in the field or is a
copy from some instance of the same field.
There is potential for further optimization when we know an xchg or
cmpxchg sets a value that was read from some other field that we know
has the same constant value, but that's a missing optimization for plain
sets as well. There is also further optimization potential when we can
reason that a cmpxchg that would write a different value will never
perform the write because the comparison would never succeed. Add tests
with TODOs so we remember these potential optimizations in the future.
This only makes them mutable, but does not actually mutate them in any
way. Specifically they are now stored in an RAII context, currently a single
global one, but that later changes will be able to modify.
Both passes use StructUtils::StructScanner to analyze struct operations.
Add support for RMW operations to this utility and update its users to
provide the new `noteRMW` hook. Test that GTO and TypeRefining
optimizations work as expected in the presence of RMW operations, but
leave a proper implementation in ConstantFieldPropagation to a later PR.
To allow TypeRefining to refine field types based only on the
"replacement" operand and not the "expected" operand of cmpxchg
operations, update validation to allow the "expected" field to be a
supertype of the accessed field type as long as it is still equality
comparable.
https://github.com/WebAssembly/shared-everything-threads/pull/92
clarifies this intended typing in the upstream proposal.
Some of the expected output lines had drifted from what the auto-update
script generates. Fix them so the changes don't inadvertently make their
way into some unrelated PR.
Hopefully this will fix the current failure:
```
Run actions/setup-python@v1
with:
python-version: 3.x
architecture: x64
Error: Version 3.x with arch x64 not found
```
Without this we get an assertion later on,
child-typer.h:720: Assertion `func' failed.
Returns use the function to find the return values, so like local
get and set, we must error early on lacking a function.
Rather than pattern-match the very specific form we emit in ClusterFuzz
testcases, support any Uint8Array that contains what look like
wasm contents. This allows us to also process Fuzzilli testcases.
We previously asserted that the end of a nested expression is the same
when we parse it with a null context just to find its children and when
we parse it for real. It turns out that it is possible for the two end
positions to be different when the instruction is invalid in a way that
only the real parse catches. Return a normal error instead of asserting
because it is possible for invalid input to trigger this condition.
Fixes#7251.
The parser trusted the type when calling `setLocalName`, but that method
asserts of the local index is invalid. Avoid that assertion so we reach the
proper error message later.
FuzzTest is a state-of-the-art fuzzing framework. It supports writing
property-based fuzz targets very similar to googletest unit tests, where
the framework provides the arguments to the test function drawn from a
given domain. These fuzz tests are run continuously for one second each
when running the normal googletest unit tests, but FuzzTest also
supports building in "fuzzing mode" where the tests can be run
continuously with coverage-guided mutations until they find a bug.
Add FuzzTest as a third_party dependency that is not built by default.
To build FuzzTest and the fuzz tests that use it, set the CMake variable
`BUILD_FUZZTEST=ON`. To build in fuzzing mode, additionally set the
CMake variable `FUZZTEST_FUZZING_MODE=ON`.
One of FuzzTest's key features is its support for domain combinators,
which combine simple domains into more complex domains. For example, the
domain `VariantOf(InRange(0, 10), Arbitrary<std::string>())` produces a
std::variant that either holds an integer between 0 and 10 or an
arbitrary string. The set of available combinators is powerful enough to
build domains for arbitrarily structured types.
Use domain combinators to define a domain of WebAssembly type
definitions. The implementation of this domain follows the same general
structure as the existing heap type fuzzer: it chooses the size of rec
groups, then it chooses the supertypes and hierarchies for all the
definitions, then it generates the particular definitions. The
difference is that all random choices are made by the FuzzTest framework
rather than our own code. Whenever the domains of future choices will
depend on the outcome of the current choice, we use the `FlatMap`
combinator to make a choice from the current domain, then pass it to a
continuation that finishes constructing the final domain of types. This
leads to strange continuation-passing code, but allows us to recursively
construct the domain of type definitions.
The current implementation of the type definition domain is not ideal:
the tree of choices used to produce a particular set of type definitions
is deeper and narrower than it could be. Since a mutation of one choice
in the tree requires regenerating and changing the subtree of choices
rooted at the changed choice, having a narrower tree than necessary
means that small mutations are not as diverse as they could be and
having a deeper tree means that many mutations are larger than they
could be. The quality of the domain construction will be improved in the
future.
This patch implements text and binary encoding/decoding support for the
stack switching proposal. It does so by adapting the previous
typed-continunations implementation. Particular changes:
* Support for new `resume` encoding.
* Added support for `resume_throw` and `switch`.
* Feature flag `typed-continuations` has been renamed to
`stack-switching`.
A small unfortunate implementation detail is that the internal name
`Switch` was already taken by the `br_table` instruction, so I opted to
give the `switch` instruction the internal name `StackSwitch`.
A minor detail is that I have reordered the declarations/definitions of
the stack switching instructions such that they appear in ascending
order according to their opcode value (this is the same order that the
stack-switching explainer document present them in).
I can look into adding validation support in a subsequent patch.
The current approach doesn't work when CMake uses the clang-style
version of the flag (i.e. `-MD` instead of `/MD`) to choose the runtime.
Now that we are depending on CMake newer than version 3.15 we can
use its builtin support for choosing the MSVC runtime.
Rather than always do
await export()
now we might stash the Promise on the side, and execute it later, after
other stacks are executed and perhaps also saved.
To do this, rewrite the logic for calling the exports in a more flexible
manner. (That required altering the random seed in fuzz_shell_orders.wast,
to preserve the current order it was emitting.)
We do not fuzz with top-level await, so the output here looks a bit out
of order, but it does still end up with interleaved executions, which I think
is useful for fuzzing.
Move all the configuration of error and warning flags to after we have
added the third_party subdirectory and declared all of the 3P targets.
This ensures that only the basic configuration that e.g. affects ABI is
applied to the 3P code. This will make it easier to add 3P code that
does not compile cleanly with all the warnings and errors we enable for
our own code.
The interpreter incorrectly trapped on OOB addresses before evaluating
the vector operand. This bug became visible when the vector operand had
side effects. Reorder the code to fix the problem.
Instead of declaring a separate static library target for each
subdirectory, declare a single binaryen library target up front and then
add sources to it from each subdirectory.
Requires updating the minimum cmake version to avoid policy errors.
The next level `*` should have two spaces indentation from the previous
level. Currently the sentences under `Reference Types` have only one,
making them appear in the same level in the markdown format.
The current interpreter used in wasm-shell, the fuzzer, and
optimizations like precompute works by recursively walking the
expression tree and computing expression results as it goes. This kind
of recursive interpretation is not going to work for stack switching,
since stack switching requires stashing context away and restoring it
later. The recursive interpreter stores intermediate values on the
native stack and returns early to implement control flow, so there is no
way to suspend a computation and resume it later.
To support stack switching and support other use future interpreter use
cases such as running the full spec test suite and fuzzing multithreaded
programs, introduce a new interpreter that is not recursive and does not
store intermediate state that needs to persist beyond the execution of a
single instruction on the native stack. The new interpreter works by
iterating through instructions and visiting them one at a time in a
loop. The visitor pushes and pops values from a stack and signals
control flow via its return values. Control flow transfers are handled
by the main interpreter loop, so expressions are only visited when they
are actually executed. This design will not only support stack switching
and other features better than the old interpreter, but it will also
significantly decrease the amount of code in the interpreter.
In addition to the core interpreter loop, also lay out a skeleton of the
execution context for the new interpreter, including a call stack and
store. The code contains several TODOs describing how these runtime
structures will need to be extended to support interpreting the full
spec test suite, including the ability to interpret over multiple linked
instances at once.
Most of the actual interpretation of expressions is left as future work,
but the interpretation of `Const` expressions and i32.add is implemented
and tested in a new gtest file to demonstrate it working end-to-end. One
of the first milestones for the new interpreter will be getting real
spec tests running with it, at which point the gtest file can be
removed.
Imported and exported tables may get new items from the outside, so
we cannot infer values there.
This uncovered a bug with doing addRoot on tuples, which is also
fixed here. Also a tiny fix to debug logging.
Tags previously preserved only their signatures and not their heap types
in the IR, so there was no need or opportunity to classify their types
as public, even for tags that were imported or exported. When we updated
tags to preserve their heap types, we did not update the visibility
classification code to handle them. Update that code now.
In principle the optimizer should be using the fact that calls (or any
other expressions) that produce uninhabitable types will never return.
Previously, when DAE removed unused, uninhabitable results, the caller
would lose this useful information and have no way of determining that
the call would never return. Fix this by inserting an `unreachable`
after the call in the caller. Also run follow-up optimizations on the
caller because the new `unreachable` is very likely to lead to
improvements.
Now that we preserve tag heap types in the IR, it was possible for
SignaturePruning to optimize heap types used by tags in such a way that
the tag uses would no longer be valid. An ideal fix would be to have
SignaturePruning analyze and optimize tag usage as well as calls, but
for now just skip optimizing any heap type used in a tag.
Now that we preserve tag heap types in the IR, it was possible for
SignatureRefining to refine heap types used by tags in such a way that
the tag uses would no longer be valid. An ideal fix would be to have
SignatureRefining analyze and optimize tag usage as well as calls, but
for now just skip optimizing any heap type used in a tag.
This adds v8 from jsvu to CI, and a single lit test that uses it, to get started.
The tests are skipped on Alpine Linux, which jsvu is not compatible with. To
do so, we just delete the tests before running lit (for lack of a better
skipping mechanism, as `lit --xfail` is not supported in our lit on CI).
When the RMW operation can be proven not to change the accessed value,
optimize it to a simple atomic get instead. This is valid because a
write that does not change an in-memory value does not synchronize with
any subsequent reads of that value, since those reads can be considered
to be reading from the previous write.
Also optimize RMW operations on unshared structs to their non-atomic
equivalent operations. This can increase code size, but can also enable
follow-on optimizations of the simpler operations and can be less
expensive at runtime.
Update the escape analysis to note that RMW modification values and
cmpxchg replacement values can escape, but other operands do not escape.
When the ref operands are being replaced with locals, lower the RMW and
cmpxchg ops to the corresponding local and binary operations, being
careful to use scratch locals necessary to prevent reordering problems.
Add tests in a new file that will be ignored by the fuzzer until we have
better fuzzing support for RMW and cmpxchg ops.
Tags in WebAssembly syntactically refer to function heap types, but
Binaryen IR was previously storing signatures instead and reconstructing
heap types as necessary when emitting binaries. Before WasmGC this was
not a problem because the reconstructed types would be the same as the
original types, but with WasmGC round tripping function types through
Signature could lose information such as the rec group, the declared
supertype, and the finality from the original type. Store the original
heap type in the IR instead to stop losing this information.
Fixes#7219.
The note mentioned update_lit_checks.py in the first line, which made
update_lit_checks.py think that it _should_ update the test output, even
though the comment was explicitly about how it should not update the
test output. Reword the comment to avoid the problem.
Also make the check in the update script stricter for good measure.
Add missing validation rules checking that accessed fields have allowed
types. Copy the proposed upstream spec tests for this validation from
https://github.com/WebAssembly/shared-everything-threads/pull/85 with
minor changes to account for differences in supported text format and
to comment out unsupported tests.
Also implement interpretation for the RMW instructions and add spec
tests testing their execution. It is simpler to implement both
validation and interpretation at once because the proposed upstream
spec tests require both to pass.
When the struct reference is null, there is no struct type from which to
look up the proper field type when finalizing a struct RMW or cmpxchg
expression. We previously reused code for this case from StructGet, but
unlike StructGet, the RMW operations have additional operands that can
constrain the type of the retrieved struct field. Take these operands
into account when computing a type for the RMW expressions.
Now that we support sending additional values on these branches, we can
run their spec tests, so enable them. Also fix a bug with block naming
that the spec tests exposed.
We still cannot run the br_on_cast and br_on_cast fail spec tests, but
update the relevant comments to describe the new reason they fail.
We may move a rethrow into an invalid position when we mutate() etc. This finds
such invalid rethrows and replaces them with something trivial so that we validate.
To do so, use an expression stack rather than a control flow stack in the fixer,
as we need to see which child of a try the rethrow ends up being (so we need the
full path from it to the try).