summaryrefslogtreecommitdiff
path: root/src/ir/module-splitting.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Preserve Function HeapTypes (#3952)Thomas Lively2021-06-301-14/+15
| | | | | | | | | When using nominal types, func.ref of two functions with identical signatures but different HeapTypes will yield different types. To preserve these semantics, Functions need to track their HeapTypes, not just their Signatures. This PR replaces the Signature field in Function with a HeapType field and adds new utility methods to make it almost as simple to update and query the function HeapType as it was to update and query the Function Signature.
* [EH] Make tag's attribute encoding detail (#3947)Heejin Ahn2021-06-211-1/+0
| | | | | | | | | This removes `attribute` field from `Tag` class, making the reserved and unused field known only to binary encoder and decoder. This also removes the `attribute` parameter from `makeTag` and `addTag` methods in wasm-builder.h, C API, and Binaryen JS API. Suggested in https://github.com/WebAssembly/binaryen/pull/3946#pullrequestreview-687756523.
* [EH] Replace event with tag (#3937)Heejin Ahn2021-06-181-7/+7
| | | | | | | | | | | We recently decided to change 'event' to 'tag', and to 'event section' to 'tag section', out of the rationale that the section contains a generalized tag that references a type, which may be used for something other than exceptions, and the name 'event' can be confusing in the web context. See - https://github.com/WebAssembly/exception-handling/issues/159#issuecomment-857910130 - https://github.com/WebAssembly/exception-handling/pull/161
* [wasm-split] Add an option to emit a placeholder map (#3931)Thomas Lively2021-06-121-2/+7
| | | | | | The new instruction emits a file containing a map between placeholder index and the name of the split out function that placeholder is replacing in the table. This map is intended to be useful for debugging, as discussed in https://github.com/emscripten-core/emscripten/issues/14330.
* [wasm-split] Minimize names of newly created exports (#3905)Thomas Lively2021-06-011-2/+10
| | | | | | | | | wasm-split would previously use internal function names to create the external names of the functions that are newly exported from the primary module to be imported into the secondary module. When the input module contains full function names (as is commonly the case when emitting symbol maps), this caused the function names to be preserved as the export names, even when names are otherwise being stripped. To save on code size and properly anonymize functions, generate minimal export names when debuginfo is disabled instead.
* Minor wasm-split improvements (#3825)Thomas Lively2021-04-201-39/+35
| | | | | | | | | | | - Support functions appearing more than once in the table. It turns out we were assuming and asserting that functions would appear at most once, but we weren't making use of that assumption in any way. - Make TableSlotManager::getSlot take a function Name rather than a RefFunc expression to avoid allocating and leaking unnecessary expressions. - Add and use a Builder interface for building TableElementSegments to make them more similar to other module-level items.
* wasm-split: Update dylink section when growing table (#3791)Sam Clegg2021-04-091-0/+3
|
* RefFunc: Validate that the type is non-nullable, and avoid possible bugs in ↵Alon Zakai2021-04-081-2/+1
| | | | | | | | the builder (#3790) The builder can receive a HeapType so that callers don't need to set non-nullability themselves. Not NFC as some of the callers were in fact still making it nullable.
* [RT] Add type to tables and element segments (#3763)Abbas Mashayekh2021-04-061-6/+13
|
* [RT] Support expressions in element segments (#3666)Abbas Mashayekh2021-03-241-34/+50
| | | | | | This PR adds support for `ref.null t` as a valid element segment item. The abbreviated format of `(elem ... func $f $g...)` is kept in both printing and binary emitting if all items are `ref.func`s. Public APIs aren't updated in this PR.
* [reference-types] Support passive elem segments (#3572)Abbas Mashayekh2021-03-051-47/+62
| | | | | | | | | | | Passive element segments do not belong to any table, so the link between Table and elem needs to be weaker; i.e. an elem may have a table in case of active segments, or simply be a collection of function references in case of passive/declarative segments. This PR takes Table::Segment out and turns it into a first class module element just like tables and functions. It also implements early support for parsing, printing, encoding and decoding passive/declarative elem segments.
* Support comparing, subtyping, and naming recursive types (#3610)Thomas Lively2021-02-251-13/+0
| | | | | | | | | | | | | | | | | | | | | When the type section is emitted, types with an equal amount of references are ordered by an arbitrary measure of simplicity, which previously would infinitely recurse on structurally equivalent recursive types. Similarly, calculating whether an recursive type was a subtype of another recursive type could have infinitely recursed. This PR avoids infinite recursions in both cases by switching the algorithms from using normal inductive recursion to using coinductive recursion. The difference is that while the inductive algorithms assume the relations do not hold for a pair of HeapTypes until they have been exhaustively shown to hold, the coinductive algorithms assume the relations hold unless a counterexample can be found. In addition to those two algorithms, this PR also implement name generation for recursive types, using de Bruijn indices to stand in for inner uses of the recursive types. There are additional algorithms that will need to be switched from inductive to coinductive recursion, such as least upper bound generation, but these presented a good starting point and are sufficient to get some interesting programs working end-to-end.
* Remove assertions that prevent non-assertion builds (#3576)Alon Zakai2021-02-171-0/+1
| | | And fix errors from such a build.
* [reference-types] remove single table restriction in IR (#3517)Abbas Mashayekh2021-02-091-46/+83
| | | Adds support for modules with multiple tables. Adds a field for the table name to `CallIndirect` and updates the C/JS APIs accordingly.
* [module-splitting] Fix a crash when a function is exported twice (#3455)Thomas Lively2020-12-171-0/+4
| | | | | | | | | `ModuleSplitter::thunkExportedSecondaryFunctions` creates a thunk for each secondary function that needs to be exported from the main module. Previously, if a secondary function was exported twice, this code would try to create two thunks for it rather than just making one thunk and exporting it twice. This caused a fatal error because the second thunk had the same name as the first thunk and therefore could not be added to the module. This PR fixes the issue by creating no more than one thunk per function.
* Fix wasm-split name collision bug (#3447)Thomas Lively2020-12-161-3/+16
| | | | | | | | | During module splitting, a map is constructed from internal names to their corresponding export names. This code previously did not take into account the fact that the same internal name may be used by different kinds of entities (e.g. a table and a memory may have the same internal name), which resulted in the secondary module incorrectly using the same import name for all of the entities that shared an internal name. This PR fixes the problem by including the ExternalKind of the entity in the keys of the export map.
* [module-splitting] Allow splitting with non-const table offsets (#3408)Thomas Lively2020-12-011-82/+181
| | | | | | | | | | Extend the splitting logic to handle splitting modules with a single table segment with a non-const offset. In this situation the placeholder function names are interpreted as offsets from the table base global rather than absolute indices into the table. Since addition is not allowed in segment offset expressions, the secondary module's segment must start at the same place as the first table's segment. That means that some primary functions must be duplicated in the secondary segment to fill any gaps. They are exported and imported as necessary.
* Module splitting (#3317)Thomas Lively2020-11-121-0/+479
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.