Skip to content

Fill in a more detailed sketch for GC/DOM/Web API integration #275

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 5, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions FutureFeatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,7 @@ Options under consideration:

## GC/DOM Integration

* Access to certain kinds of Garbage-Collected (GC) objects from variables,
arguments, expressions.
* Ability to GC-allocate certain kinds of GC objects.
* Initially, things with fixed structure:
* JavaScript strings;
* JavaScript functions (as callable closures);
* Typed Arrays;
* [Typed objects](https://github.com/nikomatsakis/typed-objects-explainer/);
* DOM objects via WebIDL.
* Perhaps a rooting API for safe reference from the linear address space.
See [GC.md](GC.md).

## Linear memory bigger than 4GiB

Expand Down
161 changes: 161 additions & 0 deletions GC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# GC / DOM / Web API Integration

After the [MVP](MVP.md), to realize the [high-level goals](HighLevelGoals.md)
of (1) integrating well with the existing Web platform and (2) supporting
languages other than C++, WebAssembly needs to be able to:
* reference DOM and other Web API objects directly from WebAssembly code;
* call Web APIs (passing primitives or DOM/GC/Web API objects) directly from
WebAssembly without calling through JS; and
* efficiently allocate and manipulate GC objects directly from WebAssembly
code.

The following document is a high-level sketch of one approach for implementing
the above goals. *Consider the contents incomplete and expect change over
time.*

An important constraint is that, while WebAssembly should allow tight
integration with the [Web](Web.md), it should not bake in details
or Web standards dependencies that prevent execution in a
[non-Web embedding](NonWeb.md). This suggests a design (called
[opaque reference types](GC.md#opaque-reference-types) below) that hides the
details of JS and WebIDL behind Web-embedding-specific builtin modules.
On the other hand, WebAssembly can define a set of [native GC](GC.md#native-gc)
primitives that allowed portable GC code to be written regardless of the
host environment.

## Opaque reference types

The first feature is to extend [module imports](Modules.md#imports-and-exports)
to allow modules to import *opaque reference types*. "Opaque" means that the
reference type itself has no structural content and does not, e.g., define any
methods or fields. Once imported, an opaque reference type can be used in the
signature of other imported functions. Thus, the point of an opaque reference
type is to be passed to and returned from exported functions.

Reference types are allowed to be used as the types of locals, parameters
and return types. Additionally, references would be allowed as operands to
operators that treat their values as black boxes (`conditional`, `comma`,
`eq`, etc.). A new `dynamic_cast` operator would be added to allow checked
casting from any opaque reference type to any other opaque reference type.
Whether the cast succeeds is up to the host environment; WebAssembly itself
will define no a priori subtyping relationship.

For reasons of safety and limiting nondeterminism, imported opaque reference
types would not be able to be loaded from or stored to linear memory where they
could otherwise be arbitrarily aliased as integers. Instead, a new set of
operations would be added for allocating, deallocating, loading and storing
from integer-indexed cells that could hold references and were not aliasable by
linear memory.

With opaque reference types expressed as imports, host environments can provide
access to various kinds of reference-counted or garbage-collected host-defined
objects via builtin modules. While this design does not mandate a JS VM or
browser, it does allow natural integration with both
[JS](GC.md#js-integration) and [WebIDL](GC.md#webidl-integration)
in a Web environment.

### JS integration

Using [opaque reference types](GC.md#opaque-reference-types),
JS values could be made accessible to WebAssembly code through a builtin
`js` module providing:
* an exported `string` opaque reference type and exported functions
to allocate, query length, and index `string` values;
* an exported `object` opaque reference type and exported functions
that correspond with the ES5 meta-object protocol including the
ability to `[[Call]]` function objects;
* further exported opaque reference types for symbols and value
types (including SIMD);
* an exported `value` opaque reference type with exported functions for
constructing `value`s from integers, floats, `object`s, `string`s, etc and
with exported functions for querying the type of a `value` and extracting the
abovementioned payload types.

Since a browser's WebAssembly engine would have full knowledge of the `js`
builtin module, it should be able to optimize string/object accesses as well as
a normal JS JIT (perhaps even using the same JIT compiler).

### WebIDL integration

Using [opaque reference types](GC.md#opaque-reference-types), it would be
possible to allow direct access to DOM and Web APIs by mapping their
[WebIDL](http://www.w3.org/TR/WebIDL) interfaces to WebAssembly builtin module
signatures. In particular:
* WebIDL interfaces (like
[WebGLRenderingContextBase](https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14)
or [WebGLTexture](https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.9))
would map to exported [opaque reference types](GC.md#opaque-reference-types);
* methods of WebIDL interfaces would map to exported functions where the
receiver was translated into an explicit argument and WebIDL value
types were mapped to appropriate [local types](AstSemantics.md#local-types)
(e.g., [bindTexture](https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14)
would translate to `void (WebGLRenderingContextBase, int32, WebGLTexture?)`).

This high-level description glosses over many important details about WebIDL:

First, the WebIDL spec contains many JavaScript-specific details that are
unnecessary in a WebAssembly context. In particular, there are basically three
components specified by a WebIDL interface:

1. a signature declaration composed of language-independent data types (like
IEEE754 doubles and floats);
2. a set of basic wellformedness checks that are executed on the arguments of
the signature declared in (1); and
3. a JavaScript-specific algorithm that maps the arbitrary set of JavaScript
values passed to a WebIDL invocation to the signature declared by (1) and
checked by (2).

(1) and (2) of the WebIDL spec are meaningful to WebAssembly, but (3)
would effectively be skipped.

Another important issue is mapping WebIDL values types that aren't simple
[primitive types](http://www.w3.org/TR/WebIDL/#dfn-primitive-type):
* [Dictionary types](http://www.w3.org/TR/WebIDL/#idl-dictionary)
would [appear](http://www.w3.org/TR/WebIDL/#es-dictionary) to require
JS objects but are actually defined as values such that they can
be (and are, in various browser implementations) flattened to C structs.
Thus, a natural WebAssembly binding would be to map dictionaries to structs
in linear memory passed by reference (integer offset).
* The same goes for [sequence types](http://www.w3.org/TR/WebIDL/#idl-sequence).
* [Enumeration types](http://www.w3.org/TR/WebIDL/#es-enumeration) could be
mapped to canonical integers.
* [Union types](http://www.w3.org/TR/WebIDL/#idl-union) could be handled in
multiple ways. One option is to treat the union type itself as an importable
opaque reference type (when all the elements are themselves reference types).
Another option is to introduce an overload of each signature for each element
of the union type such that all calls passed a single element type and the
full Union Type was never explicitly represented in WebAssembly.
* [Callback function types](http://www.w3.org/TR/WebIDL/#es-callback-function)
could map to a `(function pointer, environment pointer)` closure pair.

Overall, the goal of mapping WebIDL to WebAssembly builtin modules is to avoid
the need to define a duplicate WebAssembly interface for all Web APIs. In
practice, some WebIDL patterns may have an unnatural or inefficient mapping
into WebAssembly such that new overloads and best practices would need to be
adopted. Over time, though, these rough edges would be ironed out leaving the
long term benefit of defining Web APIs with a single interface and ensuring
that JS and WebAssembly always had access to the same raw functionality.

## Native GC

In contract to *opaque* reference types, a second feature would be to allow
direct GC allocation and field access from WebAssembly code through
*non-opaque* reference types.

There is a lot of the design left to
consider for this feature, but a few points of tentative agreement are:
* To avoid baking in a single language's object model, define low-level GC
primitives (viz., structs and arrays) and allow the source language compiler
to build up features like virtual dispatch and access control.
* GC struct and array types would have associated *struct/array reference
types* that were similar to and symmetric with
[opaque reference types](GC.md#opaque-reference-types)
(just not opaque).
* The GC heap would be semantically distinct from linear memory and thus
the fields of GC objects could safely hold reference types (unlike linear
memory).
* The GC struct and array types could be passed to and from JavaScript
by reflecting the WebAssembly GC objects in JavaScript using the
[Typed Objects](https://github.com/nikomatsakis/typed-objects-explainer/)
proposal.

5 changes: 3 additions & 2 deletions Web.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ and the rest of the Web platform that have been considered:
perform N fetches and compile N copies.
- WebAssembly may later standardize a more direct way to create a thread that
doesn't involve creating a new Worker.
* Once [SIMD is supported](PostMVP.md#fixed-width-simd), a Web implementation of
WebAssembly would:
* Once [SIMD is supported](PostMVP.md#fixed-width-simd) WebAssembly would:
- Be statically typed analogous to [SIMD.js-in-asm.js][];
- Reuse specification of operation semantics (with TC39);
- Reuse backend implementation (same IR nodes).
* Once [GC is supported](GC.md), WebAssembly code would be able to reference
and access and JS, DOM, and general WebIDL-defined objects.

[CORS]: https://www.w3.org/TR/cors/
[subresource integrity]: https://www.w3.org/TR/SRI/
Expand Down