Skip to content
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

Relocatable module experiment #890

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions cli/asc.js
Expand Up @@ -472,6 +472,7 @@ exports.main = function main(argv, options, callback) {
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
assemblyscript.setOptimizeLevelHints(compilerOptions, optimizeLevel, shrinkLevel);
assemblyscript.setNoUnsafe(compilerOptions, args.noUnsafe);
assemblyscript.setRelocatable(compilerOptions, args.relocatable);

// Initialize default aliases
assemblyscript.setGlobalAlias(compilerOptions, "Math", "NativeMath");
Expand Down
8 changes: 8 additions & 0 deletions cli/asc.json
Expand Up @@ -107,6 +107,14 @@
"type": "b",
"default": false
},
"relocatable": {
"description": [
"Emits a relocatable module. Imports memory and table base",
"offsets from the host and appends a dylink section."
],
"type": "b",
"default": false
},
"noAssert": {
"description": "Replaces assertions with just their value without trapping.",
"type": "b",
Expand Down
30 changes: 30 additions & 0 deletions lib/asrt/README.md
@@ -0,0 +1,30 @@
# ![AS](https://avatars1.githubusercontent.com/u/28916798?s=48) Shared Runtime

Experimental shared runtime working in tandem with multiple relocatable modules.

Interface
---------

* **alloc**(mbase: `usize`, size: `usize`, id: `u32`): `usize`
* **realloc**(mbase: `usize`, size: `usize`, id: `u32`): `usize`
* **free**(mbase: `usize`, ptr: `usize`): `void`
* **retain**(mbase: `usize`, ptr: `usize`): `usize`
* **release**(mbase: `usize`, ptr: `usize`, visit: `u32`): `usize`
* **visit**(mbase: `usize`, ptr: `usize`, cookie: `u32`, visit: `u32`): `void`
* **collect**(mbase: `usize`, visit: `u32`): `void`

Input values are local to the module (before relocation) while returned values are global to
the combined program (after relocation).

Proposed usage
--------------

For each relocatable module, read the `dylink` section and prepare a memory and a table that
fit all the modules including the shared runtime (assume 1kb). Afterwards, instantiate the
shared runtime (it sits at the start of the memory and the table) and provide it with the
final value of `__heap_base`. Use the instantiated runtime as the `asrt` import of all the
other modules along their respective `__memory_base` and `__table_base`, and proceed by
instantiating the relocatable modules sequentially.

Note that this is pretty much a concept at this point and hasn't been tested, but feel free
to experiment with it if you are interested in the mechanism.
46 changes: 46 additions & 0 deletions lib/asrt/assembly/asrt.ts
@@ -0,0 +1,46 @@
import { __alloc, __realloc, __free } from "rt/tlsf";
import { __retain, __release, __visit, __collect } from "rt/pure";

@external("env", "__heap_base")
declare const __heap_base: usize;

var rel_mbase: usize;
var rel_visit: (ptr: usize, cookie: u32) => void;

function __visit_members(ptr: usize, cookie: u32): void {
rel_visit(ptr - rel_mbase, cookie);
}

export function alloc(mbase: usize, size: usize, id: i32): usize {
return __alloc(size, id) - mbase;
}

export function realloc(mbase: usize, ptr: usize, size: usize): usize {
return __realloc(mbase + ptr, size) - mbase;
}

export function free(mbase: usize, ptr: usize): void {
__free(mbase + ptr);
}

export function retain(mbase: usize, ptr: usize): usize {
return __retain(mbase + ptr) - mbase;
}

export function release(mbase: usize, ptr: usize, visit: (ptr: usize, cookie: u32) => void): void {
rel_mbase = mbase;
rel_visit = visit;
__release(mbase + ptr);
}

export function visit(mbase: usize, ptr: usize, cookie: i32, visit: (ptr: usize, cookie: u32) => void): void {
rel_mbase = mbase;
rel_visit = visit;
__visit(mbase + ptr, cookie);
}

export function collect(mbase: usize, visit: (ptr: usize, cookie: u32) => void): void {
rel_mbase = mbase;
rel_visit = visit;
__collect();
}
Empty file added lib/asrt/assembly/empty.ts
Empty file.
6 changes: 6 additions & 0 deletions lib/asrt/assembly/tsconfig.json
@@ -0,0 +1,6 @@
{
"extends": "../../../std/assembly.json",
"include": [
"./**/*.ts"
]
}
3 changes: 3 additions & 0 deletions lib/asrt/build/.gitignore
@@ -0,0 +1,3 @@
*.wasm
*.wasm.map
*.asm.js