| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
| |
There are several issues here that we can't fully handle, see #3378, but basically
we are comparing results between two separate wasm modules (and
a separate instance of each) - we can't really identify an identical
reference between such things. We can only compare things structurally,
for which we compare the types.
|
|
|
|
|
|
| |
I happened to notice that this was the one place that calls ReFinalize
without the module. That could error if the module is actually needed,
which the pass might use, based on the code (but rare enough that it's
never been an issue I guess).
|
|
|
|
|
|
|
|
| |
cost.h now requires costs be defined, or it halts at runtime. But the fuzzer
already emits those two, so define them to unbreak the fuzzer.
Both access a reference, so they should be at least as costly as a load.
I31New also allocates, which is very cheap on a generational GC, so do not
add much for that.
|
|
|
|
|
|
| |
Almost NFC, but adds a cost to DataDrop, 5, which tries to reflect
that it is costlier than a call (it calls into VM internals) but also not
much more, as it actually helps perf in the long term, so it should be
preferred where possible.
|
|
|
| |
The vacuum code can be deleted as it is handled by the default anyhow.
|
| |
|
|
|
|
| |
function references (#3357)
|
|
|
|
|
|
|
| |
types (#3358)
* [TypedFunctionReferences] Allow creation of literals with typed function types
* feedback
|
|
|
|
|
| |
We will need this for typed function references support, as then we need
to know full function signatures for all functions when we reach a ref.func,
whose type is then that signature and not the generic funcref.
|
|
|
|
|
|
|
|
|
|
| |
CallRef (#3355)
This is in preparation for CallRef, which takes a reference to a function
and calls it.
CallGraphPropertyAnalysis needs to be aware of anything that is not a
direct call, and "NonDirect" is meant to cover both CallIndirect and
CallRef.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- atomic.notify -> memory.atomic.notify
- i32.atomic.wait -> memory.atomic.wait32
- i64.atomic.wait -> memory.atomic.wait64
See WebAssembly/threads#149.
This renames instruction name printing but not the internal data
structure names, such as `AtomicNotify`, which are not always the same
as printed instruction names anyway. This also does not modify C API.
But this fixes interface functions in binaryen.js because it seems
binaryen.js's interface functions all follow the corresponding
instruction names.
|
|
|
|
| |
We change the AddrSize which causes all DW_FORM_addr to be written differently.
Depends on https://reviews.llvm.org/D91395
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This function does not return exact instruction names but more of
category names. But when there is a matching instruction, as in case of
`global.get/set` or `local.get/set`, it seems to return instruction
names. In that regard, this makes `getExpressionName`'s return values to
similar to that of real instruction names when possible, in case of
some atomic instructions and `memory.init/copy` and `data.drop`.
It is hard to make a test for this because this function is used in a
very limited way in the codebase, such as:
- When printing error messages
- When printing a stack instruction names, but only for control flow
instructions
- When printing instruction names in Metrics
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We used to check if a load's sign matters before hashing it. If the load does
not extend, then the sign doesn't matter, and we ignored the value there. It
turns out that value could be garbage, as we didn't assign it in the binary
reader, if it wasn't relevant. In the rewrite this was missed, and actually it's
not really possible to do, since we have just a macro for the field, but not the
object it is on - which there may be more than one.
To fix this, just always assign the field. This is simpler anyhow, and avoids
confusion not just here but probably when debugging.
The testcase here is reduced from the fuzzer, and is not a 100% guarantee
to catch a read of uninitialized memory, but it can't hurt, and with ASan it
may be pretty consistent.
|
| |
|
|
|
|
| |
Also slightly reorder some code in the binary writer headers, that
I noticed while looking for boilerplate.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds the capability to programatically split a module into a primary and
secondary module such that the primary module can be compiled and run before the
secondary module has been instantiated. All calls to secondary functions (i.e.
functions that have been split out into the secondary module) in the primary
module are rewritten to be indirect calls through the table. Initially, the
table slots of all secondary functions contain references to imported
placeholder functions. When the secondary module is instantiated, it will
automatically patch the table to insert references to the original functions.
The process of module splitting involves these steps:
1. Create the new secondary module.
2. Export globals, events, tables, and memories from the primary module and
import them in the secondary module.
3. Move the deferred functions from the primary to the secondary module.
4. For any secondary function exported from the primary module, export in
its place a trampoline function that makes an indirect call to its
placeholder function (and eventually to the original secondary function),
allocating a new table slot for the placeholder if necessary.
5. Rewrite direct calls from primary functions to secondary functions to be
indirect calls to their placeholder functions (and eventually to their
original secondary functions), allocating new table slots for the
placeholders if necessary.
6. For each primary function directly called from a secondary function, export
the primary function if it is not already exported and import it into the
secondary module.
7. Replace all references to secondary functions in the primary module's table
segments with references to imported placeholder functions.
8. Create new active table segments in the secondary module that will replace
all the placeholder function references in the table with references to
their corresponding secondary functions upon instantiation.
Functions can be used or referenced three ways in a WebAssembly module: they can
be exported, called, or placed in a table. The above procedure introduces a
layer of indirection to each of those mechanisms that removes all references to
secondary functions from the primary module but restores the original program's
semantics once the secondary module is instantiated. As more mechanisms that
reference functions are added in the future, such as ref.func instructions, they
will have to be modified to use a similar layer of indirection.
The code as currently written makes a few assumptions about the module that is
being split:
1. It assumes that mutable-globals is allowed. This could be worked around by
introducing wrapper functions for globals and rewriting secondary code that
accesses them, but now that mutable-globals is shipped on all browsers,
hopefully that extra complexity won't be necessary.
2. It assumes that all table segment offsets are constants. This simplifies the
generation of segments to actively patch in the secondary functions without
overwriting any other table slots. This assumption could be relaxed by 1)
having secondary segments re-write primary function slots as well, 2)
allowing addition in segment offsets, or 3) synthesizing a start function to
modify the table instead of using segments.
3. It assumes that each function appears in the table at most once. This isn't
necessarily true in general or even for LLVM output after function
deduplication. Relaxing this assumption would just require slightly more
complex code, so it is a good candidate for a follow up PR.
Future Binaryen work for this feature includes providing a command line tool
exposing this functionality as well as C API, JS API, and fuzzer support. We
will also want to provide a simple instrumentation pass for finding dead or
late-executing functions that would be good candidates for splitting out. It
would also be good to integrate that instrumentation with future function
outlining work so that dead or exceptional basic blocks could be split out into
a separate module.
|
|
|
|
|
|
| |
Also fix the order of walking children, which was wrong in the macro. What's nice
is that fixing it there would fix anything else using the macro automatically
(however, so far nothing else was affected by it).
|
|
|
|
| |
See discussion in #3303
|
|
|
| |
Also avoid needing to #undef DELEGATE all the time.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
X - Y <= 0
=>
X <= Y
That is true mathematically, but not in the case of an overflow, e.g.
X=10, Y=0x8000000000000000. X - Y is a negative number, so
X - Y <= 0 is true. But it is not true that X <= Y (as Y is negative, but
X is not).
See discussion in #3303 (comment)
The actual regression was in #3275, but the fuzzer had an easier time
finding it due to #3303
|
|
|
|
|
|
| |
We mistakenly tried to run all passes there, but should run only
the function ones.
Fixes #3333
|
|
|
|
|
|
|
|
|
| |
This is because we maybe need to reference the segments
during the start function. For example in the case of
pthreads we conditionally load passive segments during
start.
Tested in emscripten with: tests/runner.py wasm2js1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Expands on #3294:
* Scope names must be distinguished as either defs or uses.
* Error when a core #define is missing, which is less error-prone, as
suggested by @tlively
* Add DELEGATE_GET_FIELD which lets one define "get the field"
once and then all the loops can use it. This helps avoid boilerplate for
loops at least in some cases (when there is a single object on which
to get the field).
With those, it is possible to replace boilerplate in comparisons and
hashing logic. This also fixes a bug where BrOnExn::sent was not
scanned there.
Add some unit tests for hashing. We didn't have any, and hashing can be
subtly wrong without observable external effects (just more collisions).
|
|
|
|
|
| |
The asmFunc now sets the outer scope's `bufferView` variable
as well as its own internal views.
|
|
|
|
|
|
| |
bool(i32(x) % C_pot) -> bool(i32(x) & (C_pot - 1))
bool(i32(x) % min_s) -> bool(i32(x) & max_s)
For all other situations we already do this for (i32|i64).rem_s
|
| |
|
|
|
|
|
|
|
| |
Using addition in more places is better for gzip, and helps simplify the
optimizer as well.
Add a FinalOptimizer phase to do optimizations like our signed LEB tweaks, to
reduce binary size in the rare case when we do want a subtraction.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
To get an idea, this is a sample from the header:
switch (DELEGATE_ID) {
[..]
case Expression::Id::BlockId: {
DELEGATE_START(Block);
DELEGATE_FIELD_CHILD_LIST(Block, list);
DELEGATE_FIELD_SCOPE_NAME(Block, name);
DELEGATE_END(Block);
break;
}
A switch is defined (on some DELEGATE_ID that is provided). There is then
a case for each expression type, calling a delegate for each field type. This allows
a user to define the delegates it wants, then include this header.
This uses the new header in the copying logic, where the rewrite also
avoids recursion.
This fixes a missing BrOnExn::sent scanning in the existing
hashing/comparing code (which is what I used as a basis). When this is
used there, it will fix that bug.
|
|
|
| |
Specifically try to cleanup use of asm_v_wasm.h and asmjs constants.
|
|
|
| |
We no longer build modules that import `global.Math`.
|
| |
|
| |
|
|
|
|
|
| |
Const (#3218)
Also don't assume numbers are 32-bit.
|
|
|
| |
It was removed in #2841
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This simplifies the three size-related inlining flags, so that their
meanings are clearer. Also improve the comments and put them
in a consistent order in both files.
This should not make any difference in general, except that it is now
possible to have oneCallerInlineMaxSize > flexibleInlineMaxSize,
and we will inline a function with one caller if
flexibleInlineMaxSize < FUNCTION_SIZE <= oneCallerInlineMaxSize
which we would not before. As the defaults of the flags didn't fit that
case, this should not change anything for anyone not passing in
those specific inlining flags. For people that pass in those flags, this
PR makes more things possible.
Resolves the FIXME in that code, and is a refactoring before some
more inlining work I have planned.
|
| |
|
|
|
|
|
|
|
| |
Division and remainder do not have an implicit trap if the
right-hand side is a constant and not one of the dangerous
values there.
Also refactor ignoreImplicitTrap handling for clarity.
|
| |
|
|
|
| |
Move the checks for most unoptimizable expression types out into visitExpression and simplify some other code.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We can still make x * -1.0 cheaper for non-fastMath mode as:
x * -1.0 -> -0.0 - x
Should at least help baseline compilers.
Also it could enable further optimizations, e.g.:
a + b * -1
a + (-0.0 - b)
(a - 0.0) - b
a - b
|
|
|
| |
We can only pack memory if we know it is zero-filled before us.
|
| |
|
|
|
|
|
| |
Selectify turns an if-else into a select where possible. Previously we abandoned
hope if any part of the if had a side effect. But it's fine for the condition to have a
side effect, so long as moving it to the end doesn't invalidate the arms.
|
|
|
|
|
|
|
| |
Make select cost more realistic - it should be as good as a jmp, as in an if.
Add missing child visiting.
Shorten repetitive cases in switches.
|
| |
|
|
|
|
|
|
|
| |
Specifically, pick a simple positive canonical NaN as the NaN output, when the output
is a NaN. This is the same as what tools like wabt do.
This fixes a testcase found by the fuzzer on #3289 but it was not that PR's fault.
|
|
|
| |
Fixed bug in memory64-lowering pass for memory.size/grow
|