1
1
mirror of https://github.com/tweag/asterius.git synced 2024-09-11 08:55:32 +03:00

Standalone JSVal manager in rts

This commit is contained in:
Cheng Shao 2021-01-06 15:06:15 +00:00
parent 6d6ba0d588
commit f3821eed1e
9 changed files with 60 additions and 66 deletions

View File

@ -16,7 +16,7 @@ function decodeTys(arr, tag) {
function decodeRtsMk(e, ty) {
switch (ty) {
case "JSVal": {
return v => e.rts_mkJSVal(e.context.stablePtrManager.newJSVal(v));
return v => e.rts_mkJSVal(e.context.components.jsvalManager.newJSValzh(v));
}
default: {
const f = `rts_mk${ty}`;
@ -28,7 +28,7 @@ function decodeRtsMk(e, ty) {
function decodeRtsGet(e, ty) {
switch (ty) {
case "JSVal": {
return p => e.context.stablePtrManager.getJSVal(e.rts_getJSVal(p));
return p => e.context.components.jsvalManager.getJSValzh(e.rts_getJSVal(p));
}
default: {
const f = `rts_get${ty}`;
@ -39,6 +39,7 @@ function decodeRtsGet(e, ty) {
export class Exports {
constructor(
components,
memory,
reentrancy_guard,
symbol_table,
@ -46,6 +47,7 @@ export class Exports {
stableptr_manager
) {
this.context = Object.freeze({
components: components,
memory: memory,
reentrancyGuard: reentrancy_guard,
symbolTable: symbol_table,
@ -107,11 +109,11 @@ export class Exports {
}
freeHaskellCallback(sn) {
const cb = this.context.stablePtrManager.getJSVal(sn);
const cb = this.context.components.jsvalManager.getJSValzh(sn);
this.context.stablePtrManager.freeStablePtr(
this.context.callbackStablePtrs.get(cb)
);
this.context.callbackStablePtrs.delete(cb);
this.context.stablePtrManager.freeJSVal(sn);
this.context.components.jsvalManager.freeJSValzh(sn);
}
}

View File

@ -364,7 +364,7 @@ export class GC {
if (info === this.symbolTable.addressOf("stg_JSVAL_info")) {
this.liveJSValManager.closure2Val.set(
dest_c,
this.stablePtrManager.jsvalManager.getJSValzh(untagged_c)
this.components.jsvalManager.getJSValzh(untagged_c)
);
}
@ -1085,7 +1085,7 @@ export class GC {
// allocate a new nursery
this.updateNursery();
// garbage collect unused JSVals
this.stablePtrManager.jsvalManager = this.liveJSValManager;
this.components.jsvalManager = this.liveJSValManager;
// cleanup
this.nonMovedObjects.clear();
this.liveMBlocks.clear();

View File

@ -0,0 +1,30 @@
export class JSValManager {
constructor(components) {
this.components = components;
this.closure2Val = new Map();
Object.seal(this);
}
newJSValzh(v) {
const c = this.components.heapAlloc.allocate(1);
this.components.memory.i64Store(
c,
this.components.symbolTable.addressOf("stg_JSVAL_info")
);
this.closure2Val.set(c, v);
return c;
}
getJSValzh(c) {
if (!this.closure2Val.has(c)) {
throw new WebAssembly.RuntimeError(`Invalid JSVal# 0x${c.toString(16)}`);
}
return this.closure2Val.get(c);
}
freeJSValzh(c) {
if (!this.closure2Val.delete(c)) {
throw new WebAssembly.RuntimeError(`Invalid JSVal# 0x${c.toString(16)}`);
}
}
}

View File

@ -6,6 +6,7 @@ import { Tracer } from "./rts.tracing.mjs";
import { Memory } from "./rts.memory.mjs";
import { MemoryTrap } from "./rts.memorytrap.mjs";
import { HeapAlloc } from "./rts.heapalloc.mjs";
import { JSValManager } from "./rts.jsval.mjs";
import { StablePtrManager } from "./rts.stableptr.mjs";
import { StableNameManager } from "./rts.stablename.mjs";
import { StaticPtrManager } from "./rts.staticptr.mjs";
@ -86,7 +87,8 @@ export async function newAsteriusInstance(req) {
__asterius_heapalloc = new HeapAlloc(
__asterius_memory
),
__asterius_stableptr_manager = new StablePtrManager(__asterius_components),
__asterius_jsval_manager = new JSValManager(__asterius_components),
__asterius_stableptr_manager = new StablePtrManager(),
__asterius_stablename_manager = new StableNameManager(
__asterius_memory,
__asterius_heapalloc,
@ -98,6 +100,7 @@ export async function newAsteriusInstance(req) {
__asterius_spt_entries
),
__asterius_scheduler = new Scheduler(
__asterius_components,
__asterius_memory,
__asterius_symbol_table,
__asterius_stableptr_manager
@ -121,6 +124,7 @@ export async function newAsteriusInstance(req) {
__asterius_messages = new Messages(__asterius_memory, __asterius_fs),
__asterius_unicode = new Unicode(),
__asterius_exports = new Exports(
__asterius_components,
__asterius_memory,
__asterius_reentrancy_guard,
__asterius_symbol_table,
@ -141,6 +145,7 @@ export async function newAsteriusInstance(req) {
__asterius_components.exports = __asterius_exports;
__asterius_components.heapAlloc = __asterius_heapalloc;
__asterius_components.symbolTable = __asterius_symbol_table;
__asterius_components.jsvalManager = __asterius_jsval_manager;
function __asterius_show_I64(x) {
return `0x${x.toString(16).padStart(8, "0")}`;
@ -148,9 +153,9 @@ export async function newAsteriusInstance(req) {
const __asterius_jsffi_instance = {
exposeMemory: (p, len, t = Uint8Array) => __asterius_memory.expose(p, len, t),
newJSVal: v => __asterius_stableptr_manager.newJSVal(v),
getJSVal: i => __asterius_stableptr_manager.getJSVal(i),
freeJSVal: i => __asterius_stableptr_manager.freeJSVal(i),
newJSValzh: v => __asterius_components.jsvalManager.newJSValzh(v),
getJSValzh: i => __asterius_components.jsvalManager.getJSValzh(i),
freeJSValzh: i => __asterius_components.jsvalManager.freeJSValzh(i),
fs: __asterius_fs,
stdio: {
stdout: () => __asterius_fs.history(1),
@ -210,7 +215,7 @@ export async function newAsteriusInstance(req) {
? () => __asterius_exports.freeHaskellCallback(sn[0])
: () => {}
);
sn[0] = __asterius_stableptr_manager.newJSVal(cb);
sn[0] = __asterius_components.jsvalManager.newJSValzh(cb);
return sn[0];
},
freeHaskellCallback: sn => __asterius_exports.freeHaskellCallback(sn)

View File

@ -9,7 +9,8 @@ import * as rtsConstants from "./rts.constants.mjs";
*
*/
export class Scheduler {
constructor(memory, symbol_table, stablePtrManager) {
constructor(components, memory, symbol_table, stablePtrManager) {
this.components = components;
this.memory = memory;
this.symbolTable = symbol_table;
this.lastTid = 0;
@ -271,7 +272,7 @@ export class Scheduler {
"base_AsteriusziTypesziJSException_mkJSException_closure"
),
this.exports.rts_mkJSVal(
this.stablePtrManager.newJSVal(tso_info.ffiRetErr)
this.components.jsvalManager.newJSValzh(tso_info.ffiRetErr)
)
);
this.memory.i64Store(stackobj + rtsConstants.offset_StgStack_sp, sp);
@ -287,7 +288,7 @@ export class Scheduler {
}
case 1: {
// JSVal
const ptr = this.stablePtrManager.newJSVal(tso_info.ffiRet);
const ptr = this.components.jsvalManager.newJSValzh(tso_info.ffiRet);
//console.log(`Restore after FFI with value: ${tso_info.ffiRet} with type ${typeof tso_info.ffiRet} constructor ${tso_info.ffiRet.constructor} as ${ptr}`);
this.memory.i64Store(
this.symbolTable.addressOf("MainCapability") +
@ -359,8 +360,8 @@ export class Scheduler {
}
tsoReportException(tso, v) {
const err = this.stablePtrManager.getJSVal(v);
this.stablePtrManager.freeJSVal(v);
const err = this.components.jsvalManager.getJSValzh(v);
this.components.jsvalManager.freeJSValzh(v);
const tid = this.getTSOid(tso);
this.tsos.get(tid).retError = err;
}

View File

@ -1,37 +1,5 @@
export class JSValManager {
constructor(components) {
this.components = components;
this.closure2Val = new Map();
Object.seal(this);
}
newJSValzh(v) {
const c = this.components.heapAlloc.allocate(1);
this.components.memory.i64Store(
c,
this.components.symbolTable.addressOf("stg_JSVAL_info")
);
this.closure2Val.set(c, v);
return c;
}
getJSValzh(c) {
if (!this.closure2Val.has(c)) {
throw new WebAssembly.RuntimeError(`Invalid JSVal# 0x${c.toString(16)}`);
}
return this.closure2Val.get(c);
}
freeJSValzh(c) {
if (!this.closure2Val.delete(c)) {
throw new WebAssembly.RuntimeError(`Invalid JSVal# 0x${c.toString(16)}`);
}
}
}
export class StablePtrManager {
constructor(components) {
this.jsvalManager = new JSValManager(components);
constructor() {
this.spt = new Map();
this.last = 0;
Object.seal(this);
@ -51,18 +19,6 @@ export class StablePtrManager {
this.spt.delete(sp);
}
newJSVal(v) {
return this.jsvalManager.newJSValzh(v);
}
getJSVal(c) {
return this.jsvalManager.getJSValzh(c);
}
freeJSVal(c) {
this.jsvalManager.freeJSValzh(c);
}
hasStablePtr(sp) {
return this.spt.has(sp);
}

View File

@ -380,7 +380,7 @@ asteriusRunTH _ _ q ty loc s ahc_dist_input = withTempDir "asdf" $ \tmp_dir ->
uint8_arr = "new Uint8Array(" <> toJS (encode loc) <> ")"
uint8_arr_sn =
toJS i
<> ".exports.context.stablePtrManager.newJSVal("
<> ".exports.context.components.jsvalManager.newJSValzh("
<> uint8_arr
<> ")"
uint8_arr_closure =

View File

@ -255,7 +255,7 @@ generateFFIFunctionImports FFIMarshalState {..} =
-- | Generate FFI import lambda
--
-- Unsafe:
-- * Return a JSVal: (_1,_2,...,_N) => __asterius_jsffi.newJSVal(code)
-- * Return a JSVal: (_1,_2,...,_N) => __asterius_jsffi.newJSValzh(code)
-- * Otherwise: (_1,_2,...,_N) => (code)
-- Safe:
-- * (_1,_2,...,_N) => __asterius_jsffi.returnFFIPromise((async () => (code))().then(v => [returnTypes,v]))
@ -288,7 +288,7 @@ generateFFIImportLambda FFIImportDecl {ffiFunctionType = FFIFunctionType {..}, .
FFIJSValRep ->
"$"
<> intDec i
<> " = __asterius_jsffi.getJSVal($"
<> " = __asterius_jsffi.getJSValzh($"
<> intDec i
<> ");"
_ -> mempty
@ -300,7 +300,7 @@ generateFFIImportLambda FFIImportDecl {ffiFunctionType = FFIFunctionType {..}, .
<> "return "
<> ( case map ffiValueTypeRep ffiResultTypes of
[FFIJSValRep] ->
"__asterius_jsffi.newJSVal("
"__asterius_jsffi.newJSValzh("
<> byteString ffiSourceText
<> ")"
_ -> "(" <> byteString ffiSourceText <> ")"

View File

@ -28,7 +28,7 @@ instance Ord JSVal where
freeJSVal :: JSVal -> IO ()
freeJSVal (JSVal sn) = js_freeJSVal sn
foreign import javascript unsafe "__asterius_jsffi.freeJSVal($1)" js_freeJSVal :: JSVal# -> IO ()
foreign import javascript unsafe "__asterius_jsffi.freeJSValzh($1)" js_freeJSVal :: JSVal# -> IO ()
foreign import javascript unsafe "$1 === $2" js_eqJSVal :: JSVal -> JSVal -> Bool