-
-
Notifications
You must be signed in to change notification settings - Fork 666
Runtime
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
Likefull
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
Likestub
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.
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.