numbl 0.3.0 → 0.3.3
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/binding.gyp +16 -33
- package/dist-cli/cli.js +20535 -25629
- package/dist-lib/graphics/types.d.ts +22 -0
- package/dist-lib/lib.d.ts +1 -0
- package/dist-lib/lib.js +59075 -63895
- package/dist-lib/numbl-core/executeCode.d.ts +11 -14
- package/dist-lib/numbl-core/executors/cJit/builtins.d.ts +30 -0
- package/dist-lib/numbl-core/executors/cJit/chainCodegen.d.ts +59 -0
- package/dist-lib/numbl-core/executors/cJit/chainExecutor.d.ts +27 -0
- package/dist-lib/numbl-core/executors/cJit/chainPass.d.ts +42 -0
- package/dist-lib/numbl-core/executors/cJit/codegen.d.ts +44 -0
- package/dist-lib/numbl-core/executors/cJit/compile.d.ts +45 -0
- package/dist-lib/numbl-core/executors/cJit/elemwiseCodegen.d.ts +23 -0
- package/dist-lib/numbl-core/executors/cJit/elemwiseStructural.d.ts +33 -0
- package/dist-lib/numbl-core/executors/cJit/fuseAnalyze.d.ts +39 -0
- package/dist-lib/numbl-core/executors/cJit/fuseCodegen.d.ts +16 -0
- package/dist-lib/numbl-core/executors/cJit/fuseExecutor.d.ts +28 -0
- package/dist-lib/numbl-core/executors/cJit/loopExecutor.d.ts +32 -0
- package/dist-lib/numbl-core/executors/cJit/register.d.ts +10 -0
- package/dist-lib/numbl-core/executors/cJit/whitelist.d.ts +15 -0
- package/dist-lib/numbl-core/executors/cache.d.ts +26 -0
- package/dist-lib/numbl-core/executors/context.d.ts +76 -0
- package/dist-lib/numbl-core/executors/index.d.ts +17 -0
- package/dist-lib/numbl-core/executors/jsJit/callExecutor.d.ts +25 -0
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/codegen}/jitCodegen.d.ts +2 -2
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/codegen}/jitCodegenHoist.d.ts +1 -1
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/codegen}/jsMultiReduction.d.ts +10 -13
- package/dist-lib/numbl-core/executors/jsJit/helpers/alloc.d.ts +12 -0
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/helpers}/jitHelpers.d.ts +2 -2
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/helpers}/jitHelpersComplex.d.ts +1 -1
- package/dist-lib/numbl-core/executors/jsJit/helpers/jitHelpersIndex.d.ts +33 -0
- package/dist-lib/numbl-core/{jit/js → executors/jsJit/helpers}/jitHelpersTensor.d.ts +7 -7
- package/dist-lib/numbl-core/executors/jsJit/jitCall.d.ts +59 -0
- package/dist-lib/numbl-core/executors/jsJit/jitLoop.d.ts +53 -0
- package/dist-lib/numbl-core/executors/jsJit/jitTopLevel.d.ts +44 -0
- package/dist-lib/numbl-core/executors/jsJit/loopExecutor.d.ts +15 -0
- package/dist-lib/numbl-core/{jit/jitLoopAnalysis.d.ts → executors/jsJit/lower/blockAnalysis.d.ts} +5 -5
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/jitBailSafety.d.ts +1 -1
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/jitLower.d.ts +18 -4
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/jitLowerExpr.d.ts +11 -2
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/jitLowerStmt.d.ts +2 -2
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/jitLowerTypes.d.ts +2 -2
- package/dist-lib/numbl-core/{jit → executors/jsJit/lower}/scalarEmit.d.ts +2 -2
- package/dist-lib/numbl-core/executors/jsJit/shared.d.ts +120 -0
- package/dist-lib/numbl-core/executors/jsJit/topLevelExecutor.d.ts +17 -0
- package/dist-lib/numbl-core/executors/lowering.d.ts +166 -0
- package/dist-lib/numbl-core/executors/plugins.d.ts +39 -0
- package/dist-lib/numbl-core/executors/registry.d.ts +148 -0
- package/dist-lib/numbl-core/executors/types.d.ts +103 -0
- package/dist-lib/numbl-core/functionResolve.d.ts +7 -0
- package/dist-lib/numbl-core/helpers/check-helpers.d.ts +4 -5
- package/dist-lib/numbl-core/helpers/linsolve.d.ts +2 -3
- package/dist-lib/numbl-core/helpers/prng.d.ts +1 -2
- package/dist-lib/numbl-core/interpreter/builtins/datetime.d.ts +2 -1
- package/dist-lib/numbl-core/interpreter/builtins/misc.d.ts +4 -1
- package/dist-lib/numbl-core/interpreter/builtins/types.d.ts +4 -91
- package/dist-lib/numbl-core/interpreter/interpreter.d.ts +33 -47
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +6 -3
- package/dist-lib/numbl-core/interpreter/types.d.ts +27 -12
- package/dist-lib/numbl-core/{jit/jitTypes.d.ts → jitTypes.d.ts} +15 -1
- package/dist-lib/numbl-core/jsUserFunctions.d.ts +8 -0
- package/dist-lib/numbl-core/lowering/loweringContext.d.ts +24 -0
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +3 -3
- package/dist-lib/numbl-core/parser/types.d.ts +20 -0
- package/dist-lib/numbl-core/runtime/constructors.d.ts +6 -6
- package/dist-lib/numbl-core/runtime/cow.d.ts +33 -0
- package/dist-lib/numbl-core/runtime/index.d.ts +3 -2
- package/dist-lib/numbl-core/runtime/indexing.d.ts +6 -1
- package/dist-lib/numbl-core/runtime/plotBuiltinDispatch.d.ts +86 -0
- package/dist-lib/numbl-core/runtime/plotUtils.d.ts +17 -2
- package/dist-lib/numbl-core/runtime/refcount.d.ts +85 -0
- package/dist-lib/numbl-core/runtime/runtime.d.ts +27 -66
- package/dist-lib/numbl-core/runtime/runtimeDispatch.d.ts +2 -2
- package/dist-lib/numbl-core/runtime/runtimeIndexing.d.ts +2 -2
- package/dist-lib/numbl-core/runtime/runtimeMemberAccess.d.ts +1 -1
- package/dist-lib/numbl-core/runtime/runtimePlot.d.ts +1 -0
- package/dist-lib/numbl-core/runtime/struct-access.d.ts +2 -1
- package/dist-lib/numbl-core/runtime/types.d.ts +104 -62
- package/dist-lib/numbl-core/runtime/utils.d.ts +2 -8
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-plot-viewer/assets/index-COAM8o1E.js +4426 -0
- package/dist-plot-viewer/index.html +1 -1
- package/native/lapack_linsolve.cpp +1 -1
- package/native/numbl_addon_common.h +2 -2
- package/native/ops/comparison.c +1 -1
- package/package.json +3 -6
- package/dist-lib/numbl-core/jit/c/abi.d.ts +0 -90
- package/dist-lib/numbl-core/jit/c/assemble.d.ts +0 -56
- package/dist-lib/numbl-core/jit/c/classify.d.ts +0 -70
- package/dist-lib/numbl-core/jit/c/compile.d.ts +0 -37
- package/dist-lib/numbl-core/jit/c/context.d.ts +0 -152
- package/dist-lib/numbl-core/jit/c/emit/assign.d.ts +0 -20
- package/dist-lib/numbl-core/jit/c/emit/complexScalar.d.ts +0 -18
- package/dist-lib/numbl-core/jit/c/emit/fused.d.ts +0 -42
- package/dist-lib/numbl-core/jit/c/emit/helpers.d.ts +0 -40
- package/dist-lib/numbl-core/jit/c/emit/index.d.ts +0 -14
- package/dist-lib/numbl-core/jit/c/emit/scalar.d.ts +0 -23
- package/dist-lib/numbl-core/jit/c/emit/stmt.d.ts +0 -25
- package/dist-lib/numbl-core/jit/c/emit/tensor.d.ts +0 -127
- package/dist-lib/numbl-core/jit/c/emit/userCall.d.ts +0 -58
- package/dist-lib/numbl-core/jit/c/epilogue.d.ts +0 -26
- package/dist-lib/numbl-core/jit/c/feasibility.d.ts +0 -44
- package/dist-lib/numbl-core/jit/c/prelude.d.ts +0 -37
- package/dist-lib/numbl-core/jit/c/visit.d.ts +0 -63
- package/dist-lib/numbl-core/jit/e1/complexKernelEmit.d.ts +0 -46
- package/dist-lib/numbl-core/jit/e1/hash.d.ts +0 -10
- package/dist-lib/numbl-core/jit/e1/install.d.ts +0 -13
- package/dist-lib/numbl-core/jit/e1/kernelEmit.d.ts +0 -54
- package/dist-lib/numbl-core/jit/e1/multiReductionKernel.d.ts +0 -66
- package/dist-lib/numbl-core/jit/e1/openmpFlag.d.ts +0 -13
- package/dist-lib/numbl-core/jit/e1/scalarFnKernel.d.ts +0 -44
- package/dist-lib/numbl-core/jit/e2/assignKernel.d.ts +0 -34
- package/dist-lib/numbl-core/jit/e2/astToJitExpr.d.ts +0 -25
- package/dist-lib/numbl-core/jit/e2/cache.d.ts +0 -80
- package/dist-lib/numbl-core/jit/e2/chainKernelEmit.d.ts +0 -55
- package/dist-lib/numbl-core/jit/e2/classify.d.ts +0 -119
- package/dist-lib/numbl-core/jit/e2/compileFn.d.ts +0 -16
- package/dist-lib/numbl-core/jit/e2/complexChainKernelEmit.d.ts +0 -79
- package/dist-lib/numbl-core/jit/e2/emitShared.d.ts +0 -71
- package/dist-lib/numbl-core/jit/e2/install.d.ts +0 -11
- package/dist-lib/numbl-core/jit/e2/liveness.d.ts +0 -29
- package/dist-lib/numbl-core/jit/e2/loopKernel.d.ts +0 -49
- package/dist-lib/numbl-core/jit/e2/loopKernelEmit.d.ts +0 -75
- package/dist-lib/numbl-core/jit/e2/multiReductionDriver.d.ts +0 -24
- package/dist-lib/numbl-core/jit/e2/reductionKernelEmit.d.ts +0 -72
- package/dist-lib/numbl-core/jit/e2/scalarFnDriver.d.ts +0 -29
- package/dist-lib/numbl-core/jit/fusedChainHelpers.d.ts +0 -65
- package/dist-lib/numbl-core/jit/fusedScalarEmit.d.ts +0 -69
- package/dist-lib/numbl-core/jit/fusion.d.ts +0 -71
- package/dist-lib/numbl-core/jit/fusionOps.d.ts +0 -25
- package/dist-lib/numbl-core/jit/heavyOps.d.ts +0 -15
- package/dist-lib/numbl-core/jit/index.d.ts +0 -7
- package/dist-lib/numbl-core/jit/jitLoop.d.ts +0 -25
- package/dist-lib/numbl-core/jit/jitTopLevel.d.ts +0 -22
- package/dist-lib/numbl-core/jit/js/jitHelpersIndex.d.ts +0 -33
- package/dist-lib/numbl-core/jit/js/jsFusedCodegen.d.ts +0 -17
- package/dist-lib/numbl-core/runtime/alloc.d.ts +0 -23
- package/dist-plot-viewer/assets/index-GiUNnMQg.js +0 -4426
- package/native/jit_runtime/jit_runtime.c +0 -261
- package/native/jit_runtime/jit_runtime.h +0 -204
|
@@ -22,8 +22,8 @@ export interface ExecOptions {
|
|
|
22
22
|
profile?: boolean;
|
|
23
23
|
/** Called each time a JIT function is compiled, with a description and the generated JS. */
|
|
24
24
|
onJitCompile?: (description: string, jsCode: string) => void;
|
|
25
|
-
/** Called each time
|
|
26
|
-
|
|
25
|
+
/** Called each time a C-JIT artifact is compiled, with a description and the generated C source. */
|
|
26
|
+
onCJitCompile?: (description: string, cCode: string) => void;
|
|
27
27
|
/** Initial hold state for plotting (persisted across REPL executions). */
|
|
28
28
|
initialHoldState?: boolean;
|
|
29
29
|
/** Override or add builtins for this execution only. */
|
|
@@ -34,17 +34,13 @@ export interface ExecOptions {
|
|
|
34
34
|
system?: SystemAdapter;
|
|
35
35
|
/** Synchronous callback for the `input()` builtin. Displays prompt, returns user's line. */
|
|
36
36
|
onInput?: (prompt: string) => string;
|
|
37
|
-
/** Optimization
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
|
|
44
|
-
*/
|
|
45
|
-
experimental?: string;
|
|
46
|
-
/** Parallelize fused loops with OpenMP threads (--par flag). */
|
|
47
|
-
par?: boolean;
|
|
37
|
+
/** Optimization mode: `"0"` interpreter, `"1"` JS-JIT, `"e3"` C-JIT
|
|
38
|
+
* scalar-loop only. */
|
|
39
|
+
optimization?: import("./executors/plugins.js").OptLevel;
|
|
40
|
+
/** Compile C-JIT kernels with `-ffast-math` (libmvec-vectorized
|
|
41
|
+
* transcendentals; reductions are reorder-allowed). Default true;
|
|
42
|
+
* opt out via the CLI's `--no-fast-math` flag. */
|
|
43
|
+
fastMath?: boolean;
|
|
48
44
|
/**
|
|
49
45
|
* Initial implicit cwd path for the MATLAB-style "cwd is the first search path" feature.
|
|
50
46
|
* - undefined → auto-detect from `system.cwd()` and scan its files.
|
|
@@ -85,7 +81,8 @@ export interface ProfileData {
|
|
|
85
81
|
export interface ExecResult {
|
|
86
82
|
output: string[];
|
|
87
83
|
generatedJS: string;
|
|
88
|
-
/**
|
|
84
|
+
/** Collected C source from C-JIT compilations during this run, or
|
|
85
|
+
* empty when no C-JIT artifact was produced. */
|
|
89
86
|
generatedC: string;
|
|
90
87
|
plotInstructions: PlotInstruction[];
|
|
91
88
|
returnValue: RuntimeValue;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C-JIT builtin registry — the single source of truth for which
|
|
3
|
+
* builtins each C-JIT context can emit.
|
|
4
|
+
*
|
|
5
|
+
* Two contexts:
|
|
6
|
+
*
|
|
7
|
+
* - **Elementwise** (`c-jit-fuse`, `c-jit-chain`): unary real-math
|
|
8
|
+
* builtins that compile to a single C function call inside an
|
|
9
|
+
* element-wise loop. Real-only — no complex args.
|
|
10
|
+
*
|
|
11
|
+
* - **Scalar loop** (`c-jit-loop`): a superset that adds `atan2`
|
|
12
|
+
* (binary) and the complex projection builtins (`real`, `imag`,
|
|
13
|
+
* `conj`, which accept either real or complex args).
|
|
14
|
+
*
|
|
15
|
+
* Adding a new builtin: extend the relevant set here, make sure the
|
|
16
|
+
* C name is right (override `cBuiltinName` if it differs), and add a
|
|
17
|
+
* test or benchmark that exercises it. See
|
|
18
|
+
* `docs/developer_reference/jit/cjit-substrate.md` for the broader
|
|
19
|
+
* substrate contract.
|
|
20
|
+
*/
|
|
21
|
+
/** Real-only unary math builtins emittable in an element-wise loop. */
|
|
22
|
+
export declare const ELEMWISE_REAL_BUILTINS: ReadonlySet<string>;
|
|
23
|
+
/** Real-only math builtins emittable in a scalar loop body.
|
|
24
|
+
* Superset of the elementwise set; adds `atan2` (binary). */
|
|
25
|
+
export declare const LOOP_REAL_MATH_BUILTINS: ReadonlySet<string>;
|
|
26
|
+
/** Projection builtins that accept real OR complex args. */
|
|
27
|
+
export declare const LOOP_COMPLEX_PROJECTION_BUILTINS: ReadonlySet<string>;
|
|
28
|
+
/** Map a numbl/MATLAB builtin name to its math.h C name. Identity for
|
|
29
|
+
* most; `abs` maps to `fabs` because C's `abs` is integer-typed. */
|
|
30
|
+
export declare function cBuiltinName(name: string): string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-chain codegen — combine N adjacent fusable Assigns into one
|
|
3
|
+
* C kernel with a single i-loop.
|
|
4
|
+
*
|
|
5
|
+
* Each per-name role is decided by walking the chain in source order:
|
|
6
|
+
* - input-tensor : first occurrence is RHS, env says it's a tensor
|
|
7
|
+
* - input-scalar : first occurrence is RHS, env says it's a scalar
|
|
8
|
+
* - local-tensor : first occurrence is LHS (writes the value
|
|
9
|
+
* without reading any prior value); becomes a
|
|
10
|
+
* per-iter `double` local
|
|
11
|
+
* - input+local : first occurrence is RHS but the chain also
|
|
12
|
+
* writes it — read from input pointer, then
|
|
13
|
+
* writes update the local
|
|
14
|
+
*
|
|
15
|
+
* Live-outs (any LHS of any Assign in the chain) get their own `double *`
|
|
16
|
+
* out parameter and a writeback at the end of the loop body.
|
|
17
|
+
*
|
|
18
|
+
* Today: every RHS expression must be element-wise on tensors of the
|
|
19
|
+
* chain's numel (scalars broadcast). The executor's propose() rejects
|
|
20
|
+
* chains where this can't be guaranteed.
|
|
21
|
+
*
|
|
22
|
+
* ABI:
|
|
23
|
+
* void <fnName>(
|
|
24
|
+
* long n,
|
|
25
|
+
* double *out_<name1>, double *out_<name2>, ..., // live-outs
|
|
26
|
+
* const double *in_<nameA>, const double *in_<nameB>, ...,
|
|
27
|
+
* double <nameC>, double <nameD>, ...);
|
|
28
|
+
*/
|
|
29
|
+
import type { ChainAnalysis } from "./chainPass.js";
|
|
30
|
+
/** Per-name role (decided at compile time using env types). */
|
|
31
|
+
export type NameRole = {
|
|
32
|
+
kind: "input-tensor";
|
|
33
|
+
} | {
|
|
34
|
+
kind: "input-scalar";
|
|
35
|
+
} | {
|
|
36
|
+
kind: "local-tensor";
|
|
37
|
+
readsFromInput: boolean;
|
|
38
|
+
};
|
|
39
|
+
/** Resolved per-name info carried from compile() into codegen. */
|
|
40
|
+
export interface ChainResolution {
|
|
41
|
+
/** Role for every name referenced in the chain. */
|
|
42
|
+
readonly roles: ReadonlyMap<string, NameRole>;
|
|
43
|
+
/** Names whose final value is live-out (written somewhere in the
|
|
44
|
+
* chain). For Phase A: every Assign LHS is conservatively
|
|
45
|
+
* live-out. */
|
|
46
|
+
readonly liveOuts: readonly string[];
|
|
47
|
+
/** Tensor input names in stable order (for koffi declaration). */
|
|
48
|
+
readonly tensorInputs: readonly string[];
|
|
49
|
+
/** Scalar input names in stable order. */
|
|
50
|
+
readonly scalarInputs: readonly string[];
|
|
51
|
+
}
|
|
52
|
+
/** Decide each name's role from the AST + a "is this var a tensor?"
|
|
53
|
+
* classifier. Returns null if any per-stmt structure is incompatible
|
|
54
|
+
* with the codegen — caller should bail. */
|
|
55
|
+
export declare function resolveChain(cls: ChainAnalysis, isTensor: (name: string) => boolean | null): ChainResolution | null;
|
|
56
|
+
/** Build the koffi function declaration string. */
|
|
57
|
+
export declare function buildChainDeclaration(fnName: string, res: ChainResolution): string;
|
|
58
|
+
/** Emit the C source. */
|
|
59
|
+
export declare function generateChainCSource(fnName: string, cls: ChainAnalysis, res: ChainResolution): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-chain — element-wise chain executor.
|
|
3
|
+
*
|
|
4
|
+
* - `propose()` filters on Synth stmts with `tag === "c-jit-chain"`.
|
|
5
|
+
* Reads each tensor input's `numel` from env and verifies they
|
|
6
|
+
* all match. Declines below `CHAIN_MIN_NUMEL`.
|
|
7
|
+
*
|
|
8
|
+
* - `compile()` resolves per-name roles using runtime env types,
|
|
9
|
+
* emits the combined C kernel, builds the koffi declaration,
|
|
10
|
+
* calls compileAndLoad. Surfaces source via `interp.onCJitCompile`.
|
|
11
|
+
*
|
|
12
|
+
* - `run()` gathers tensor data + scalars, allocates one
|
|
13
|
+
* `Float64Array(numel)` per live-out, invokes the kernel, writes
|
|
14
|
+
* each live-out back to env as a `RuntimeTensor` with the input
|
|
15
|
+
* tensors' shape.
|
|
16
|
+
*/
|
|
17
|
+
import type { Executor } from "../types.js";
|
|
18
|
+
import type { SynthLoweredStmt } from "../lowering.js";
|
|
19
|
+
import { type ChainResolution } from "./chainCodegen.js";
|
|
20
|
+
import { type CompiledC } from "./compile.js";
|
|
21
|
+
interface ChainCompiled {
|
|
22
|
+
readonly compiled: CompiledC;
|
|
23
|
+
readonly resolution: ChainResolution;
|
|
24
|
+
readonly source: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const cJitChainExecutor: Executor<SynthLoweredStmt, ChainCompiled | null>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-chain AST transformer.
|
|
3
|
+
*
|
|
4
|
+
* Walks a stmt list once and identifies maximal contiguous runs of
|
|
5
|
+
* adjacent stmts that are individually candidates for fusion (today:
|
|
6
|
+
* tensor element-wise Assigns whose RHS is a fusable expression
|
|
7
|
+
* tree). Wraps each non-trivial run (length >= 2) in a `Synth` node
|
|
8
|
+
* with `tag: "c-jit-chain"`; the matching `cJitChainExecutor` will
|
|
9
|
+
* compile the whole chain to one C kernel at dispatch time.
|
|
10
|
+
*
|
|
11
|
+
* Singletons (chains of length 1) are left as the original Assign so
|
|
12
|
+
* the existing `c-jit-fuse` per-stmt path handles them. That keeps
|
|
13
|
+
* the win path narrow: chains exist only where multiple adjacent
|
|
14
|
+
* fusable Assigns can amortize per-call overhead and share memory
|
|
15
|
+
* traversal.
|
|
16
|
+
*
|
|
17
|
+
* Purely structural — no env access. Runtime decisions (size,
|
|
18
|
+
* type-shape match) happen in the executor's `propose()`.
|
|
19
|
+
*
|
|
20
|
+
* Recursive descent: For/While/If bodies are transformed lazily via
|
|
21
|
+
* `Registry.transformStmts` when the interpreter walks them. This
|
|
22
|
+
* pass just operates on the immediate stmt list.
|
|
23
|
+
*/
|
|
24
|
+
import { type Stmt } from "../../parser/types.js";
|
|
25
|
+
/** Per-stmt classification used by the chain executor. The data
|
|
26
|
+
* carried on each Synth node is `ChainAnalysis`. */
|
|
27
|
+
export interface ChainAnalysis {
|
|
28
|
+
/** Original Assigns in source order. */
|
|
29
|
+
readonly assigns: readonly (Stmt & {
|
|
30
|
+
type: "Assign";
|
|
31
|
+
})[];
|
|
32
|
+
/** Stable shape hash — combines per-stmt RHS structures and LHS
|
|
33
|
+
* names, used by the executor's cacheKey. Sizes / runtime types
|
|
34
|
+
* are NOT included; those affect cost, not codegen shape. */
|
|
35
|
+
readonly cacheKey: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Transform a stmt list, wrapping maximal fusable runs (length >= 2)
|
|
39
|
+
* in `Synth` nodes. Returns a new list when any transformation
|
|
40
|
+
* happens; returns the input unchanged otherwise.
|
|
41
|
+
*/
|
|
42
|
+
export declare function chainPass(stmts: readonly Stmt[]): Stmt[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-loop codegen — JIT IR → C source.
|
|
3
|
+
*
|
|
4
|
+
* Emits one C function per loop. Each scalar variable is encoded
|
|
5
|
+
* either as a single `double` (real) or a pair `<name>_re`, `<name>_im`
|
|
6
|
+
* (complex). Inputs are passed by value (real → 1 arg, complex →
|
|
7
|
+
* 2 args); outputs are written through a `double *out` pointer
|
|
8
|
+
* (real → 1 slot, complex → 2 slots).
|
|
9
|
+
*
|
|
10
|
+
* Codegen is deliberately narrow — see `whitelist.ts` for the set of
|
|
11
|
+
* IR nodes accepted. Anything outside that set is a programming error
|
|
12
|
+
* here (the executor's `propose()` must reject before reaching this
|
|
13
|
+
* module).
|
|
14
|
+
*/
|
|
15
|
+
import type { JitStmt, JitType } from "../../jitTypes.js";
|
|
16
|
+
/** Per-variable C encoding. */
|
|
17
|
+
export type VarEncoding = "real" | "complex";
|
|
18
|
+
/** Resolved (input + local) variable types. Codegen keys lookups on
|
|
19
|
+
* the variable name; both Vars and Assigns consult this map. */
|
|
20
|
+
export type VarTypeMap = ReadonlyMap<string, VarEncoding>;
|
|
21
|
+
/** Emitted scalar value. Real values are a single C expression;
|
|
22
|
+
* complex values are a (re, im) pair. */
|
|
23
|
+
export type Emitted = {
|
|
24
|
+
kind: "real";
|
|
25
|
+
expr: string;
|
|
26
|
+
} | {
|
|
27
|
+
kind: "complex";
|
|
28
|
+
re: string;
|
|
29
|
+
im: string;
|
|
30
|
+
};
|
|
31
|
+
/** Walk the IR + input typings and produce a per-name encoding map.
|
|
32
|
+
* A name is "complex" iff at least one read or write of it has a
|
|
33
|
+
* complex_or_number type. Otherwise "real".
|
|
34
|
+
*
|
|
35
|
+
* This mirrors the JIT's type widening: by the time the IR is
|
|
36
|
+
* produced, every Var / Assign for the same name has been unified
|
|
37
|
+
* to a single type. The walker just records that type. */
|
|
38
|
+
export declare function inferVarEncodings(inputs: readonly string[], inputTypes: readonly JitType[], body: readonly JitStmt[]): Map<string, VarEncoding>;
|
|
39
|
+
/** Per-variable slot count in the marshaling ABI: real → 1, complex → 2. */
|
|
40
|
+
export declare function varSlotCount(enc: VarEncoding): number;
|
|
41
|
+
/** Total number of `double` slots a variable list consumes. */
|
|
42
|
+
export declare function totalSlotCount(names: readonly string[], varTypes: VarTypeMap): number;
|
|
43
|
+
/** Emit a complete C source file. */
|
|
44
|
+
export declare function generateCSource(fnName: string, inputs: readonly string[], outputs: readonly string[], body: readonly JitStmt[], varTypes: VarTypeMap): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit compile + cache + load.
|
|
3
|
+
*
|
|
4
|
+
* Cache layout: `~/.cache/numbl/c-jit/<sha>.so` (one per unique
|
|
5
|
+
* (declaration, source) pair). On hit, dlopen and reuse — no `cc`
|
|
6
|
+
* invocation. On miss, write `<sha>.c`, exec `cc`, dlopen.
|
|
7
|
+
*
|
|
8
|
+
* The koffi function declaration is fully owned by the caller —
|
|
9
|
+
* different executors (c-jit-loop, c-jit-fuse, ...) emit the
|
|
10
|
+
* declaration that matches their ABI. This module only handles
|
|
11
|
+
* source-string-in / koffi-callable-out.
|
|
12
|
+
*/
|
|
13
|
+
import type { NativeBridge } from "../../workspace/types.js";
|
|
14
|
+
/**
|
|
15
|
+
* The koffi function reference returned by `lib.func(decl)`. The
|
|
16
|
+
* actual call signature is controlled by the caller's declaration —
|
|
17
|
+
* type as variadic and let the caller cast as needed.
|
|
18
|
+
*/
|
|
19
|
+
export type CFn = (...args: unknown[]) => unknown;
|
|
20
|
+
export interface CompiledC {
|
|
21
|
+
readonly fn: CFn;
|
|
22
|
+
/** Path to the .so on disk — useful for diagnostics. */
|
|
23
|
+
readonly libPath: string;
|
|
24
|
+
/** Cache hit (true) vs. fresh cc invocation (false). */
|
|
25
|
+
readonly cacheHit: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface CompileOptions {
|
|
28
|
+
/** Enable `-ffast-math`. On by default for ~30% speedup on
|
|
29
|
+
* element-wise tensor benchmarks (libmvec vectorization of
|
|
30
|
+
* transcendentals). Opt out via the CLI's `--no-fast-math` flag
|
|
31
|
+
* to keep FP semantics bitwise-deterministic. */
|
|
32
|
+
readonly fastMath?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Compile (or look up cached) and load. The cache key is the SHA of
|
|
36
|
+
* `(declaration, source)` so the same source compiled with different
|
|
37
|
+
* koffi declarations gets distinct cache entries (defensive — usually
|
|
38
|
+
* the declaration matches the source's signature).
|
|
39
|
+
*/
|
|
40
|
+
export declare function compileAndLoad(source: string, declaration: string, bridge: NativeBridge, options?: CompileOptions): CompiledC;
|
|
41
|
+
/**
|
|
42
|
+
* Read a previously-compiled C source from disk. Diagnostic helper
|
|
43
|
+
* for verifying cache hits.
|
|
44
|
+
*/
|
|
45
|
+
export declare function readCachedSource(hash: string): string | null;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared codegen helpers for the element-wise C-JIT executors
|
|
3
|
+
* (`c-jit-fuse`, `c-jit-chain`).
|
|
4
|
+
*
|
|
5
|
+
* Both executors lower the same AST subset (the one accepted by
|
|
6
|
+
* `elemwiseStructural.isElemwiseStructuralExpr`) to C; they only
|
|
7
|
+
* differ in how an `Ident` leaf maps to a C expression (tensor pointer
|
|
8
|
+
* indexing vs. local-name vs. scalar parameter). This module owns the
|
|
9
|
+
* shared structural emitter and a few utility helpers; the per-executor
|
|
10
|
+
* codegen is reduced to a thin wrapper that supplies the leaf mapping.
|
|
11
|
+
*/
|
|
12
|
+
import { type Expr } from "../../parser/types.js";
|
|
13
|
+
/** Emit a C `double` literal that's unambiguous to the compiler.
|
|
14
|
+
* Handles NaN, ±Inf, integer-valued doubles. */
|
|
15
|
+
export declare function formatDouble(v: number): string;
|
|
16
|
+
/** Walk `e` and add every `Ident` name to `out`. Whitelisted to the
|
|
17
|
+
* element-wise AST subset — anything outside (e.g. `Index`) is a
|
|
18
|
+
* programming error (the structural classifier should have rejected). */
|
|
19
|
+
export declare function collectIdents(e: Expr, out: Set<string>): void;
|
|
20
|
+
/** Lower an element-wise AST expression to a C string. The caller
|
|
21
|
+
* supplies `identToC` to map each `Ident` name to its in-loop C form
|
|
22
|
+
* (e.g. `t0[i]`, `in_x[i]`, `s2`, or a bare local name). */
|
|
23
|
+
export declare function emitElemwiseExpr(e: Expr, identToC: (name: string) => string): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared structural classifier for element-wise C-JIT.
|
|
3
|
+
*
|
|
4
|
+
* The "is this AST expression element-wise lowerable?" check, in two
|
|
5
|
+
* pieces:
|
|
6
|
+
*
|
|
7
|
+
* - `isElemwiseStructuralExpr(e)` — fully structural, no env access.
|
|
8
|
+
* Used by `chainPass` (runs at stmt-list-entry time, before env
|
|
9
|
+
* types are known).
|
|
10
|
+
*
|
|
11
|
+
* - `isElemwiseBinaryOp(op)` / `binaryOpNeedsScalarCheck(op)` — the
|
|
12
|
+
* binary-op subset, exposed so env-aware walkers (`fuseAnalyze`)
|
|
13
|
+
* can apply runtime-scalar checks on top of the structural shape.
|
|
14
|
+
*
|
|
15
|
+
* Pairs with `builtins.ts` (which owns the unary builtin set). Anything
|
|
16
|
+
* not accepted here is rejected at propose-time.
|
|
17
|
+
*/
|
|
18
|
+
import { BinaryOperation, type Expr, UnaryOperation } from "../../parser/types.js";
|
|
19
|
+
/** Binary ops the element-wise codegen can emit. `Mul`/`Div` are matrix
|
|
20
|
+
* ops in MATLAB but degenerate to element-wise when at least one
|
|
21
|
+
* operand is a scalar — env-aware callers should additionally apply
|
|
22
|
+
* `binaryOpNeedsScalarCheck`. */
|
|
23
|
+
export declare function isElemwiseBinaryOp(op: BinaryOperation): boolean;
|
|
24
|
+
/** True iff `op` requires a runtime scalar-operand check before being
|
|
25
|
+
* emitted element-wise (i.e. plain `*` and `/`). */
|
|
26
|
+
export declare function binaryOpNeedsScalarCheck(op: BinaryOperation): boolean;
|
|
27
|
+
/** Unary ops the element-wise codegen can emit. */
|
|
28
|
+
export declare function isElemwiseUnaryOp(op: UnaryOperation): boolean;
|
|
29
|
+
/** Structural check: is `e` element-wise lowerable as a tree shape?
|
|
30
|
+
* Does NOT consult env. Leaves (`Ident`, `Number`) are accepted
|
|
31
|
+
* unconditionally; runtime classification of identifiers (tensor vs.
|
|
32
|
+
* scalar) is the caller's responsibility. */
|
|
33
|
+
export declare function isElemwiseStructuralExpr(e: Expr): boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-fuse — structural feasibility analysis on a single AST `Assign`.
|
|
3
|
+
*
|
|
4
|
+
* Walks the AST directly (not the JS-JIT IR — that pipeline is sized
|
|
5
|
+
* for whole-function lowering). Determines whether the RHS expression
|
|
6
|
+
* tree can be compiled to a single-pass element-wise C kernel, and
|
|
7
|
+
* extracts the tensor / scalar input identifiers in a stable order.
|
|
8
|
+
*
|
|
9
|
+
* Returns `null` when the stmt isn't a fusable shape — caller (the
|
|
10
|
+
* lowering pipeline) then leaves the stmt for the interpreter.
|
|
11
|
+
*
|
|
12
|
+
* Today's scope: real-only, plain-Ident LHS, same-shape tensor
|
|
13
|
+
* leaves. Broadcasting, complex tensors, and in-place mutation are
|
|
14
|
+
* not handled yet.
|
|
15
|
+
*/
|
|
16
|
+
import { type Expr, type Stmt } from "../../parser/types.js";
|
|
17
|
+
import type { Environment } from "../../interpreter/types.js";
|
|
18
|
+
/** Per-leaf classification: tensor, scalar (number), or literal. */
|
|
19
|
+
export type LeafKind = "tensor" | "scalar";
|
|
20
|
+
export interface FuseClassification {
|
|
21
|
+
/** Output variable name (LHS of the Assign). */
|
|
22
|
+
readonly outputName: string;
|
|
23
|
+
/** Tensor inputs in the order they should appear as C parameters. */
|
|
24
|
+
readonly tensorInputs: readonly string[];
|
|
25
|
+
/** Scalar inputs in the order they should appear as C parameters. */
|
|
26
|
+
readonly scalarInputs: readonly string[];
|
|
27
|
+
/** The RHS expression, kept as AST for codegen to walk. */
|
|
28
|
+
readonly rhs: Expr;
|
|
29
|
+
/** Stable cache key projected from the AST shape and per-leaf
|
|
30
|
+
* classification. Drops sizes — those are runtime-only and live
|
|
31
|
+
* in `propose()`. */
|
|
32
|
+
readonly cacheKey: string;
|
|
33
|
+
/** Per-name kind, used by codegen to map identifiers to either
|
|
34
|
+
* `tN[i]` (tensor) or `sN` (scalar). */
|
|
35
|
+
readonly kindOf: ReadonlyMap<string, LeafKind>;
|
|
36
|
+
}
|
|
37
|
+
/** Determine whether `stmt` is a fusable Assign and, if so, return
|
|
38
|
+
* its classification. Returns null on any structural mismatch. */
|
|
39
|
+
export declare function analyzeFuse(stmt: Stmt, env: Environment): FuseClassification | null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-fuse codegen — single-pass element-wise C kernel.
|
|
3
|
+
*
|
|
4
|
+
* Emits one C function whose body is a single `for (long i = 0; i < n; i++)`
|
|
5
|
+
* loop with `out[i] = <fused expression>;`. The fused expression is
|
|
6
|
+
* the AST RHS, with each `Ident` mapped to either `tN[i]` (tensor)
|
|
7
|
+
* or `sN` (scalar) via `emitElemwiseExpr`'s leaf callback.
|
|
8
|
+
*
|
|
9
|
+
* ABI:
|
|
10
|
+
* void <fnName>(double *out, long n,
|
|
11
|
+
* const double *t0, const double *t1, ...,
|
|
12
|
+
* double s0, double s1, ...);
|
|
13
|
+
*/
|
|
14
|
+
import type { FuseClassification } from "./fuseAnalyze.js";
|
|
15
|
+
/** Emit a complete C source file for a fuse classification. */
|
|
16
|
+
export declare function generateFuseCSource(fnName: string, cls: FuseClassification): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-fuse — element-wise tensor op fusion.
|
|
3
|
+
*
|
|
4
|
+
* - `propose()` filters on `lowered.kind === "fuse"`. Reads each
|
|
5
|
+
* tensor input's `numel` from env and verifies they all match;
|
|
6
|
+
* declines below a per-call threshold so small tensors stay on
|
|
7
|
+
* the interpreter path.
|
|
8
|
+
*
|
|
9
|
+
* - `compile()` emits a single-pass C kernel, builds the koffi
|
|
10
|
+
* declaration, calls `compileAndLoad`. Surfaces the source via
|
|
11
|
+
* `interp.onCJitCompile` for `--dump-c`.
|
|
12
|
+
*
|
|
13
|
+
* - `run()` gathers tensor data + scalar values, allocates an
|
|
14
|
+
* output `Float64Array(numel)`, invokes the kernel, wraps the
|
|
15
|
+
* output as a real `RuntimeTensor` whose shape mirrors the first
|
|
16
|
+
* tensor input's, and writes back.
|
|
17
|
+
*/
|
|
18
|
+
import type { Executor } from "../types.js";
|
|
19
|
+
import type { FuseLoweredStmt } from "../lowering.js";
|
|
20
|
+
import { type CompiledC } from "./compile.js";
|
|
21
|
+
interface CFuseCompiled {
|
|
22
|
+
readonly compiled: CompiledC;
|
|
23
|
+
readonly tensorInputs: readonly string[];
|
|
24
|
+
readonly scalarInputs: readonly string[];
|
|
25
|
+
readonly source: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const cJitFuseExecutor: Executor<FuseLoweredStmt, CFuseCompiled | null>;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-loop — C codegen executor for scalar for/while loops.
|
|
3
|
+
*
|
|
4
|
+
* - `propose()` filters on `lowered.kind === "loop"`, requires a
|
|
5
|
+
* wired `nativeBridge`, applies the C feasibility whitelist, and
|
|
6
|
+
* rejects loops containing IO + bail-risk.
|
|
7
|
+
*
|
|
8
|
+
* - `compile()` generates C source from the lowered IR, caches the
|
|
9
|
+
* compiled `.so` under `~/.cache/numbl/c-jit/<sha>.so`, and loads
|
|
10
|
+
* via koffi.
|
|
11
|
+
*
|
|
12
|
+
* - `run()` reads loop inputs from the interpreter env, marshals
|
|
13
|
+
* complex values to (re, im) pairs, invokes the compiled C
|
|
14
|
+
* function with an output Float64Array, and writes the outputs
|
|
15
|
+
* back to env.
|
|
16
|
+
*/
|
|
17
|
+
import type { Executor } from "../types.js";
|
|
18
|
+
import type { LoopLowered } from "../jsJit/jitLoop.js";
|
|
19
|
+
import { type VarEncoding } from "./codegen.js";
|
|
20
|
+
import { type CompiledC } from "./compile.js";
|
|
21
|
+
interface CLoopCompiled {
|
|
22
|
+
readonly compiled: CompiledC;
|
|
23
|
+
readonly inputs: readonly string[];
|
|
24
|
+
readonly outputs: readonly string[];
|
|
25
|
+
readonly inputEncodings: readonly VarEncoding[];
|
|
26
|
+
readonly outputEncodings: readonly VarEncoding[];
|
|
27
|
+
/** Total `double` slots in `out` — sum of per-output slot counts. */
|
|
28
|
+
readonly outputSlots: number;
|
|
29
|
+
readonly source: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const cJitLoopExecutor: Executor<LoopLowered, CLoopCompiled | null>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only entry that wires the C-JIT executors into the shared
|
|
3
|
+
* `plugins.ts` registrar slot. Importing this module for its side
|
|
4
|
+
* effect (from `cli.ts`) is what makes `--opt e3` work in the CLI.
|
|
5
|
+
*
|
|
6
|
+
* The browser worker bundle deliberately does not import this file,
|
|
7
|
+
* keeping `compile.ts` (and its `node:fs`/`node:os`/`node:child_process`
|
|
8
|
+
* imports) out of the web build's module graph.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* c-jit-loop feasibility whitelist.
|
|
3
|
+
*
|
|
4
|
+
* Walks a `LoopLowered` IR body and returns true iff every node is
|
|
5
|
+
* something the C codegen can emit. Nodes outside the whitelist
|
|
6
|
+
* (tensor ops, struct field access, etc.) cause `propose()` to
|
|
7
|
+
* decline so the dispatcher falls through to the interpreter.
|
|
8
|
+
*
|
|
9
|
+
* Today's scope: scalar-only loops, real or complex (pair-of-doubles
|
|
10
|
+
* encoding). Math builtins on complex args are NOT supported except
|
|
11
|
+
* `real`, `imag`, and `conj`.
|
|
12
|
+
*/
|
|
13
|
+
import type { JitStmt, JitType } from "../../jitTypes.js";
|
|
14
|
+
export declare function isCScalarType(t: JitType): boolean;
|
|
15
|
+
export declare function isCJitFeasible(body: readonly JitStmt[]): boolean;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-executor compilation cache.
|
|
3
|
+
*
|
|
4
|
+
* Keyed by (executor, owner, cacheKey). The `owner` is the object the
|
|
5
|
+
* cache entry's lifetime is tied to:
|
|
6
|
+
* - For stmt dispatch: the head Stmt at `siblings[i]`.
|
|
7
|
+
* - For function-call dispatch: the FunctionDef.
|
|
8
|
+
*
|
|
9
|
+
* WeakMap scoping ensures entries are reclaimed when the owner is
|
|
10
|
+
* garbage-collected (e.g., when an AST is dropped after addpath).
|
|
11
|
+
*
|
|
12
|
+
* Each registered executor gets its own slot in the cache; a single
|
|
13
|
+
* owner can host entries from multiple executors with different
|
|
14
|
+
* specializations.
|
|
15
|
+
*/
|
|
16
|
+
declare const BAILED: unique symbol;
|
|
17
|
+
type Bailed = typeof BAILED;
|
|
18
|
+
export declare class ExecutorCache {
|
|
19
|
+
/** owner → executorName → cacheKey → compiled artifact (or BAILED) */
|
|
20
|
+
private readonly slots;
|
|
21
|
+
get(executorName: string, owner: object, key: string): unknown | undefined;
|
|
22
|
+
set(executorName: string, owner: object, key: string, compiled: unknown): void;
|
|
23
|
+
markBailed(executorName: string, owner: object, key: string): void;
|
|
24
|
+
isBailed(value: unknown): value is Bailed;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch context — passed to every executor call.
|
|
3
|
+
*
|
|
4
|
+
* Provides env access, type-info queries, sub-dispatch into the
|
|
5
|
+
* registry, and runtime callbacks. Memoizes type-info lookups for the
|
|
6
|
+
* lifetime of a single dispatch so repeated `typeOf(name)` calls from
|
|
7
|
+
* different executors don't re-infer.
|
|
8
|
+
*/
|
|
9
|
+
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
10
|
+
import type { Stmt } from "../parser/types.js";
|
|
11
|
+
import type { ControlSignal } from "../interpreter/types.js";
|
|
12
|
+
import type { Registry } from "./registry.js";
|
|
13
|
+
import { type JitType } from "../jitTypes.js";
|
|
14
|
+
export declare class DispatchContext {
|
|
15
|
+
readonly interp: Interpreter;
|
|
16
|
+
readonly registry: Registry;
|
|
17
|
+
/** When true, only no-bail executors are eligible. Set when the
|
|
18
|
+
* caller's compiled artifact has emitted observable side effects
|
|
19
|
+
* that mustn't repeat. */
|
|
20
|
+
readonly requireNoBail: boolean;
|
|
21
|
+
/** Per-dispatch memoization of typeOf(name) lookups. */
|
|
22
|
+
private readonly typeCache;
|
|
23
|
+
/** Re-entrancy guard: which executors are currently running on
|
|
24
|
+
* which head stmts. Prevents an executor sub-dispatching back into
|
|
25
|
+
* itself on the same stmt. */
|
|
26
|
+
private readonly active;
|
|
27
|
+
/** Sibling list and head index for the current dispatch. Set by
|
|
28
|
+
* Registry.dispatch before calling executors; read by peekSibling.
|
|
29
|
+
* Most executors don't read these directly. */
|
|
30
|
+
private _siblings;
|
|
31
|
+
private _i;
|
|
32
|
+
constructor(interp: Interpreter, registry: Registry, requireNoBail: boolean, active?: Set<string>);
|
|
33
|
+
/** Look up a name's JitType from the interpreter env, memoized. */
|
|
34
|
+
typeOf(name: string): JitType;
|
|
35
|
+
/** Read a value from env (no inference). Returns undefined if unbound. */
|
|
36
|
+
envValue(name: string): unknown;
|
|
37
|
+
/** Peek at a sibling stmt at `offset` from the current head.
|
|
38
|
+
* offset=0 is the current stmt; positive values look ahead.
|
|
39
|
+
* Returns null if the offset is past the end of the scope. Used by
|
|
40
|
+
* chain-style executors that may consume multiple consecutive
|
|
41
|
+
* stmts. */
|
|
42
|
+
peekSibling(offset: number): Stmt | null;
|
|
43
|
+
/** Sibling list of the current scope. The head stmt is at
|
|
44
|
+
* `siblings[headIndex]`. Most executors don't need this directly —
|
|
45
|
+
* use `peekSibling(offset)` for lookahead. The rare cases that
|
|
46
|
+
* forward the raw list to a legacy adapter (the chain executor) or
|
|
47
|
+
* claim the whole scope (the top-level executor) read these. */
|
|
48
|
+
get siblings(): readonly Stmt[];
|
|
49
|
+
get headIndex(): number;
|
|
50
|
+
/** @internal Set the position state for an upcoming dispatch. Only
|
|
51
|
+
* the registry calls this. */
|
|
52
|
+
_setPosition(siblings: readonly Stmt[], i: number): void;
|
|
53
|
+
/** Reset per-dispatch state so this context can be reused for the
|
|
54
|
+
* next stmt in a sibling loop. The reentrancy guard is expected to
|
|
55
|
+
* already be empty (every pushActive is paired with a popActive in
|
|
56
|
+
* Registry.runCandidate's finally). */
|
|
57
|
+
resetForNextDispatch(): void;
|
|
58
|
+
/** Construct a child context for sub-dispatch. `requireNoBail` is
|
|
59
|
+
* the OR of the parent flag and the parent executor's
|
|
60
|
+
* `requireNoBailInChildren` declaration. */
|
|
61
|
+
childContext(requireNoBail: boolean): DispatchContext;
|
|
62
|
+
/** @internal Whether the reentrancy guard has any entries. The
|
|
63
|
+
* registry uses this to skip the guard check on the hot path —
|
|
64
|
+
* when nothing is active there's nothing to detect. */
|
|
65
|
+
get hasActive(): boolean;
|
|
66
|
+
/** @internal Used by the registry's reentrancy guard. Pre-checked
|
|
67
|
+
* with hasActive on the hot path, so the actual `has` only fires
|
|
68
|
+
* during sub-dispatch. */
|
|
69
|
+
isActive(executorName: string, stmt: Stmt): boolean;
|
|
70
|
+
/** @internal */
|
|
71
|
+
pushActive(executorName: string, stmt: Stmt): void;
|
|
72
|
+
/** @internal */
|
|
73
|
+
popActive(executorName: string, stmt: Stmt): void;
|
|
74
|
+
}
|
|
75
|
+
/** Re-export for the runner's signal type. */
|
|
76
|
+
export type { ControlSignal };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Executor registry — public surface.
|
|
3
|
+
*
|
|
4
|
+
* See docs/developer_reference/executors.md for the design.
|
|
5
|
+
*/
|
|
6
|
+
export type { Executor, CostEstimate, BailReason, RunResult, Proposal, } from "./types.js";
|
|
7
|
+
export { Registry, makeRootContext } from "./registry.js";
|
|
8
|
+
export type { DispatchResult, CallDispatchResult, WholeScopeResult, } from "./registry.js";
|
|
9
|
+
export { DispatchContext } from "./context.js";
|
|
10
|
+
export { ExecutorCache } from "./cache.js";
|
|
11
|
+
export type { JitType, SignCategory } from "../jitTypes.js";
|
|
12
|
+
export { jitTypeKey, unifyJitTypes, isScalarType, isTensorType, isComplexType, isKnownInteger, } from "../jitTypes.js";
|
|
13
|
+
export { inferJitType } from "../interpreter/builtins/types.js";
|
|
14
|
+
export { jsJitTopLevelExecutor } from "./jsJit/topLevelExecutor.js";
|
|
15
|
+
export { jsJitLoopExecutor } from "./jsJit/loopExecutor.js";
|
|
16
|
+
export { jsJitCallExecutor } from "./jsJit/callExecutor.js";
|
|
17
|
+
export { registerExecutorsForOpt } from "./plugins.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* js-jit-call — JS codegen executor for the call shape.
|
|
3
|
+
*
|
|
4
|
+
* Lowering is the dispatcher's job. The call executor receives the
|
|
5
|
+
* lowered IR (with pre-computed feasibility flags) as the first arg
|
|
6
|
+
* to propose, decides whether to commit, and produces a compiled JS
|
|
7
|
+
* artifact on commit.
|
|
8
|
+
*
|
|
9
|
+
* - `propose()` filters on `lowered.kind === "call"`, applies
|
|
10
|
+
* IO+bail-risk feasibility check. Returns null to decline.
|
|
11
|
+
*
|
|
12
|
+
* - `compile()` calls `generateCallJS` against the lowered IR.
|
|
13
|
+
* Cached by the registry under the classification's cacheKey.
|
|
14
|
+
*
|
|
15
|
+
* - `run()` calls `runCallCompiled`. JitBailToInterpreter →
|
|
16
|
+
* transient bail.
|
|
17
|
+
*/
|
|
18
|
+
import type { Executor } from "../types.js";
|
|
19
|
+
import { type CallLowered, type CallCompiled } from "./jitCall.js";
|
|
20
|
+
interface JsJitCallData {
|
|
21
|
+
readonly lowered: CallLowered;
|
|
22
|
+
readonly args: readonly unknown[];
|
|
23
|
+
}
|
|
24
|
+
export declare const jsJitCallExecutor: Executor<JsJitCallData, CallCompiled | null>;
|
|
25
|
+
export {};
|