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:
parent
6d6ba0d588
commit
f3821eed1e
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
30
asterius/rts/rts.jsval.mjs
Normal file
30
asterius/rts/rts.jsval.mjs
Normal 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)}`);
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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 <> ")"
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user