diff options
| author | Luke Wagner <mail@lukewagner.name> | 2015-04-30 19:00:51 -0500 |
|---|---|---|
| committer | Luke Wagner <mail@lukewagner.name> | 2015-04-30 19:00:51 -0500 |
| commit | 070f56c5c59030e2d735973f3e10dbe2c87366db (patch) | |
| tree | 639c4b0ee55d3390a6dc8e1d30b4268b29d2b1a0 | |
| parent | d5093ea4f7804f88f56a83e9139456644a0fd195 (diff) | |
| download | nanowasm-design-070f56c5c59030e2d735973f3e10dbe2c87366db.tar.gz | |
Fill in V1.md
Fill in with the discussion from the previous GDoc to start discussion here.
| -rw-r--r-- | V1.md | 135 |
1 files changed, 120 insertions, 15 deletions
@@ -11,28 +11,133 @@ low-level and precise descriptions of: * [text assembly language](TODO.md) * [opcode semantics](TODO.md) -(Currently in the process of importing/simplifying state of discussion on https://docs.google.com/document/d/1YwPHB08b0nkISqKBNBWmke2Gb0obPXDQaXTGRVJ37xo) - ## Module structure - * TODO + * At the top level, a module would be ELF-like: a squence of sections which declare their type and byte-length. + * Sections with unknown types would be skipped without error. + * Standardized section types: + * index-space section (see [Backwards compatible evolution](V1.md#backwards-compatible-evolution) below) + * module import section (see [Module imports](V1.md#module-imports) below) + * globals section (constants, signatures, variables) + * code section (see [Code representation](V1.md#code-representation) below) + * heap initialization section (see [Heap](V1.md#heap) below) ## Code representation - * TODO + * Functions are the basic executable unit of code. + * The [code section](V1.md#module-structure) begins with a table of functions containing the signatures, + offsets and byte-lengths of each function followed by the list of function bodies. + * This allows parallel and streaming decoding, validation and compilation. + * Abstractly, a function body consists of a set of typed variable bindings and an AST closed under these bindings. + * The AST is composed of two primary kinds of nodes: statements and expressions. + * Expressions are typed; validation consists of simple, bottom-up, O(1) type checking. + * Why not a stack-, register- or SSA-based bytecode? + * Smaller binary encoding: [JSZap](http://research.microsoft.com/en-us/projects/jszap), + [Slim Binaries](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.108.1711) + * [Polyfill prototype](https://github.com/WebAssembly/polyfill) shows simple and efficient translation + to asm.js. + * Control flow is structured (no goto) + * Simple and size-efficient binary encoding and compilation. + * Most (reducible) goto-based control flow can be transformed into structured control flow with a + [relooping](http://mozakai.blogspot.com/2012/05/reloop-all-blocks.html) algorithm. + * The [signature-restricted proper tail-call](https://github.com/WebAssembly/spec/blob/master/EssentialPostV1Features.md#signature-restricted-proper-tail-calls) + feature would allow efficient compilation of both direct and indirect goto. + * For specific details, see the [opcode semantics](TODO.md). + +## Binary format + * This is the format natively decoded by the browser. + * Most of this is tentative and based on the experimental polyfill prototype: + * Pre-order serialization of the AST described [above](V1.md#code-representation). + * Good for efficient single-pass validation+compilation and polyfill. + * Since expression result type is known from the context in a preordering, segregate the index space + of opcodes by kind (statement vs. expression) and result-type (i32-producing vs. f32-producing) to + allow overlapping and thus smaller encoding. + * Do not compete with generic compression algorithm by trying to suck out every last bit; assume a + generic compression algorithm is applied on top of the binary encoding. + * Given generic compression, is there any win from having a binary format over a text format? + Text is so compressible! + * The experimental results from the [polyfill prototype](https://github.com/WebAssembly/polyfill) are + "yes, the compressed binary format is about 20-30% smaller than gzipped asm.js". That's just asm.js, + not some ideal text language, but given that [compressed asm.js is about the same size as compressed + machine code](http://mozakai.blogspot.com/2011/11/code-size-when-compiling-to-javascript.html), asm.js + isn't a bad sample point. Other experimental evidence is welcome of course. + * Also, decoding a binary format with indices as variable names is much faster than a human-readable + text format with names that require dictionary lookups. The + [polyfill prototype](https://github.com/WebAssembly/polyfill) binary format is about TODOx faster + to decode than asm.js is to parse. -## Code loading - * TODO +## Text format +* This purpose of this format is to support: + * View source on a WebAssembly module. + * Presentation in debugging tools when source maps aren't present (which is necessarily the case with v.1). + * Writing WebAssembly code directly for reasons including pedagogical, experimental, debugging, or + optimization. +* Given that the code representation is actually an AST, the text syntax would also contain nested + statements and expressions (instead of the linear list of instructions most assembly languages have). +* There is no requirement to use JS syntax; this format is not intended to be evaluated or translated + directly into JS. +* TODO: there is no real proposal yet + +## Code loading and imports + * The loadable unit of WebAssembly code is a *module*. + * WebAssembly modules can be loaded declaratively (via import on page load) or imperatively (via API call) + and can be compiled dynamically (from bytes, as defined by the binary format). + * A natural integration point with JS would be to have WebAssembly modules be reflected to JS + as ES6 Modules. + * The module interface would mostly hide whether the module was JS or WebAssembly (except for things + like `fun.toSource()`) would allow webapps to be naturally composed of both JS and WebAssembly modules. + * ES6 Modules can be loaded declaratively (via imports) or imperatively (via API calls); this would allow + WebAssembly modules to be loaded dynamically. + * The ES6 Module API also allows dynamically generated modules (viz., a module can be compiled froma string); + building on this, WebAssembly modules could be dynamically compiled from an ArrayBuffer of bytes. + * Just like ES6 modules, WebAssembly modules could import other modules (JS or WebAssembly); this would + replace asm.js [FFIs](http://asmjs.org/spec/latest/index.html#external-code-and-data). -## Linear address space - * TODO +## Heap + * In v.1, when a WebAssembly module is loaded, it always gets a new private heap. + * The [dynamic linking](FutureFeatures.md#dynamic-linking) feature is necessary for two modules + to share the same heap. + * Modules can specify heap size and initialization data (data, rodata, bss). + * Modules can specify whether the heap is growable (via sbrk) and/or aliasable by JS (via an ArrayBuffer). + * A module's is not, semantically, a JS typed array, but it can be *aliased* by JS (if declared). + * To keep an ArrayBuffer's length immutable, resizing a module's heap detaches any existant ArrayBuffers. + * Modules throw on out-of-bound access. + * A module can declare that low-memory (and how much) is to be considered out-of-bounds. + * A stronger rule that allows slightly more optimization and tighter security would be to additionally + "poison" the heap after any out-of-bound so that it cannot be accessed again. + * Loads and stores are guaranteed to work when unaligned (though possibly very slowly). ## Function pointers - * TODO - + * In v.1, function pointers are local to a single module. + * The [dynamic linking](FutureFeatures.md#dynamic-linking) feature is necessary for two modules + to pass function pointers back and forth. + * Function pointers have a unique type per signature that is coercible to and from an int32. + * The heap can only load/store integer types, so a coercion is required when loading/storing + function pointers to the heap. + * Values of function pointer types are comparable for equality and callable. + * Function pointer values are created via special AddressOf ops that take a function's index + and returns a function pointer value unique to the function index. + ## Backwards compatible evolution - * TODO - -## API access - * TODO + * Restating the [high-level goal](HighLevelGoals.md): Design to maintain the versionless, feature-testing and + backwards-compatible evolution story of the web; engines should not need multiple, versioned decoders. + * Refining this into goals: + 1. New versions of WebAssembly shouldn't require new decoders, just new cases in the existing decoder. + 2. Browsers should be able to implement and ship new features of future versions (as they do now with JS) + without worrying about index space conflicts in the binary format (global ordering problem). + 3. WebAssembly modules should be able to test for the existence of features and either load different code + that doesn't depend on the feature or polyfill the feature. + * TODO: more explanation required for how to realize these goals. +## Non-browser embedding + * Host environments can define builtin modules that are implemented natively and can be imported directly by WebAssembly modules. + * For example, a WebAssembly shell might define a builtin "stdio" library with an export "puts". + * Another example, in the browser, would be the WebIDL support mentioned in [future features](FutureFeatures.md). + * Where there is overlap between the browser and popular non-browser environments, a shared spec could be proposed, but this would be separate from the WebAssembly spec. + * A symmetric example in JS would be the [Loader](http://whatwg.github.io/loader) spec, intended to be implemented by both browsers and node.js. + * However, one would expect a fair amount of variance between the browser and various shell environments on core APIs like network and file I/O. + * To allow writing portable POSIX-like code (that ran in both browser and other environments), the WebAssembly community would develop a shared repository of WebAssembly code that mapped between a POSIX-like interface and the host's builtin modules at either compile-time (#ifdefs) or run-time (feature-testing and conditional loading; both v.1 features). + * A symmetric example in JS would be the [ES6 Module Loader polyfill](https://github.com/ModuleLoader/es6-module-loader) library. + * The WebAssembly spec would thus not try to define any large portable libc-like library. + * However, certain features that are core to WebAssembly semantics that are found in native libc would be part of the core WebAssembly spec as either primitive opcodes or a special builtin module (e.g., sbrk(), mmap()). + ## Security - * TODO + * No different from a security pov than if the WebAssembly module was asm.js. |
