aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Wagner <mail@lukewagner.name>2015-04-30 19:00:51 -0500
committerLuke Wagner <mail@lukewagner.name>2015-04-30 19:00:51 -0500
commit070f56c5c59030e2d735973f3e10dbe2c87366db (patch)
tree639c4b0ee55d3390a6dc8e1d30b4268b29d2b1a0
parentd5093ea4f7804f88f56a83e9139456644a0fd195 (diff)
downloadnanowasm-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.md135
1 files changed, 120 insertions, 15 deletions
diff --git a/V1.md b/V1.md
index 8ad423d..06a5833 100644
--- a/V1.md
+++ b/V1.md
@@ -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.