summaryrefslogtreecommitdiff
path: root/src/passes/Asyncify.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Use const modifier when dealing with types (#3064)Daniel Wirtz2020-08-201-2/+2
| | | Since they make the code clearer and more self-documenting.
* Replace Type::expand() with an iterator-based approach (#3061)Daniel Wirtz2020-08-191-8/+7
| | | This leads to simpler code and is a prerequisite for #3012, which makes it so that not all `Type`s are backed by vectors that `expand` could return.
* Fix typo in Asyncify comment (#3031)Nikita Baksalyar2020-08-101-1/+1
|
* Asyncify verbose option (#3022)Alon Zakai2020-08-061-4/+45
| | | | | | | | | | | | | | | | This logs out the decisions made about instrumenting functions, which can help figure out why a function is instrumented, or to get a list of what might need to be. As the test shows, it can print things like this: [asyncify] import is an import that can change the state [asyncify] calls-import can change the state due to import [asyncify] calls-calls-import can change the state due to calls-import [asyncify] calls-calls-calls-import can change the state due to calls-calls-import (the test has calls-calls-calls-import => calls-calls-import => calls-import -> import).
* Add a builder.makeConst helper template (#2971)Alon Zakai2020-07-211-10/+9
|
* Asyncify liveness analysis (#2890)Alon Zakai2020-06-231-8/+62
| | | | | | | | | This finds out which locals are live at call sites that might pause/resume, which is the set of locals we need to actually save/load. That is, if a local is not alive at any call site in the function, then it's value doesn't need to stay alive while sleeping. This saves about 10% of locals that are saved/loaded, and about 1.5% in final code size.
* Asyncify: Instrument indirect calls from functions in add-list or only-list ↵Alon Zakai2020-06-171-18/+49
| | | | | | | | | | | | | | | | | | | | | | (#2913) When doing manual tuning of calls using asyncify lists, we want it to be possible to write out all the functions that can be on the stack when pausing, and for that to work. This did not quite work right with the ignore-indirect option: that would ignore all indirect calls all the time, so that if foo() calls bar() indirectly, that indirect call was not instrumented (we didn't check for a pause around it), even if both foo() and bar() were listed. There was no way to make that work (except for not ignoring indirect calls at all). This PR makes the add-list and only-lists fully instrument the functions mentioned in them: both themselves, and indirect calls from them. (Note that direct calls need no special handling - we can just add the direct call target to the add-list or only-list.) This may add some overhead to existing users, but only in a function that is instrumented anyhow, and also indirect calls are slow anyhow, so it's probably fine. And it is simpler to do it this way instead of adding another list for indirect call handling.
* Asyncify: Add an "add list", rename old lists (#2910)Alon Zakai2020-06-121-48/+87
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Asyncify does a whole-program analysis to figure out the list of functions to instrument. In emscripten-core/emscripten#10746 (comment) we realized that we need another type of list there, an "add list" which is a list of functions to add to the instrumented functions list, that is, that we should definitely instrument. The use case in that link is that we disable indirect calls, but there is one special indirect call that we do need to instrument. Being able to add just that one can be much more efficient than assuming all indirect calls in a big codebase need instrumentation. Similar issues can come up if we add a profile-guided option to asyncify, which we've discussed. The existing lists were not good enough to allow that, so a new option is needed. I took the opportunity to rename the old ones to something better and more consistent, so after this PR we have 3 lists as follows: * The old "remove list" (previously "blacklist") which removes functions from the list of functions to be instrumented. * The new "add list" which adds to that list (note how add/remove are clearly parallel). * The old "only list" (previously "whitelist") which simply replaces the entire list, and so only those functions are instrumented and no other. This PR temporarily still supports the old names in the commandline arguments, to avoid immediate breakage for our CI.
* Handle tuples in Asyncify call support (#2743)Thomas Lively2020-04-091-9/+41
| | | | | Instead of adding globals for hardcoded basic types, traverse the module to collect all call types that might need to be handled and emit a global for each of them. Adapted from #2712.
* Revert to using globals in Asyncify call support (#2719)Thomas Lively2020-04-011-71/+53
| | | | | | | | This reverts commit 5ddda8d2e6a3287ff6adcd69493e1e1c8b6c3872. We decided it would be easier to allow tuple-typed globals than to make calls work here after all. Reverts that change, but keeps small improvements it made for clarity.
* Convert Asyncify fake globals to fake calls. NFC (#2706)Alon Zakai2020-03-251-46/+71
| | | | | This will be easier to extend for tuples. Also add more clarifying comments.
* Support tuple locals in Asyncify (#2696)Thomas Lively2020-03-171-28/+46
| | | Iterate over tuple locals and separately load or store each component.
* Asyncify: Fix wasm-only instrumentation of unnamed imports (#2682)Alon Zakai2020-03-051-23/+39
| | | | | | | | | | | | | We assumed that the imports were already named (in their internal name) properly. When processing a binary file without names, or if the names don't match in general, that's not true. To fix this, use ModuleUtils::renameFunctions to do a proper renaming up front. Also fix renameFunctions to not assert on the case of renaming a function to the same name it already has. Helps #2680
* Expose asyncify state via a getter (#2679)Alon Zakai2020-03-041-1/+16
| | | | | | | | | | Normally, a wrapper has to track state separately to know when to unwind/rewind and when to actually call import functions. Exposing Asyncify state can help avoid this duplication and avoid subtle bugs when internal and wrapper state get out of sync. Since this is a tiny function and it's useful for any Asyncify embedder, I've decided to expose it by default rather than hide behind an option.
* Handle indirect calls in CallGraphPropertyAnalysis (#2624)Alon Zakai2020-01-241-1/+2
| | | | | | | | | | | | | We ignored them, which is a bad default, as typically they imply we can call anything in the table (and the table might change). Instead, notice indirect calls during traversal, and force the user to decide whether to ignore them or not. This was only an issue in PostEmscripten because the other user, Asyncify, already had indirect call analysis because it needed it for other things. Fixes a bug uncovered by #2619 and fixes the current binaryen roll.
* [NFC] Enforce use of `Type::` on type names (#2434)Thomas Lively2020-01-071-43/+45
|
* Move Type-related functions into Type class (NFC) (#2556)Heejin Ahn2019-12-291-3/+3
| | | | | | | | | | | Several type-related functions currently exist outside of `Type` class and thus in the `wasm`, effectively global, namespace. This moves these functions into `Type` class, making them either member functions or static functions. Also this renames `getSize` to `getByteSize` to make it not to be confused with `size`, which returns the number of types in multiple types. This also reorders the order of functions in `wasm-type.cpp` to match that of `wasm-type.h`.
* Remove FunctionType (#2510)Thomas Lively2019-12-111-6/+6
| | | | | | | | | | | | | | | | | Function signatures were previously redundantly stored on Function objects as well as on FunctionType objects. These two signature representations had to always be kept in sync, which was error-prone and needlessly complex. This PR takes advantage of the new ability of Type to represent multiple value types by consolidating function signatures as a pair of Types (params and results) stored on the Function object. Since there are no longer module-global named function types, significant changes had to be made to the printing and emitting of function types, as well as their parsing and manipulation in various passes. The C and JS APIs and their tests also had to be updated to remove named function types.
* Add string parameter to WASM_UNREACHABLE (#2499)Sam Clegg2019-12-051-1/+1
| | | | | This works more like llvm's unreachable handler in that is preserves information even in release builds.
* Multivalue type creation and inspection (#2459)Thomas Lively2019-11-221-1/+1
| | | | | | | | | | | | | Adds the ability to create multivalue types from vectors of concrete value types. All types are transparently interned, so their representation is still a single uint32_t. Types can be extracted into vectors of their component parts, and all the single value types expand into vectors containing themselves. Multivalue types are not yet used in the IR, but their creation and inspection functionality is exposed and tested in the C and JS APIs. Also makes common type predicates methods of Type and improves the ergonomics of type printing.
* Refactor a CallGraphPropertyAnalysis helper [NFC] (#2441)Alon Zakai2019-11-181-41/+33
| | | | | | | | | | | This moves code out of Asyncify into a general helper class. The class automates scanning the functions for a property, then propagating it to functions that call them. In Asyncify, the property is "may call something that leads to sleep", and we propagate backwards to callers, to find all those that may sleep. This will be useful in a future exceptions-optimizing pass I want to write, where the property will be "may throw". We will then be able to remove exceptions overhead in cases that definitely do not throw.
* Add ModAsyncify* passes (#2404)Alon Zakai2019-10-231-1/+145
| | | | | | | | | | | | | | | | | | | | | | | | | | | | These passes are meant to be run after Asyncify has been run, they modify the output. We can assume that we will always unwind if we reach an import, or that we will never unwind, etc. This is meant to help with lazy code loading, that is, the ability for an initially-downloaded wasm to not contain all the code, and if code not present there is called, we download all the rest and continue with that. That could work something like this: * The wasm is created. It contains calls to a special import for lazy code loading. * Asyncify is run on it. * The initially downloaded wasm is created by running --mod-asyncify-always-and-only-unwind: if the special import for lazy code loading is called, we will definitely unwind, and we won't rewind in this binary. * The lazily downloaded wasm is created by running --mod-asyncify-never-unwind: we will rewind into this binary, but no longer need support for unwinding. (Optionally, there could also be a third wasm, which has not had Asyncify run on it, and which we'd swap to for max speed.) These --mod-asyncify passes allow the optimizer to do a lot of work, especially for the initially downloaded wasm if we have lots of calls to the lazy code loading import. In that case the optimizer will see that those calls unwind, which means the code after them is not reached, potentially making lots of code dead and removable.
* Show the unescaped name in Asyncify pattern warnings (#2351)Alon Zakai2019-09-231-3/+5
| | | | | | | | | This is part of the fix for https://logs.chromium.org/logs/emscripten-releases/buildbucket/cr-buildbucket.appspot.com/8901492015302662960/+/steps/Emscripten_testsuite__upstream__other_/0/stdout Specifically it fixes that the name shown there should not be escaped. Followup for #2344
* asyncify: support *-matching in whitelist and blacklist (#2344)Beuc2019-09-231-32/+70
| | | See emscripten-core/emscripten#9381 for rationale.
* Fix typo in Asyncify (#2346)Beuc2019-09-191-2/+2
|
* Add asserts in Asyncify (#2338)Alon Zakai2019-09-131-7/+84
| | | | | With the optional asserts, we throw if we see an unwind begin in code that we thought could never unwind (say, because the user incorrectly blacklisted it). Helps with emscripten-core/emscripten#9389
* More response file support in asyncify: whitelist/blacklist (#2335)Alon Zakai2019-09-081-2/+10
|
* Support response files, and use that in Asyncify (#2319)Alon Zakai2019-08-301-2/+10
| | | See emscripten-core/emscripten#9206, the asyncify names can need complex escaping, so this provides an escape hatch.
* Proper Asyncify list name handling (#2275)Alon Zakai2019-07-311-0/+3
| | | | | The lists are comma separated, but the names can have internal commas since they are human-readable. This adds awareness of bracketing things, so void foo(int, double) is parsed as a single function name, properly. Helps emscripten-core/emscripten#9128
* Python3-ify check.py and auto_update_tests.py (#2270)Alon Zakai2019-07-311-0/+4
| | | | | I fixed flatten.bin.txt which seems to have just had some corrupted data, and I removed some fancy unicode from the spec comments tests, which I'm not sure it's important enough to figure out how to fix. Fixes #1691
* Asyncify: whitelist and blacklist support (#2264)Alon Zakai2019-07-261-16/+97
| | | | | | | | | The blacklist means "functions here are to be ignored and not instrumented, we can assume they never unwind." The whitelist means "only these functions, and no others, can unwind." I had hoped such lists would not be necessary, since Asyncify's overhead is much smaller than the old Asyncify and Emterpreter, but as projects have noticed, the overhead to size and speed is still significant. The lists give power users a way to reduce any unnecessary overhead. A slightly tricky thing is escaping of names: we escape names from the names section (see #2261 #1646). The lists arrive in human-readable format, so we escape them before comparing to the internal escaped names. To enable that I refactored wasm-binary a little bit to provide the escaping logic, cc @yurydelendik If both lists are specified, an error is shown (since that is meaningless). If a name appears in a list that is not in the module, we show a warning, which will hopefully help people debug typos etc. I had hoped to make this an error, but the problem is that due to inlining etc. a single list will not always work for both unoptimized and optimized builds (a function may vanish when optimizing, due to duplicate function elimination or inlining). Fixes #2218.
* Finalize tail call support (#2246)Thomas Lively2019-07-231-0/+6
| | | | Adds tail call support to fuzzer and makes small changes to handle return calls in multiple utilities and passes. Makes larger changes to DAE and inlining passes to properly handle tail calls.
* Simpify PassRunner.add() and automatically parallelize parallel functions ↵Alon Zakai2019-07-191-2/+2
| | | | | | | | | (#2242) Main change here is in pass.h, everything else is changes to work with the new API. The add("name") remains as before, while the weird variadic add(..) which constructed the pass now just gets a std::unique_ptr of a pass. This also makes the memory management internally fully automatic. And it makes it trivial to parallelize WalkerPass::run on parallel passes. As a benefit, this allows removing a lot of code since in many cases there is no need to create a new pass runner, and running a pass can be just a single line.
* Cleanups after renaming Bysyncify to Asyncify (#2228)Alon Zakai2019-07-161-6/+7
| | | | | * Clarify the difference between old and new Asyncify. * Remove the old --bysyncify pass option.
* Bysyncify => Asyncify (#2226)Alon Zakai2019-07-151-0/+1116
After some discussion this seems like a less confusing name: what the pass does is "asyncify" code, after all. The one downside is the name overlaps with the old emscripten "Asyncify" utility, which we'll need to clarify in the docs there. This keeps the old --bysyncify flag around for now, which is helpful for avoiding temporary breakage on CI as we move the emscripten side as well.