@scriptc/compiler 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +78 -34
- package/dist/backend/cc-cache.test.d.ts +1 -0
- package/dist/backend/cc-cache.test.js +2507 -0
- package/dist/backend/cc-cache.test.js.map +1 -0
- package/dist/backend/cc.d.ts +69 -11
- package/dist/backend/cc.js +1937 -222
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +355 -8
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +108 -7
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +16 -0
- package/dist/backend/emission/emitter.js +23 -2
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +305 -8
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +527 -2
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +108 -0
- package/dist/compat/fetch-profile.js +482 -0
- package/dist/compat/fetch-profile.js.map +1 -0
- package/dist/coverage/surface-manifest.js +54 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +21 -8
- package/dist/frontend/lowering/lower-builtins.js +137 -14
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +40 -0
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +4 -3
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +2 -2
- package/dist/frontend/lowering/lower-exprs.js +63 -12
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +102 -7
- package/dist/frontend/lowering/lower-island.js +1702 -26
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +25 -5
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +39 -0
- package/dist/frontend/lowering/lowerer.js +286 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +12 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +16 -0
- package/dist/frontend/program.js +130 -6
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/types.d.ts +14 -7
- package/dist/frontend/types.js +95 -31
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +86 -20
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +32 -16
- package/dist/ir/nodes.js +36 -28
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +61 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.d.ts +7 -12
- package/dist/library/int-infer.js +72 -30
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +200 -1
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/profile.d.ts +7 -0
- package/dist/library/profile.js +2 -0
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +5 -0
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +3 -0
- package/dist/library/sidecar.js +168 -30
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +859 -1
package/dist/backend/llvm/dyn.js
CHANGED
|
@@ -24,6 +24,7 @@ export const DK = {
|
|
|
24
24
|
HANDLE: 9,
|
|
25
25
|
PROMISE: 10,
|
|
26
26
|
JSVAL: 11, /* SCR_DYN_JSVAL — island values held by reference */
|
|
27
|
+
TYPED_REF: 12, /* SCR_DYN_TYPED_REF — static Web-stream transit capsule */
|
|
27
28
|
};
|
|
28
29
|
/** Exact double literal (the emitter's f64Lit — the walkers' copy). */
|
|
29
30
|
function f64Lit(n) {
|
|
@@ -282,6 +283,35 @@ export class LlDyn {
|
|
|
282
283
|
const name = `sc_dm_${this.dynMatchers.size}`;
|
|
283
284
|
this.dynMatchers.set(key, name);
|
|
284
285
|
const B = new BlockBuilder();
|
|
286
|
+
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
287
|
+
this.host.declare(`declare zeroext i1 @scr_dyn_typed_ref_is(ptr, ptr, i64)`);
|
|
288
|
+
const matched = B.tmp();
|
|
289
|
+
B.line(`${matched} = call zeroext i1 @scr_dyn_typed_ref_is(ptr %d, ptr ${this.host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")})`);
|
|
290
|
+
const lRef = B.newLabel("dm.tr");
|
|
291
|
+
const lNext = B.newLabel("dm.nt");
|
|
292
|
+
B.condBr(matched, lRef, lNext);
|
|
293
|
+
B.startBlock(lRef);
|
|
294
|
+
B.terminate(`ret i1 true`);
|
|
295
|
+
B.startBlock(lNext);
|
|
296
|
+
}
|
|
297
|
+
if (t.kind !== "dyn") {
|
|
298
|
+
this.host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
299
|
+
this.host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
300
|
+
const kind = this.kindOf(B, "%d");
|
|
301
|
+
const capsule = B.tmp();
|
|
302
|
+
B.line(`${capsule} = icmp eq i32 ${kind}, ${DK.TYPED_REF}`);
|
|
303
|
+
const lCapsule = B.newLabel("dm.tr.mat");
|
|
304
|
+
const lPlain = B.newLabel("dm.tr.plain");
|
|
305
|
+
B.condBr(capsule, lCapsule, lPlain);
|
|
306
|
+
B.startBlock(lCapsule);
|
|
307
|
+
const materialized = B.tmp();
|
|
308
|
+
const matched = B.tmp();
|
|
309
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
310
|
+
B.line(`${matched} = call zeroext i1 @${name}(ptr ${materialized})`);
|
|
311
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
312
|
+
B.terminate(`ret i1 ${matched}`);
|
|
313
|
+
B.startBlock(lPlain);
|
|
314
|
+
}
|
|
285
315
|
const kindIs = (k) => {
|
|
286
316
|
const kd = this.kindOf(B, "%d");
|
|
287
317
|
const r = B.tmp();
|
|
@@ -482,6 +512,129 @@ export class LlDyn {
|
|
|
482
512
|
host.declare(`declare void @scr_dyn_check_fail(ptr, ptr, ptr)`);
|
|
483
513
|
const want = host.cstr(this.dynDesc(t));
|
|
484
514
|
const B = new BlockBuilder();
|
|
515
|
+
if (isRefCounted(t) && t.kind !== "dyn") {
|
|
516
|
+
host.declare(`declare zeroext i1 @scr_dyn_typed_ref_is(ptr, ptr, i64)`);
|
|
517
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_unbox(ptr)`);
|
|
518
|
+
const matched = B.tmp();
|
|
519
|
+
B.line(`${matched} = call zeroext i1 @scr_dyn_typed_ref_is(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")})`);
|
|
520
|
+
const lRef = B.newLabel("dc.tr");
|
|
521
|
+
const lNext = B.newLabel("dc.nt");
|
|
522
|
+
B.condBr(matched, lRef, lNext);
|
|
523
|
+
B.startBlock(lRef);
|
|
524
|
+
const ref = B.tmp();
|
|
525
|
+
B.line(`${ref} = call ptr @scr_dyn_typed_ref_unbox(ptr %d)`);
|
|
526
|
+
B.terminate(`ret ptr ${ref}`);
|
|
527
|
+
B.startBlock(lNext);
|
|
528
|
+
if (t.kind !== "union") {
|
|
529
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
530
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_cached_cast(ptr, ptr, i64)`);
|
|
531
|
+
host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, i64, ptr, ptr, ptr)`);
|
|
532
|
+
host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
533
|
+
const rc = vAdapters(host, t);
|
|
534
|
+
const kind = this.kindOf(B, "%d");
|
|
535
|
+
const capsule = B.tmp();
|
|
536
|
+
B.line(`${capsule} = icmp eq i32 ${kind}, ${DK.TYPED_REF}`);
|
|
537
|
+
const lCapsule = B.newLabel("dc.tr.cap");
|
|
538
|
+
const lPlain = B.newLabel("dc.tr.plain");
|
|
539
|
+
B.condBr(capsule, lCapsule, lPlain);
|
|
540
|
+
B.startBlock(lCapsule);
|
|
541
|
+
const cached = B.tmp();
|
|
542
|
+
B.line(`${cached} = call ptr @scr_dyn_typed_ref_cached_cast(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")})`);
|
|
543
|
+
const hasCached = B.tmp();
|
|
544
|
+
B.line(`${hasCached} = icmp ne ptr ${cached}, null`);
|
|
545
|
+
if (t.kind !== "record" && t.kind !== "array") {
|
|
546
|
+
const lCached = B.newLabel("dc.tr.hit");
|
|
547
|
+
const lMaterialize = B.newLabel("dc.tr.mat");
|
|
548
|
+
B.condBr(hasCached, lCached, lMaterialize);
|
|
549
|
+
B.startBlock(lCached);
|
|
550
|
+
B.terminate(`ret ptr ${cached}`);
|
|
551
|
+
B.startBlock(lMaterialize);
|
|
552
|
+
}
|
|
553
|
+
const materialized = B.tmp();
|
|
554
|
+
const checked = B.tmp();
|
|
555
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
556
|
+
B.line(`${checked} = call ${retTy} @${name}(ptr ${materialized}, ptr %path)`);
|
|
557
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
558
|
+
const ok = B.tmp();
|
|
559
|
+
B.line(`${ok} = icmp ne ptr ${checked}, null`);
|
|
560
|
+
if (t.kind === "record" || t.kind === "array") {
|
|
561
|
+
const shape = t.kind === "record"
|
|
562
|
+
? host.recordsById.get(t.shapeId)
|
|
563
|
+
: undefined;
|
|
564
|
+
if (t.kind === "record" && !shape) {
|
|
565
|
+
throw new Error(`llvm emitter bug: cached typed-ref cast of unknown shape ${t.shapeId}`);
|
|
566
|
+
}
|
|
567
|
+
const lOk = B.newLabel("dc.tr.ok");
|
|
568
|
+
const lBad = B.newLabel("dc.tr.bad");
|
|
569
|
+
B.condBr(ok, lOk, lBad);
|
|
570
|
+
B.startBlock(lBad);
|
|
571
|
+
const lBadDrop = B.newLabel("dc.tr.bad.drop");
|
|
572
|
+
const lBadRet = B.newLabel("dc.tr.bad.ret");
|
|
573
|
+
B.condBr(hasCached, lBadDrop, lBadRet);
|
|
574
|
+
B.startBlock(lBadDrop);
|
|
575
|
+
B.line(`call void ${releaseSym(host, t)}(ptr ${cached})`);
|
|
576
|
+
B.br(lBadRet);
|
|
577
|
+
B.startBlock(lBadRet);
|
|
578
|
+
B.terminate(`ret ptr null`);
|
|
579
|
+
B.startBlock(lOk);
|
|
580
|
+
const lRefresh = B.newLabel("dc.tr.refresh");
|
|
581
|
+
const lCache = B.newLabel("dc.tr.put");
|
|
582
|
+
B.condBr(hasCached, lRefresh, lCache);
|
|
583
|
+
B.startBlock(lRefresh);
|
|
584
|
+
const members = t.kind === "record"
|
|
585
|
+
? [
|
|
586
|
+
...shape.fields.map((field, index) => ({
|
|
587
|
+
index: index + 1,
|
|
588
|
+
type: llFieldType(field.type),
|
|
589
|
+
name: field.name,
|
|
590
|
+
})),
|
|
591
|
+
...(shape.indexValue
|
|
592
|
+
? [{
|
|
593
|
+
index: shape.fields.length + 1,
|
|
594
|
+
type: "ptr",
|
|
595
|
+
name: "[key: string] overflow",
|
|
596
|
+
}]
|
|
597
|
+
: []),
|
|
598
|
+
]
|
|
599
|
+
: [
|
|
600
|
+
{ index: 1, type: "i64", name: "length" },
|
|
601
|
+
{ index: 2, type: "i64", name: "capacity" },
|
|
602
|
+
{ index: 7, type: "ptr", name: "data" },
|
|
603
|
+
];
|
|
604
|
+
members.forEach((member) => {
|
|
605
|
+
const cachedPtr = B.tmp();
|
|
606
|
+
const checkedPtr = B.tmp();
|
|
607
|
+
const oldValue = B.tmp();
|
|
608
|
+
const newValue = B.tmp();
|
|
609
|
+
const struct = t.kind === "record"
|
|
610
|
+
? `%${mangleRecordStruct(t.shapeId)}`
|
|
611
|
+
: "%ScrArr";
|
|
612
|
+
B.line(`${cachedPtr} = getelementptr inbounds ${struct}, ptr ${cached}, i64 0, i32 ${member.index}`);
|
|
613
|
+
B.line(`${checkedPtr} = getelementptr inbounds ${struct}, ptr ${checked}, i64 0, i32 ${member.index}`);
|
|
614
|
+
B.line(`${oldValue} = load ${member.type}, ptr ${cachedPtr} ; ${member.name}`);
|
|
615
|
+
B.line(`${newValue} = load ${member.type}, ptr ${checkedPtr}`);
|
|
616
|
+
B.line(`store ${member.type} ${newValue}, ptr ${cachedPtr}`);
|
|
617
|
+
B.line(`store ${member.type} ${oldValue}, ptr ${checkedPtr}`);
|
|
618
|
+
});
|
|
619
|
+
B.line(`call void ${releaseSym(host, t)}(ptr ${checked})`);
|
|
620
|
+
B.terminate(`ret ptr ${cached}`);
|
|
621
|
+
B.startBlock(lCache);
|
|
622
|
+
B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
|
|
623
|
+
B.terminate(`ret ptr ${checked}`);
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
const lCache = B.newLabel("dc.tr.put");
|
|
627
|
+
const lReturn = B.newLabel("dc.tr.ret");
|
|
628
|
+
B.condBr(ok, lCache, lReturn);
|
|
629
|
+
B.startBlock(lCache);
|
|
630
|
+
B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
|
|
631
|
+
B.br(lReturn);
|
|
632
|
+
B.startBlock(lReturn);
|
|
633
|
+
B.terminate(`ret ptr ${checked}`);
|
|
634
|
+
}
|
|
635
|
+
B.startBlock(lPlain);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
485
638
|
/** kind test with the standard fail path (got = %d). */
|
|
486
639
|
const requireKind = (k, hint) => {
|
|
487
640
|
const kd = this.kindOf(B, "%d");
|
|
@@ -518,9 +671,11 @@ export class LlDyn {
|
|
|
518
671
|
break;
|
|
519
672
|
}
|
|
520
673
|
case "dyn": {
|
|
521
|
-
//
|
|
522
|
-
|
|
523
|
-
|
|
674
|
+
// Preserve the capsule at an unknown boundary. Generic dyn
|
|
675
|
+
// operations materialize its one cached detached view, while
|
|
676
|
+
// strict equality keeps repeated stream references identical.
|
|
677
|
+
const retained = this.retainDyn(B, "%d");
|
|
678
|
+
B.terminate(`ret ptr ${retained}`);
|
|
524
679
|
break;
|
|
525
680
|
}
|
|
526
681
|
case "bytes": {
|
|
@@ -652,13 +807,17 @@ export class LlDyn {
|
|
|
652
807
|
const m = this.objGetLit(B, "%d", f.name);
|
|
653
808
|
if (f.type.kind === "dyn") {
|
|
654
809
|
// An `unknown` field: a present key passes through, a missing
|
|
655
|
-
// one IS the undefined dyn value.
|
|
810
|
+
// one IS the undefined dyn value. Go through the dyn builder so
|
|
811
|
+
// a Web-stream typed-ref capsule cannot escape inside a checked
|
|
812
|
+
// record field.
|
|
656
813
|
const has = B.tmp();
|
|
657
814
|
B.line(`${has} = icmp ne ptr ${m}, null`);
|
|
658
815
|
const sel = B.tmp();
|
|
659
816
|
const u = this.undef(B);
|
|
660
817
|
B.line(`${sel} = select i1 ${has}, ptr ${m}, ptr ${u}`);
|
|
661
|
-
|
|
818
|
+
const value = B.tmp();
|
|
819
|
+
B.line(`${value} = call ptr @${this.dynCheckHelper(f.type)}(ptr ${sel}, ptr ${pathSlot})`);
|
|
820
|
+
storeInto(f.name, f.type, value);
|
|
662
821
|
}
|
|
663
822
|
else if (utag >= 0 && f.type.kind === "union") {
|
|
664
823
|
const unit = host.unitInstanceRef(f.type.unionId, utag);
|
|
@@ -847,6 +1006,75 @@ export class LlDyn {
|
|
|
847
1006
|
}
|
|
848
1007
|
B.startBlock(lNext);
|
|
849
1008
|
});
|
|
1009
|
+
// Preserve an exact typed-ref arm above. If no producer tag matched,
|
|
1010
|
+
// retry the union against the ordinary copy-based structural
|
|
1011
|
+
// snapshot (the compiler's width-coercion stance, rather than a
|
|
1012
|
+
// live narrowed alias).
|
|
1013
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
1014
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_cached_cast(ptr, ptr, i64)`);
|
|
1015
|
+
host.declare(`declare void @scr_dyn_typed_ref_cache_cast(ptr, ptr, i64, ptr, ptr, ptr)`);
|
|
1016
|
+
host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
1017
|
+
host.declare(`declare void @scr_union_release(ptr)`);
|
|
1018
|
+
const rc = vAdapters(host, t);
|
|
1019
|
+
const kind = this.kindOf(B, "%d");
|
|
1020
|
+
const capsule = B.tmp();
|
|
1021
|
+
B.line(`${capsule} = icmp eq i32 ${kind}, ${DK.TYPED_REF}`);
|
|
1022
|
+
const lCapsule = B.newLabel("dcu.cap");
|
|
1023
|
+
const lFail = B.newLabel("dcu.fail");
|
|
1024
|
+
B.condBr(capsule, lCapsule, lFail);
|
|
1025
|
+
B.startBlock(lCapsule);
|
|
1026
|
+
const cached = B.tmp();
|
|
1027
|
+
B.line(`${cached} = call ptr @scr_dyn_typed_ref_cached_cast(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")})`);
|
|
1028
|
+
const hasCached = B.tmp();
|
|
1029
|
+
B.line(`${hasCached} = icmp ne ptr ${cached}, null`);
|
|
1030
|
+
const materialized = B.tmp();
|
|
1031
|
+
const checked = B.tmp();
|
|
1032
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
1033
|
+
B.line(`${checked} = call ptr @${name}(ptr ${materialized}, ptr %path)`);
|
|
1034
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
1035
|
+
const ok = B.tmp();
|
|
1036
|
+
B.line(`${ok} = icmp ne ptr ${checked}, null`);
|
|
1037
|
+
const lOk = B.newLabel("dcu.ok");
|
|
1038
|
+
const lBad = B.newLabel("dcu.bad");
|
|
1039
|
+
B.condBr(ok, lOk, lBad);
|
|
1040
|
+
B.startBlock(lBad);
|
|
1041
|
+
const lBadDrop = B.newLabel("dcu.bad.drop");
|
|
1042
|
+
const lBadRet = B.newLabel("dcu.bad.ret");
|
|
1043
|
+
B.condBr(hasCached, lBadDrop, lBadRet);
|
|
1044
|
+
B.startBlock(lBadDrop);
|
|
1045
|
+
B.line(`call void @scr_union_release(ptr ${cached})`);
|
|
1046
|
+
B.br(lBadRet);
|
|
1047
|
+
B.startBlock(lBadRet);
|
|
1048
|
+
B.terminate(`ret ptr null`);
|
|
1049
|
+
B.startBlock(lOk);
|
|
1050
|
+
const lRefresh = B.newLabel("dcu.refresh");
|
|
1051
|
+
const lCache = B.newLabel("dcu.put");
|
|
1052
|
+
B.condBr(hasCached, lRefresh, lCache);
|
|
1053
|
+
B.startBlock(lRefresh);
|
|
1054
|
+
[
|
|
1055
|
+
[1, "i32", "tag"],
|
|
1056
|
+
[2, "ptr", "retain"],
|
|
1057
|
+
[3, "ptr", "release"],
|
|
1058
|
+
[4, "ptr", "trace"],
|
|
1059
|
+
[5, "i64", "slot"],
|
|
1060
|
+
].forEach(([index, fieldType, fieldName]) => {
|
|
1061
|
+
const cachedPtr = B.tmp();
|
|
1062
|
+
const checkedPtr = B.tmp();
|
|
1063
|
+
const oldValue = B.tmp();
|
|
1064
|
+
const newValue = B.tmp();
|
|
1065
|
+
B.line(`${cachedPtr} = getelementptr inbounds %ScrUnion, ptr ${cached}, i64 0, i32 ${index}`);
|
|
1066
|
+
B.line(`${checkedPtr} = getelementptr inbounds %ScrUnion, ptr ${checked}, i64 0, i32 ${index}`);
|
|
1067
|
+
B.line(`${oldValue} = load ${fieldType}, ptr ${cachedPtr} ; ${fieldName}`);
|
|
1068
|
+
B.line(`${newValue} = load ${fieldType}, ptr ${checkedPtr}`);
|
|
1069
|
+
B.line(`store ${fieldType} ${newValue}, ptr ${cachedPtr}`);
|
|
1070
|
+
B.line(`store ${fieldType} ${oldValue}, ptr ${checkedPtr}`);
|
|
1071
|
+
});
|
|
1072
|
+
B.line(`call void @scr_union_release(ptr ${checked})`);
|
|
1073
|
+
B.terminate(`ret ptr ${cached}`);
|
|
1074
|
+
B.startBlock(lCache);
|
|
1075
|
+
B.line(`call void @scr_dyn_typed_ref_cache_cast(ptr %d, ptr ${host.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")}, ptr ${checked}, ptr ${rc.retain}, ptr ${rc.release})`);
|
|
1076
|
+
B.terminate(`ret ptr ${checked}`);
|
|
1077
|
+
B.startBlock(lFail);
|
|
850
1078
|
B.line(`call void @scr_dyn_check_fail(ptr %path, ptr ${want}, ptr %d)`);
|
|
851
1079
|
B.terminate(`ret ptr null`);
|
|
852
1080
|
break;
|
|
@@ -929,6 +1157,7 @@ export class LlDyn {
|
|
|
929
1157
|
this.toDynFns.set(key, name);
|
|
930
1158
|
const host = this.host;
|
|
931
1159
|
const B = new BlockBuilder();
|
|
1160
|
+
let sourceAccessor = null;
|
|
932
1161
|
switch (t.kind) {
|
|
933
1162
|
case "f64": {
|
|
934
1163
|
host.declare(`declare ptr @scr_dyn_new_num(double)`);
|
|
@@ -967,6 +1196,12 @@ export class LlDyn {
|
|
|
967
1196
|
B.terminate(`ret ptr ${r}`);
|
|
968
1197
|
break;
|
|
969
1198
|
}
|
|
1199
|
+
case "func": {
|
|
1200
|
+
const r = B.tmp();
|
|
1201
|
+
B.line(`${r} = call ptr @${this.dynFuncBoxHelper(t)}(ptr %v, ptr null)`);
|
|
1202
|
+
B.terminate(`ret ptr ${r}`);
|
|
1203
|
+
break;
|
|
1204
|
+
}
|
|
970
1205
|
case "bytes": {
|
|
971
1206
|
if (t.elem !== "u8")
|
|
972
1207
|
throw new Error(`llvm emitter bug: to-dyn of bytes<${t.elem}>`);
|
|
@@ -1021,9 +1256,21 @@ export class LlDyn {
|
|
|
1021
1256
|
B.terminate(`ret ptr ${d}`);
|
|
1022
1257
|
break;
|
|
1023
1258
|
}
|
|
1024
|
-
host.declare(`declare ptr @scr_dyn_new_obj()`);
|
|
1025
1259
|
const d = B.tmp();
|
|
1026
|
-
|
|
1260
|
+
const carriesListenerIdentity = shape.fields.some((f) => f.name === "handleEvent" && f.type.kind === "func");
|
|
1261
|
+
if (carriesListenerIdentity) {
|
|
1262
|
+
const rc = vAdapters(host, t);
|
|
1263
|
+
sourceAccessor = {
|
|
1264
|
+
name: `${name}_source_access`,
|
|
1265
|
+
release: rc.release,
|
|
1266
|
+
};
|
|
1267
|
+
host.declare(`declare ptr @scr_dyn_new_obj_with_identity(ptr, ptr, ptr)`);
|
|
1268
|
+
B.line(`${d} = call ptr @scr_dyn_new_obj_with_identity(ptr %v, ptr ${rc.retain}, ptr @${sourceAccessor.name})`);
|
|
1269
|
+
}
|
|
1270
|
+
else {
|
|
1271
|
+
host.declare(`declare ptr @scr_dyn_new_obj()`);
|
|
1272
|
+
B.line(`${d} = call ptr @scr_dyn_new_obj()`);
|
|
1273
|
+
}
|
|
1027
1274
|
// Keys insert in DECLARED order (JS insertion order); internal
|
|
1028
1275
|
// '%'-fields follow so a record→dyn→record round trip keeps them.
|
|
1029
1276
|
const byName = new Map(shape.fields.map((f) => [f.name, f]));
|
|
@@ -1298,6 +1545,9 @@ export class LlDyn {
|
|
|
1298
1545
|
}
|
|
1299
1546
|
}
|
|
1300
1547
|
this.defs.push(`define internal ptr @${name}(${this.valTy(t)} %v) ${FN_ATTRS} { ; to-dyn ${key}`, B.render(), `}`, ``);
|
|
1548
|
+
if (sourceAccessor) {
|
|
1549
|
+
this.defs.push(`define internal ptr @${sourceAccessor.name}(ptr %v, i1 %materialize) ${FN_ATTRS} { ; live listener source ${key}`, `entry:`, ` br i1 %materialize, label %snapshot, label %release`, `snapshot:`, ` %d = call ptr @${name}(ptr %v)`, ` ret ptr %d`, `release:`, ` call void ${sourceAccessor.release}(ptr %v)`, ` ret ptr null`, `}`, ``);
|
|
1550
|
+
}
|
|
1301
1551
|
return name;
|
|
1302
1552
|
}
|
|
1303
1553
|
/** The checked-dynamic tree-promise settle adapter for one fulfillment payload type —
|
|
@@ -1407,7 +1657,7 @@ export class LlDyn {
|
|
|
1407
1657
|
const kd = this.kindOf(B, "%d");
|
|
1408
1658
|
const done = B.newLabel("ds.d");
|
|
1409
1659
|
const labels = new Map();
|
|
1410
|
-
for (const k of [DK.NULL, DK.BOOL, DK.NUM, DK.STR, DK.ARR, DK.OBJ, DK.UNDEF, DK.BYTES, DK.FUNC, DK.HANDLE, DK.PROMISE, DK.JSVAL]) {
|
|
1660
|
+
for (const k of [DK.NULL, DK.BOOL, DK.NUM, DK.STR, DK.ARR, DK.OBJ, DK.UNDEF, DK.BYTES, DK.FUNC, DK.HANDLE, DK.PROMISE, DK.JSVAL, DK.TYPED_REF]) {
|
|
1411
1661
|
labels.set(k, B.newLabel(`ds.k${k}`));
|
|
1412
1662
|
}
|
|
1413
1663
|
B.terminate(`switch i32 ${kd}, label %${done} [ ${[...labels].map(([k, l]) => `i32 ${k}, label %${l}`).join(" ")} ]`);
|
|
@@ -1419,6 +1669,16 @@ export class LlDyn {
|
|
|
1419
1669
|
B.line(`call void @scr_dyn_isl_tostr_buf(ptr %b, ptr %d)`);
|
|
1420
1670
|
B.br(done);
|
|
1421
1671
|
}
|
|
1672
|
+
B.startBlock(labels.get(DK.TYPED_REF));
|
|
1673
|
+
{
|
|
1674
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
1675
|
+
host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
1676
|
+
const materialized = B.tmp();
|
|
1677
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
1678
|
+
B.line(`call void @sc_ds_buf(ptr %b, ptr ${materialized})`);
|
|
1679
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
1680
|
+
B.br(done);
|
|
1681
|
+
}
|
|
1422
1682
|
B.startBlock(labels.get(DK.UNDEF));
|
|
1423
1683
|
this.puts(B, "%b", "undefined");
|
|
1424
1684
|
B.br(done);
|
|
@@ -1859,6 +2119,25 @@ export class LlDyn {
|
|
|
1859
2119
|
B.terminate(`ret ptr null`);
|
|
1860
2120
|
B.startBlock(lNext);
|
|
1861
2121
|
}
|
|
2122
|
+
// Typed stream capsules expose their one cached, refreshed dyn view to
|
|
2123
|
+
// ordinary property reads while the capsule itself keeps identity.
|
|
2124
|
+
{
|
|
2125
|
+
const isTyped = B.tmp();
|
|
2126
|
+
B.line(`${isTyped} = icmp eq i32 ${kd}, ${DK.TYPED_REF}`);
|
|
2127
|
+
const lTyped = B.newLabel("kg.tr");
|
|
2128
|
+
const lNext = B.newLabel("kg.n");
|
|
2129
|
+
B.condBr(isTyped, lTyped, lNext);
|
|
2130
|
+
B.startBlock(lTyped);
|
|
2131
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
2132
|
+
host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
2133
|
+
const materialized = B.tmp();
|
|
2134
|
+
const r = B.tmp();
|
|
2135
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
2136
|
+
B.line(`${r} = call ptr @${name}(ptr ${materialized}, ptr %k, i1 %opt)`);
|
|
2137
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
2138
|
+
B.terminate(`ret ptr ${r}`);
|
|
2139
|
+
B.startBlock(lNext);
|
|
2140
|
+
}
|
|
1862
2141
|
// ISLAND-held receivers: o[k] reads the REAL engine property (getters
|
|
1863
2142
|
// included, throws bridged catchably) and the result wraps back
|
|
1864
2143
|
// scalar-normalized — the routed keyed read that retired the fence.
|
|
@@ -2240,6 +2519,24 @@ export class LlDyn {
|
|
|
2240
2519
|
host.declare(`declare void @scr_str_release(ptr)`);
|
|
2241
2520
|
const B = new BlockBuilder();
|
|
2242
2521
|
const kd = this.kindOf(B, "%d");
|
|
2522
|
+
// Typed stream capsules iterate their cached, refreshed dyn view.
|
|
2523
|
+
{
|
|
2524
|
+
const isTyped = B.tmp();
|
|
2525
|
+
B.line(`${isTyped} = icmp eq i32 ${kd}, ${DK.TYPED_REF}`);
|
|
2526
|
+
const lTyped = B.newLabel("din.tr");
|
|
2527
|
+
const lNext = B.newLabel("din.nt");
|
|
2528
|
+
B.condBr(isTyped, lTyped, lNext);
|
|
2529
|
+
B.startBlock(lTyped);
|
|
2530
|
+
host.declare(`declare ptr @scr_dyn_typed_ref_materialize(ptr)`);
|
|
2531
|
+
host.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
2532
|
+
const materialized = B.tmp();
|
|
2533
|
+
const out = B.tmp();
|
|
2534
|
+
B.line(`${materialized} = call ptr @scr_dyn_typed_ref_materialize(ptr %d)`);
|
|
2535
|
+
B.line(`${out} = call ptr @${name}(ptr ${materialized}, i64 %n)`);
|
|
2536
|
+
B.line(`call void @scr_dyn_release_v(ptr ${materialized})`);
|
|
2537
|
+
B.terminate(`ret ptr ${out}`);
|
|
2538
|
+
B.startBlock(lNext);
|
|
2539
|
+
}
|
|
2243
2540
|
// ISLAND-held sources: an engine array IS iterable — the not-iterable
|
|
2244
2541
|
// TypeError below would be a wrong claim. Loud fence (lane
|
|
2245
2542
|
// dyn-routing-ops).
|