Skip to content

Runtime

Daniel Wirtz edited this page May 26, 2019 · 27 revisions

An AssemblyScript runtime adds support for the parts of memory management and garbage collection that can't be performed at compile-time, but must be performed during runtime, as the name suggest.

There are currently five variations to pick from using the --runtime parameter:

  • --runtime full
    TLSF memory allocator and PureRC garbage collector with the necessary exports to create managed objects externally. This is the default.
  • --runtime half
    Like full but without the exports. Useful where no high-level interaction with the host is required, so the optimizer can eliminate what's dead code.
  • --runtime stub
    Minimal arena memory allocator without support for freeing memory (no garbage collection) with the necessary exports to create managed objects externally.
  • --runtime none
    Like stub but without the exports. Essentially evaporates after optimizations.
  • --runtime pathToYourImplementation
    The hard way: Your very own implementation of everything.

Previous versions of the compiler (pre 0.7) didn't include any runtime functionality by default, leaving it up to the developer to import relevant implementations manually, while newer versions of the compiler include a runtime suitable for most tasks.

The individual runtime functions are described at std/assembly/rt and additional usage instructions are included with the loader.

Runtime header

In order to provide the functionality mentioned above, each managed object (not annotated @unmanaged) has a hidden header that contains the necessary information. Usually, one doesn't come into contact with the runtime header because it is "hidden", that means that it is located before the address that a reference points at. However, if you are for some reason thinking of tinkering with the runtime header directly, first be warned, then here's it's structure:

╒════════════════ Common block layout (32-bit) ═════════════════╕
   3                   2                   1
 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0  bits
├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤
│                           MM info                             │ -16
├───────────────────────────────────────────────────────────────┤
│                           GC info                             │ -12
├───────────────────────────────────────────────────────────────┤
│                          runtime id                           │ -8
├───────────────────────────────────────────────────────────────┤
│                         runtime size                          │ -4
╞═══════════════════════════════════════════════════════════════╡
│                              ...                              │ ref

The allocator (TLSF) stores its information in the MM info field:

╒═══════════════ MM info interpretation (32-bit) ═══════════════╕
   3                   2                   1
 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0  bits
├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┼─┴─┴─┴─╫─┴─┴─┴─┤
│ |                    FL                       │ SB = SL + AL  │ ◄─ usize
└───────────────────────────────────────────────┴───────╨───────┘
FL: first level, SL: second level, AL: alignment, SB: small block

The reference counting implementation (PureRC) stores its information in the GC info field:

╒═══════════════════ GC info interpretation ════════════════════╕
│  3                   2                   1                    │
│1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0│
├─┼─┴─┴─┼─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤
│B│color│                     refCount                          │
└─┴─────┴───────────────────────────────────────────────────────┘
B: buffered

The other two fields are the unique computed id of the respective object that can be obtained via idof<MyClass>() and the actual size in bytes used by the object following the header, that is for example used to compute the .length of a string or the .byteLength of an ArrayBuffer. The total length of 16 bytes isn't coincidental by the way: The largest basic value in WebAssembly as of today is a 16 bytes v128 vector, hence an alignment of 16 bytes is the common denominator anyway. Detailed information is available within the runtime sources.

 

Clone this wiki locally