numbl 0.1.6 → 0.2.0
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 +53 -2
- package/dist-cli/cli.js +38743 -24679
- package/dist-lib/lib.js +43424 -30466
- package/dist-lib/numbl-core/executeCode.d.ts +22 -0
- package/dist-lib/numbl-core/helpers/bessel.d.ts +9 -0
- package/dist-lib/numbl-core/helpers/reduction-helpers.d.ts +7 -2
- package/dist-lib/numbl-core/interpreter/builtins/datetime.d.ts +39 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/time-system.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/types.d.ts +100 -5
- package/dist-lib/numbl-core/interpreter/interpreter.d.ts +41 -3
- package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +2 -0
- package/dist-lib/numbl-core/interpreter/types.d.ts +16 -7
- package/dist-lib/numbl-core/jit/c/abi.d.ts +90 -0
- package/dist-lib/numbl-core/jit/c/assemble.d.ts +56 -0
- package/dist-lib/numbl-core/jit/c/classify.d.ts +70 -0
- package/dist-lib/numbl-core/jit/c/compile.d.ts +37 -0
- package/dist-lib/numbl-core/jit/c/context.d.ts +152 -0
- package/dist-lib/numbl-core/jit/c/emit/assign.d.ts +20 -0
- package/dist-lib/numbl-core/jit/c/emit/complexScalar.d.ts +18 -0
- package/dist-lib/numbl-core/jit/c/emit/fused.d.ts +42 -0
- package/dist-lib/numbl-core/jit/c/emit/helpers.d.ts +40 -0
- package/dist-lib/numbl-core/jit/c/emit/index.d.ts +14 -0
- package/dist-lib/numbl-core/jit/c/emit/scalar.d.ts +23 -0
- package/dist-lib/numbl-core/jit/c/emit/stmt.d.ts +25 -0
- package/dist-lib/numbl-core/jit/c/emit/tensor.d.ts +127 -0
- package/dist-lib/numbl-core/jit/c/emit/userCall.d.ts +58 -0
- package/dist-lib/numbl-core/jit/c/epilogue.d.ts +26 -0
- package/dist-lib/numbl-core/jit/c/feasibility.d.ts +44 -0
- package/dist-lib/numbl-core/jit/c/hybrid.d.ts +42 -0
- package/dist-lib/numbl-core/jit/c/install.d.ts +15 -0
- package/dist-lib/numbl-core/jit/c/parityError.d.ts +26 -0
- package/dist-lib/numbl-core/jit/c/prelude.d.ts +37 -0
- package/dist-lib/numbl-core/jit/c/registry.d.ts +51 -0
- package/dist-lib/numbl-core/jit/c/visit.d.ts +63 -0
- package/dist-lib/numbl-core/jit/e1/install.d.ts +13 -0
- package/dist-lib/numbl-core/jit/e1/kernelEmit.d.ts +54 -0
- package/dist-lib/numbl-core/jit/e1/openmpFlag.d.ts +13 -0
- package/dist-lib/numbl-core/jit/e1/scalarFnKernel.d.ts +44 -0
- package/dist-lib/numbl-core/jit/fusedChainHelpers.d.ts +65 -0
- package/dist-lib/numbl-core/jit/fusedScalarEmit.d.ts +61 -0
- package/dist-lib/numbl-core/jit/fusion.d.ts +71 -0
- package/dist-lib/numbl-core/jit/fusionOps.d.ts +25 -0
- package/dist-lib/numbl-core/{interpreter/jit → jit}/index.d.ts +2 -2
- package/dist-lib/numbl-core/jit/jitBailSafety.d.ts +41 -0
- package/dist-lib/numbl-core/{interpreter/jit → jit}/jitLoop.d.ts +2 -2
- package/dist-lib/numbl-core/{interpreter/jit → jit}/jitLoopAnalysis.d.ts +13 -1
- package/dist-lib/numbl-core/jit/jitLower.d.ts +122 -0
- package/dist-lib/numbl-core/jit/jitLowerExpr.d.ts +27 -0
- package/dist-lib/numbl-core/jit/jitLowerStmt.d.ts +9 -0
- package/dist-lib/numbl-core/jit/jitLowerTypes.d.ts +29 -0
- package/dist-lib/numbl-core/jit/jitTopLevel.d.ts +22 -0
- package/dist-lib/numbl-core/jit/jitTypes.d.ts +394 -0
- package/dist-lib/numbl-core/jit/js/jitCodegen.d.ts +7 -0
- package/dist-lib/numbl-core/jit/js/jitCodegenHoist.d.ts +70 -0
- package/dist-lib/numbl-core/jit/js/jitHelpers.d.ts +34 -0
- package/dist-lib/numbl-core/jit/js/jitHelpersComplex.d.ts +21 -0
- package/dist-lib/numbl-core/jit/js/jitHelpersIndex.d.ts +33 -0
- package/dist-lib/numbl-core/jit/js/jitHelpersTensor.d.ts +34 -0
- package/dist-lib/numbl-core/jit/js/jsFusedCodegen.d.ts +17 -0
- package/dist-lib/numbl-core/jit/scalarEmit.d.ts +58 -0
- package/dist-lib/numbl-core/lexer/types.d.ts +2 -1
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +46 -1
- package/dist-lib/numbl-core/ops/bessel.d.ts +18 -0
- package/dist-lib/numbl-core/ops/comparison.d.ts +11 -0
- package/dist-lib/numbl-core/ops/complexBinaryElemwise.d.ts +10 -0
- package/dist-lib/numbl-core/ops/complexUnaryElemwise.d.ts +8 -0
- package/dist-lib/numbl-core/ops/dispatch.d.ts +26 -0
- package/dist-lib/numbl-core/ops/index.d.ts +8 -0
- package/dist-lib/numbl-core/ops/opCodes.d.ts +70 -0
- package/dist-lib/numbl-core/ops/realBinaryElemwise.d.ts +8 -0
- package/dist-lib/numbl-core/ops/realUnaryElemwise.d.ts +5 -0
- package/dist-lib/numbl-core/ops/reduce.d.ts +6 -0
- package/dist-lib/numbl-core/parser/types.d.ts +6 -0
- package/dist-lib/numbl-core/runtime/alloc.d.ts +23 -0
- package/dist-lib/numbl-core/runtime/constructors.d.ts +2 -1
- package/dist-lib/numbl-core/runtime/error.d.ts +3 -0
- package/dist-lib/numbl-core/runtime/index.d.ts +1 -1
- package/dist-lib/numbl-core/runtime/runtime.d.ts +15 -2
- package/dist-lib/numbl-core/runtime/runtimePlot.d.ts +11 -0
- package/dist-lib/numbl-core/runtime/types.d.ts +16 -1
- package/dist-lib/numbl-core/runtime/utils.d.ts +3 -1
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-plot-viewer/assets/{index-vtrJ8bml.js → index-GiUNnMQg.js} +1 -1
- package/dist-plot-viewer/index.html +1 -1
- package/native/elemwise.cpp +134 -0
- package/native/jit_runtime/jit_runtime.c +261 -0
- package/native/jit_runtime/jit_runtime.h +204 -0
- package/native/numbl_addon.cpp +55 -1
- package/native/numbl_addon_common.h +1 -0
- package/native/ops/bessel.c +572 -0
- package/native/ops/comparison.c +150 -0
- package/native/ops/complex_binary_elemwise.c +192 -0
- package/native/ops/complex_unary_elemwise.c +152 -0
- package/native/ops/numbl_ops.c +66 -0
- package/native/ops/numbl_ops.h +262 -0
- package/native/ops/real_binary_elemwise.c +85 -0
- package/native/ops/real_unary_elemwise.c +104 -0
- package/native/ops/reduce.c +162 -0
- package/native/ops_napi.cpp +320 -0
- package/package.json +11 -10
- package/dist-lib/numbl-core/interpreter/jit/jitCodegen.d.ts +0 -5
- package/dist-lib/numbl-core/interpreter/jit/jitHelpers.d.ts +0 -14
- package/dist-lib/numbl-core/interpreter/jit/jitLower.d.ts +0 -20
- package/dist-lib/numbl-core/interpreter/jit/jitTypes.d.ts +0 -168
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs the C-JIT backend (koffi path). Side-effect import only.
|
|
3
|
+
*
|
|
4
|
+
* Must be imported exactly once from a Node-only entry point (currently
|
|
5
|
+
* src/cli.ts). The browser bundle never reaches this file, so the
|
|
6
|
+
* Node-only dependencies stay out of the web build.
|
|
7
|
+
*
|
|
8
|
+
* The JS wrapper handles:
|
|
9
|
+
* - Extracting .data (Float64Array) and .data.length from RuntimeTensor args
|
|
10
|
+
* - Pre-allocating output buffers (Float64Array for tensor outputs,
|
|
11
|
+
* Float64Array(1) for scalar out-pointers)
|
|
12
|
+
* - Buffer reuse for tensor outputs (same logic as jitHelpersTensor.ts)
|
|
13
|
+
* - Wrapping results back into RuntimeTensor objects
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown under `--check-c-jit-parity` when the C-JIT declines to compile
|
|
3
|
+
* a function/loop whose IR the JS-JIT would have accepted. The message
|
|
4
|
+
* names the construct (from the feasibility checker) and the call site,
|
|
5
|
+
* giving us an actionable punch list of features to implement in the
|
|
6
|
+
* C-JIT so parity with JS-JIT holds.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CJitParityError extends Error {
|
|
9
|
+
readonly reason: string;
|
|
10
|
+
readonly kind: "infeasible" | "env";
|
|
11
|
+
constructor(message: string, reason: string, kind: "infeasible" | "env");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build a one-line parity-error message with the offending construct,
|
|
15
|
+
* the call site (function/loop name + file:line), and the arg-type
|
|
16
|
+
* signature that triggered the specialization.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatCJitParityMessage(opts: {
|
|
19
|
+
kind: "infeasible" | "env";
|
|
20
|
+
reason: string;
|
|
21
|
+
reasonLine?: number;
|
|
22
|
+
siteLabel: string;
|
|
23
|
+
file: string;
|
|
24
|
+
callSiteLine: number;
|
|
25
|
+
argsDesc: string;
|
|
26
|
+
}): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function prelude emission.
|
|
3
|
+
*
|
|
4
|
+
* The prelude is the set of C declarations at the top of a generated
|
|
5
|
+
* function, written before any statement from the body: shadowed param
|
|
6
|
+
* locals (for param-output seeding + unshare-at-entry), local tensor
|
|
7
|
+
* declarations, complex-scalar imag companions, and scratch buffer
|
|
8
|
+
* slots.
|
|
9
|
+
*
|
|
10
|
+
* Exported as `buildPrelude` — called once per function by `generateC`
|
|
11
|
+
* in [assemble.ts](./assemble.ts).
|
|
12
|
+
*
|
|
13
|
+
* The epilogue (tensor frees, out-pointer writes) is in
|
|
14
|
+
* [epilogue.ts](./epilogue.ts); both read from the same shared state
|
|
15
|
+
* (`ClassificationResult` + `EmitCtx`) populated upstream.
|
|
16
|
+
*/
|
|
17
|
+
import type { JitType } from "../jitTypes.js";
|
|
18
|
+
import type { ClassificationResult } from "./classify.js";
|
|
19
|
+
import { type EmitCtx } from "./context.js";
|
|
20
|
+
export interface PreludeInput {
|
|
21
|
+
cls: ClassificationResult;
|
|
22
|
+
ctx: EmitCtx;
|
|
23
|
+
params: string[];
|
|
24
|
+
argTypes: JitType[];
|
|
25
|
+
/** Names with `kind === "paramOutput"` (output name reuses a param name). */
|
|
26
|
+
paramOutputTensors: Set<string>;
|
|
27
|
+
/** Pure-input tensor params that need an unshare-at-entry malloc+memcpy
|
|
28
|
+
* (the body writes to them, and we must not mutate the caller's buffer). */
|
|
29
|
+
unshareTensorParams: Set<string>;
|
|
30
|
+
/** Locals to declare — outer-scope `localVars` minus params, sorted. */
|
|
31
|
+
allLocals: string[];
|
|
32
|
+
/** Names carrying `complex_or_number` scalar values (paired re+im locals). */
|
|
33
|
+
complexScalarVars: Set<string>;
|
|
34
|
+
/** Indent string to prepend to each emitted line. */
|
|
35
|
+
indent: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function buildPrelude(input: PreludeInput): string[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registrable hook for the C-JIT backend.
|
|
3
|
+
*
|
|
4
|
+
* The C-JIT's implementation pulls in Node-only modules (`child_process`,
|
|
5
|
+
* `fs`, `path`, ...) that would pollute the browser bundle if imported
|
|
6
|
+
* statically from [jit/index.ts](./index.ts). This module defines a
|
|
7
|
+
* thin interface + a module-level slot; the real backend is installed
|
|
8
|
+
* from the CLI entry point via [install.ts](./install.ts),
|
|
9
|
+
* which is only pulled into the Node-targeted build.
|
|
10
|
+
*
|
|
11
|
+
* When no backend is registered (e.g. browser, or someone running the
|
|
12
|
+
* library API directly) `getCJitBackend()` returns null and
|
|
13
|
+
* `tryJitCall` silently falls through to JS-JIT.
|
|
14
|
+
*/
|
|
15
|
+
import type { Interpreter } from "../../interpreter/interpreter.js";
|
|
16
|
+
import type { FunctionDef } from "../../interpreter/types.js";
|
|
17
|
+
import type { JitStmt, JitType } from "../jitTypes.js";
|
|
18
|
+
import type { GeneratedFn } from "../jitLower.js";
|
|
19
|
+
/**
|
|
20
|
+
* Outcome of a C-JIT compile attempt.
|
|
21
|
+
*
|
|
22
|
+
* - `ok: true`: compilation succeeded; `fn` is callable.
|
|
23
|
+
* - `ok: false, kind: "infeasible"`: the lowered IR contains a construct
|
|
24
|
+
* the C-JIT doesn't handle (JS-JIT probably would). Carries a `reason`
|
|
25
|
+
* and optional `line` from the feasibility checker; `--check-c-jit-parity`
|
|
26
|
+
* treats this as a hard error.
|
|
27
|
+
* - `ok: false, kind: "env"`: the environment couldn't support C-JIT
|
|
28
|
+
* (no C compiler, compile/link failed, header missing, etc.). Also a
|
|
29
|
+
* hard error under `--check-c-jit-parity` because the user explicitly
|
|
30
|
+
* asked for C-JIT.
|
|
31
|
+
*/
|
|
32
|
+
export type CJitCompileResult = {
|
|
33
|
+
ok: true;
|
|
34
|
+
fn: (...args: unknown[]) => unknown;
|
|
35
|
+
} | {
|
|
36
|
+
ok: false;
|
|
37
|
+
kind: "infeasible" | "env";
|
|
38
|
+
reason: string;
|
|
39
|
+
line?: number;
|
|
40
|
+
};
|
|
41
|
+
export interface CJitBackend {
|
|
42
|
+
/**
|
|
43
|
+
* Attempt to emit + compile + load a C specialization for the given
|
|
44
|
+
* lowered IR. Returns a structured result: callers distinguish
|
|
45
|
+
* `infeasible` (parity gap with JS-JIT) from `env` (missing compiler)
|
|
46
|
+
* when `--check-c-jit-parity` is on.
|
|
47
|
+
*/
|
|
48
|
+
tryCompile(interp: Interpreter, fn: FunctionDef, body: JitStmt[], outputNames: string[], localVars: Set<string>, outputType: JitType | null, outputTypes: JitType[], argTypes: JitType[], nargout: number, generatedIRBodies: Map<string, GeneratedFn>): CJitCompileResult;
|
|
49
|
+
}
|
|
50
|
+
export declare function registerCJitBackend(b: CJitBackend): void;
|
|
51
|
+
export declare function getCJitBackend(): CJitBackend | null;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight IR traversal helpers shared across the C-JIT subsystem.
|
|
3
|
+
*
|
|
4
|
+
* Several places in `jit/c/` need to walk a lowered IR body observing
|
|
5
|
+
* (but not transforming) expressions and statements: the feasibility
|
|
6
|
+
* fall-through paths, tensor-classification, hybrid-loop live-in/out
|
|
7
|
+
* analysis, and the shape-propagation / callee-discovery / complex-
|
|
8
|
+
* scalar scans in [assemble.ts](./assemble.ts). Each used to
|
|
9
|
+
* reimplement the same switch-on-tag descent.
|
|
10
|
+
*
|
|
11
|
+
* This module centralizes the descent. Three primitives, composable:
|
|
12
|
+
*
|
|
13
|
+
* - `walkExprNodes(expr, visit)` — post-order walk of every sub-node
|
|
14
|
+
* of `expr` (including `expr` itself). Every leaf calls `visit`
|
|
15
|
+
* once; nothing is skipped. Adding a new JitExpr tag means editing
|
|
16
|
+
* this one function.
|
|
17
|
+
*
|
|
18
|
+
* - `walkStmts(body, visit)` — pre-order walk of every statement in
|
|
19
|
+
* `body`, recursing into If/For/While nested bodies. Does NOT
|
|
20
|
+
* traverse expressions inside the stmt — callers that need that
|
|
21
|
+
* compose with `walkStmtExprs` + `walkExprNodes`.
|
|
22
|
+
*
|
|
23
|
+
* - `walkStmtExprs(stmt, visit)` — call `visit` on each top-level
|
|
24
|
+
* expression attached to `stmt` (the `expr` in an Assign, the
|
|
25
|
+
* `cond` in an If, the `start`/`end`/`step` in a For, etc.). Does
|
|
26
|
+
* NOT recurse into nested expression sub-nodes (use `walkExprNodes`
|
|
27
|
+
* for that) and does NOT walk into nested stmt bodies.
|
|
28
|
+
*
|
|
29
|
+
* The dispatchers in `feasibility.ts`, `emit/stmt.ts`, and
|
|
30
|
+
* `emit/fused.ts` keep their native switches — they produce structured
|
|
31
|
+
* results (feasibility verdicts, emitted C lines), so a callback-based
|
|
32
|
+
* observer doesn't fit their shape.
|
|
33
|
+
*/
|
|
34
|
+
import type { JitExpr, JitStmt } from "../jitTypes.js";
|
|
35
|
+
/**
|
|
36
|
+
* Walk every sub-node of `expr` in post-order (children first, then
|
|
37
|
+
* `expr` itself), calling `visit` on each. Leaves (NumberLiteral,
|
|
38
|
+
* ImagLiteral, Var, StringLiteral, MemberRead) are still visited once.
|
|
39
|
+
*
|
|
40
|
+
* Adding a new JitExpr tag: add a case here. Observer callers (which
|
|
41
|
+
* is all of them) don't need to know about tag-specific sub-node
|
|
42
|
+
* fields — this is the one place those are encoded.
|
|
43
|
+
*/
|
|
44
|
+
export declare function walkExprNodes(expr: JitExpr, visit: (e: JitExpr) => void): void;
|
|
45
|
+
/**
|
|
46
|
+
* Walk every statement in `body`, recursing into nested If / For /
|
|
47
|
+
* While bodies. Pre-order: `visit` is called on each stmt before
|
|
48
|
+
* descending. Does NOT traverse expressions inside the stmt.
|
|
49
|
+
*/
|
|
50
|
+
export declare function walkStmts(body: JitStmt[], visit: (s: JitStmt) => void): void;
|
|
51
|
+
/**
|
|
52
|
+
* Call `visit` on every top-level expression attached to `stmt` — the
|
|
53
|
+
* RHS of an Assign, the indices + value of an AssignIndex, the start /
|
|
54
|
+
* end / step of a For, the cond of an If / While, and so on. Does
|
|
55
|
+
* NOT recurse into expression sub-nodes (compose with `walkExprNodes`)
|
|
56
|
+
* and does NOT descend into nested stmt bodies (compose with
|
|
57
|
+
* `walkStmts`).
|
|
58
|
+
*
|
|
59
|
+
* For If, the `cond` of the primary branch AND each elseif is visited;
|
|
60
|
+
* the bodies themselves are stmt-trees, not exprs, and are reached via
|
|
61
|
+
* `walkStmts` recursion.
|
|
62
|
+
*/
|
|
63
|
+
export declare function walkStmtExprs(stmt: JitStmt, visit: (e: JitExpr) => void): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node-only install shim for the e1 (experimental) kernel pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Side-effect import from `cli.ts`. Replaces the `compileKernel` stub on
|
|
5
|
+
* the module-level `jitHelpers` object with a real implementation that
|
|
6
|
+
* shells out to `cc` via `compile.ts` and loads the result through koffi.
|
|
7
|
+
*
|
|
8
|
+
* Registration is idempotent — re-importing this module in tests won't
|
|
9
|
+
* re-install. The kernel cache on `jitHelpers.$kernels` is shared across
|
|
10
|
+
* all specializations in the process so the same fused chain used from
|
|
11
|
+
* two different JIT'd functions compiles only once.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* e1 (experimental) — standalone C-kernel emission for fusible tensor
|
|
3
|
+
* chains used by the JS-JIT.
|
|
4
|
+
*
|
|
5
|
+
* Given a `FusibleChain` the normal JS fused codegen would emit, this
|
|
6
|
+
* module produces an equivalent standalone C function of the form
|
|
7
|
+
*
|
|
8
|
+
* void k_<hash>(int64_t n,
|
|
9
|
+
* const double *in_<x>, ...,
|
|
10
|
+
* double s_<scalar>, ...,
|
|
11
|
+
* double *out_<y>, ...)
|
|
12
|
+
* {
|
|
13
|
+
* #pragma omp simd
|
|
14
|
+
* for (int64_t i = 0; i < n; i++) {
|
|
15
|
+
* double f_tmp1 = <expr>;
|
|
16
|
+
* ...
|
|
17
|
+
* out_<y>[i] = <final>;
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* It returns the full C source, a koffi signature string, a content-
|
|
22
|
+
* addressed hash, and the ordered list of JS expressions the generated
|
|
23
|
+
* code should pass as arguments — everything the JS codegen needs to
|
|
24
|
+
* emit a `$h.compileKernel(source, sig); kernel(n, x_data, y_data)`
|
|
25
|
+
* dispatch.
|
|
26
|
+
*
|
|
27
|
+
* The prototype deliberately handles only the common real-tensor chain
|
|
28
|
+
* shape: no reductions, no complex tensors, no dynamic-shape outputs.
|
|
29
|
+
* Any chain that falls outside that envelope causes `emitChainKernel`
|
|
30
|
+
* to return `null`, which signals the caller to fall back to the plain
|
|
31
|
+
* inline JS fused loop.
|
|
32
|
+
*/
|
|
33
|
+
import type { FusibleChain } from "../fusion.js";
|
|
34
|
+
/**
|
|
35
|
+
* A fused chain compiled to a standalone C kernel. The caller (the JS
|
|
36
|
+
* codegen) combines this with a runtime size threshold to emit
|
|
37
|
+
*
|
|
38
|
+
* if (n >= THRESHOLD) $h.<kernelName>(n, x_data, y_data)
|
|
39
|
+
* else <plain JS fused loop>
|
|
40
|
+
*/
|
|
41
|
+
export interface KernelEmitResult {
|
|
42
|
+
/** Hash-derived C function name, e.g. `nk_3a7f81b2`. */
|
|
43
|
+
kernelName: string;
|
|
44
|
+
/** Full C source: `#include` + function definition. */
|
|
45
|
+
cSource: string;
|
|
46
|
+
/** koffi function signature, e.g. `"void nk_3a7f81b2(int64_t, ...)"`. */
|
|
47
|
+
koffiSig: string;
|
|
48
|
+
/** Content hash over the final C source (stable id for caching). */
|
|
49
|
+
hash: string;
|
|
50
|
+
/** Ordered list of JS expressions to pass as call arguments. The
|
|
51
|
+
* caller emits something like `$h.<kernelName>(${jsCallArgs.join(",")})`. */
|
|
52
|
+
jsCallArgs: string[];
|
|
53
|
+
}
|
|
54
|
+
export declare function emitChainKernel(chain: FusibleChain, allTensorVars: ReadonlySet<string>, outputTensorNames: ReadonlySet<string>): KernelEmitResult | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-overridable OpenMP availability flag for the e1 codegen path.
|
|
3
|
+
*
|
|
4
|
+
* `scalarFnKernel.ts` is transitively reachable from the JS-JIT module
|
|
5
|
+
* graph that Vite bundles for the web REPL, but `c/compile.ts` is
|
|
6
|
+
* Node-only (child_process, fs, ...). Importing `cJitOpenmpAvailable`
|
|
7
|
+
* directly from `compile.ts` would drag all of that into the browser
|
|
8
|
+
* bundle. Instead we default to `false` here and let Node-only
|
|
9
|
+
* `e1/install.ts` override the getter at install time — the same
|
|
10
|
+
* pattern used for the `compileKernel` stub in `jitHelpers.ts`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function setOpenmpAvailableGetter(fn: () => boolean): void;
|
|
13
|
+
export declare function isOpenmpAvailable(): boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* e1 (experimental) — whole-function scalar kernel emission.
|
|
3
|
+
*
|
|
4
|
+
* Complements [kernelEmit.ts](./kernelEmit.ts) (which handles tensor
|
|
5
|
+
* fusible chains) by covering the other big win case: a user function
|
|
6
|
+
* that is entirely scalar arithmetic — e.g. the inner loop of a
|
|
7
|
+
* Horner-style series, a Runge-Kutta step on a handful of doubles,
|
|
8
|
+
* benchmarks/scalar_bench.m's `run_bench(N, M)`.
|
|
9
|
+
*
|
|
10
|
+
* Under `--opt e1`, when a JIT-able function's signature and body are
|
|
11
|
+
* purely scalar, we call `generateC()` (the same emitter the C-JIT
|
|
12
|
+
* uses at `--opt 2`) and wrap its output with a thin inline JS
|
|
13
|
+
* function that shells out to `$h.compileKernel(...)`. The C source
|
|
14
|
+
* and koffi signature are inlined as JS string literals, so
|
|
15
|
+
* `--dump-js` shows the complete picture.
|
|
16
|
+
*
|
|
17
|
+
* Scope for the prototype:
|
|
18
|
+
* - All params are scalar doubles / booleans (CParamDesc.kind === "scalar")
|
|
19
|
+
* - All outputs are scalar / boolean (COutputDesc.kind === "scalar" | "boolean")
|
|
20
|
+
* - No tic/toc, no Index reads (no errFlag), no disp(...) calls
|
|
21
|
+
*
|
|
22
|
+
* Anything outside that envelope returns `null` and the caller falls
|
|
23
|
+
* back to the plain JS-JIT path, which still benefits from e1's
|
|
24
|
+
* per-chain tensor kernels.
|
|
25
|
+
*/
|
|
26
|
+
import type { FunctionDef } from "../../interpreter/types.js";
|
|
27
|
+
import type { JitStmt, JitType } from "../jitTypes.js";
|
|
28
|
+
import type { GeneratedFn } from "../jitLower.js";
|
|
29
|
+
import type { Interpreter } from "../../interpreter/interpreter.js";
|
|
30
|
+
export interface ScalarFnKernelResult {
|
|
31
|
+
/** The inline-compileKernel JS source. The JIT caller splices this
|
|
32
|
+
* in place of the normal JS-JIT body. */
|
|
33
|
+
jsSource: string;
|
|
34
|
+
/** Content-addressed kernel name from generateC, for logging. */
|
|
35
|
+
kernelName: string;
|
|
36
|
+
/** Raw C source (also embedded in `jsSource` as a string literal).
|
|
37
|
+
* Exposed for `--dump-c` / logging. */
|
|
38
|
+
cSource: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Try to emit a whole-function scalar kernel for the given lowered IR.
|
|
42
|
+
* Returns null when the function is not a pure-scalar candidate.
|
|
43
|
+
*/
|
|
44
|
+
export declare function tryEmitScalarFnKernel(interp: Interpreter, fn: FunctionDef, body: JitStmt[], outputNames: string[], localVars: Set<string>, outputType: JitType | null, outputTypes: JitType[], argTypes: JitType[], nargout: number, generatedIRBodies: Map<string, GeneratedFn>): ScalarFnKernelResult | null;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chain-level helpers shared by the JS and C fused-codegen backends.
|
|
3
|
+
*
|
|
4
|
+
* The per-element scalar expression walker lives in `fusedScalarEmit.ts`;
|
|
5
|
+
* this module covers the surrounding logic that decides which chain dests
|
|
6
|
+
* need a write-back to their tensor buffer, and the reduction-accumulator
|
|
7
|
+
* init/combine snippets for inline reductions.
|
|
8
|
+
*
|
|
9
|
+
* Reductions are parameterized over a small `ReductionLiterals` record so
|
|
10
|
+
* each backend supplies its own spelling of `0` vs `0.0`, `===` vs `==`,
|
|
11
|
+
* `-Infinity` vs `(-1.0/0.0)`, etc. — the control structure is identical.
|
|
12
|
+
*/
|
|
13
|
+
import { BinaryOperation } from "../parser/types.js";
|
|
14
|
+
import type { FusibleChain } from "./fusion.js";
|
|
15
|
+
/**
|
|
16
|
+
* Compute the set of distinct dest names in a fused chain and which of
|
|
17
|
+
* them require a write-back into their tensor buffer.
|
|
18
|
+
*
|
|
19
|
+
* A dest normally needs write-back; the exception is the chain's last
|
|
20
|
+
* tensor if it is fully consumed by a trailing reduction (in which case
|
|
21
|
+
* the scalar reduction accumulator is the only output — materialising
|
|
22
|
+
* the tensor buffer would be wasted work). If that last-dest tensor is
|
|
23
|
+
* ALSO a named output of the enclosing function, the write-back is kept
|
|
24
|
+
* so the caller sees the updated buffer.
|
|
25
|
+
*/
|
|
26
|
+
export declare function determineWriteBack(chain: FusibleChain, outputTensorNames: ReadonlySet<string>): {
|
|
27
|
+
destNames: Set<string>;
|
|
28
|
+
writeBack: Set<string>;
|
|
29
|
+
reductionConsumes: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Target-specific literal spellings used by the reduction helpers.
|
|
33
|
+
*
|
|
34
|
+
* The structure of the reduction snippets is identical between JS and
|
|
35
|
+
* C, but the literals differ: JS uses `1`, `-Infinity`, `===`/`!==`,
|
|
36
|
+
* while C uses `1.0`, `(-1.0/0.0)`, `==`/`!=`. The caller picks a
|
|
37
|
+
* record for its target and reuses it.
|
|
38
|
+
*/
|
|
39
|
+
export interface ReductionLiterals {
|
|
40
|
+
/** Additive identity (`0` for JS, `0.0` for C). */
|
|
41
|
+
zero: string;
|
|
42
|
+
/** Multiplicative identity / truthy (`1` or `1.0`). */
|
|
43
|
+
one: string;
|
|
44
|
+
/** Positive infinity literal (`Infinity` or `(1.0/0.0)`). */
|
|
45
|
+
posInf: string;
|
|
46
|
+
/** Negative infinity literal (`-Infinity` or `(-1.0/0.0)`). */
|
|
47
|
+
negInf: string;
|
|
48
|
+
/** Strict-equality operator (`===` for JS, `==` for C). */
|
|
49
|
+
eq: string;
|
|
50
|
+
/** Strict-inequality operator (`!==` for JS, `!=` for C). */
|
|
51
|
+
neq: string;
|
|
52
|
+
}
|
|
53
|
+
export declare const JS_REDUCTION_LITERALS: ReductionLiterals;
|
|
54
|
+
export declare const C_REDUCTION_LITERALS: ReductionLiterals;
|
|
55
|
+
/** Initial value expression for a reduction accumulator. */
|
|
56
|
+
export declare function reductionInit(reduceName: string, lits: ReductionLiterals): string;
|
|
57
|
+
/** Statement that folds a per-element `valueExpr` into the accumulator. */
|
|
58
|
+
export declare function reductionCombine(reduceName: string, accVar: string, valueExpr: string, lits: ReductionLiterals): string;
|
|
59
|
+
/**
|
|
60
|
+
* Statement that folds a per-chain `val` into an enclosing accumulator
|
|
61
|
+
* `dest` via the outer-loop op (e.g. `ir_acc = ir_acc + sum(...)`).
|
|
62
|
+
*
|
|
63
|
+
* Target-neutral: `+=` / `-=` / `*=` have identical syntax in JS and C.
|
|
64
|
+
*/
|
|
65
|
+
export declare function accumulateOp(op: BinaryOperation, dest: string, val: string): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared per-element scalar-expression emission for fused loops.
|
|
3
|
+
*
|
|
4
|
+
* Both the JS-JIT and C-JIT fused-chain emitters walk the chain's
|
|
5
|
+
* expression trees and emit each sub-expression in "per-element"
|
|
6
|
+
* form — tensor Vars become `data[__i]` reads (or a scalar local for
|
|
7
|
+
* chain-produced intermediates), Binary/Unary/Call map to scalar
|
|
8
|
+
* operations that will run once per element of the fused loop.
|
|
9
|
+
*
|
|
10
|
+
* The walk itself is identical between the two backends; only the
|
|
11
|
+
* leaf syntax differs (JS `Math.sin` vs C `sin`, integer literal
|
|
12
|
+
* formatting, mangling prefix). A backend supplies a `FusedTarget`
|
|
13
|
+
* describing those leaves and a value-form `ScalarOpTarget` for the
|
|
14
|
+
* arithmetic/comparison/logical switches.
|
|
15
|
+
*
|
|
16
|
+
* Note: the op target used here must emit comparison / logical ops
|
|
17
|
+
* in *numeric* form (result is a double 0.0/1.0 suitable for tensor
|
|
18
|
+
* write-back). For C this coincides with the regular value target;
|
|
19
|
+
* for JS a second target instance is needed because value-form
|
|
20
|
+
* comparisons return a JS boolean.
|
|
21
|
+
*/
|
|
22
|
+
import type { JitExpr } from "./jitTypes.js";
|
|
23
|
+
import type { FusibleChain } from "./fusion.js";
|
|
24
|
+
import { type ScalarOpTarget } from "./scalarEmit.js";
|
|
25
|
+
/** Scalar local name for a chain-produced tensor intermediate. */
|
|
26
|
+
export declare function fusedLocal(name: string): string;
|
|
27
|
+
export interface FusedTarget {
|
|
28
|
+
/** Format a numeric literal (e.g. `1` for JS, `1.0` for C). */
|
|
29
|
+
formatNumber(v: number): string;
|
|
30
|
+
/** Mangle a scalar variable reference (non-tensor). */
|
|
31
|
+
mangle(name: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Emit a per-element read of tensor var `name` — i.e. the expression
|
|
34
|
+
* that yields `data[__i]` for that tensor. The backend decides how
|
|
35
|
+
* the data pointer is named and whether it's aliased locally.
|
|
36
|
+
*/
|
|
37
|
+
tensorElemRead(name: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Emit a call to a scalar math builtin. The backend decides which
|
|
40
|
+
* builtins it supports and how they map to library functions (e.g.
|
|
41
|
+
* JS `Math.sin` vs C `sin`). Return `null` to reject.
|
|
42
|
+
*
|
|
43
|
+
* `name` is the builtin name (e.g. `"sin"`, `"mod"`, `"rem"`);
|
|
44
|
+
* `args` are already-emitted per-element scalar expressions.
|
|
45
|
+
*/
|
|
46
|
+
emitBuiltinCall(name: string, args: string[]): string | null;
|
|
47
|
+
}
|
|
48
|
+
/** Shared walker: emit a JitExpr as a per-element scalar expression. */
|
|
49
|
+
export declare function emitFusedScalarExpr(expr: JitExpr, chainLocals: ReadonlySet<string>, allTensorVars: ReadonlySet<string>, opTarget: ScalarOpTarget, fusedTarget: FusedTarget): string;
|
|
50
|
+
/**
|
|
51
|
+
* Find the first tensor-param name referenced in a chain's assigns.
|
|
52
|
+
* Used by both backends to pick the length-determining tensor.
|
|
53
|
+
*/
|
|
54
|
+
export declare function findTensorParamInChain(chain: FusibleChain, paramTensors: ReadonlySet<string>, allTensorVars: ReadonlySet<string>): string | null;
|
|
55
|
+
/**
|
|
56
|
+
* Collect distinct tensor names referenced in the chain's expression
|
|
57
|
+
* trees that are NOT produced by the chain itself (i.e. read from
|
|
58
|
+
* outside: params or pre-existing locals). Both backends need this to
|
|
59
|
+
* pick a length-reference tensor when no formal param is in the chain.
|
|
60
|
+
*/
|
|
61
|
+
export declare function collectInputTensors(chain: FusibleChain, allTensorVars: ReadonlySet<string>): Set<string>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fusion analysis for JIT backends (shared by JS-JIT and C-JIT).
|
|
3
|
+
*
|
|
4
|
+
* Scans a statement list for runs of tensor element-wise assigns that
|
|
5
|
+
* can be collapsed into a single per-element `for` loop. Each such run
|
|
6
|
+
* is a "fusible chain."
|
|
7
|
+
*
|
|
8
|
+
* A chain breaks on:
|
|
9
|
+
* - control flow (If/For/While)
|
|
10
|
+
* - any non-Assign statement
|
|
11
|
+
* - a tensor assign whose RHS references a tensor that is NOT an input
|
|
12
|
+
* param and NOT previously assigned within the same chain
|
|
13
|
+
* - a scalar assign (left for the per-op emitter)
|
|
14
|
+
*
|
|
15
|
+
* An optional **trailing reduction** is absorbed when the statement
|
|
16
|
+
* immediately after a tensor chain is of the form
|
|
17
|
+
* `acc = acc + reduce(lastChainVar)` or
|
|
18
|
+
* `acc = reduce(lastChainVar)`
|
|
19
|
+
* where `reduce` is sum/prod/max/min/mean/any/all. Absorbing the
|
|
20
|
+
* reduction lets the fused loop emit an inline accumulator instead of
|
|
21
|
+
* materialising the intermediate buffer.
|
|
22
|
+
*/
|
|
23
|
+
import type { JitExpr, JitStmt } from "./jitTypes.js";
|
|
24
|
+
import { BinaryOperation } from "../parser/types.js";
|
|
25
|
+
/** One tensor assign inside a fusible chain. */
|
|
26
|
+
export interface FusedAssign {
|
|
27
|
+
/** Destination tensor variable name. */
|
|
28
|
+
destName: string;
|
|
29
|
+
/** RHS expression tree (all tensor ops are element-wise). */
|
|
30
|
+
expr: JitExpr;
|
|
31
|
+
}
|
|
32
|
+
/** A trailing reduction absorbed into the fused loop. */
|
|
33
|
+
export interface FusedReduction {
|
|
34
|
+
/** Scalar accumulator variable name (e.g. `chain_acc`). */
|
|
35
|
+
accName: string;
|
|
36
|
+
/** Reduction builtin name (e.g. `sum`). */
|
|
37
|
+
reduceName: string;
|
|
38
|
+
/** The tensor variable being reduced (last chain dest). */
|
|
39
|
+
tensorName: string;
|
|
40
|
+
/**
|
|
41
|
+
* When true, the scalar statement is `acc = acc OP reduce(tensor)`,
|
|
42
|
+
* and `accOp` says which binary op combines the old accumulator with
|
|
43
|
+
* the reduction result. When false, it's a plain `acc = reduce(tensor)`.
|
|
44
|
+
*/
|
|
45
|
+
hasAccumulate: boolean;
|
|
46
|
+
accOp?: BinaryOperation;
|
|
47
|
+
}
|
|
48
|
+
/** Describes one fusible chain found in a statement list. */
|
|
49
|
+
export interface FusibleChain {
|
|
50
|
+
/** Index of the first statement in the chain (within the parent list). */
|
|
51
|
+
startIdx: number;
|
|
52
|
+
/** Number of statements consumed (tensor assigns + optional reduction). */
|
|
53
|
+
length: number;
|
|
54
|
+
/** The tensor assigns to fuse. */
|
|
55
|
+
assigns: FusedAssign[];
|
|
56
|
+
/** Optional trailing reduction. */
|
|
57
|
+
reduction?: FusedReduction;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Scan a statement list and return all fusible chains.
|
|
61
|
+
*
|
|
62
|
+
* `paramTensors` is the set of tensor parameter names (input data that
|
|
63
|
+
* will be read via `data[i]` in the fused loop).
|
|
64
|
+
* `allTensorVars` is the full set of tensor-typed variables (params +
|
|
65
|
+
* locals + outputs).
|
|
66
|
+
* `allowedUnaryOps` optionally restricts which tensor unary Call names
|
|
67
|
+
* are fusible. Defaults to `FUSIBLE_TENSOR_UNARY_OPS` (full set).
|
|
68
|
+
* The JS backend passes a restricted set that excludes transcendentals
|
|
69
|
+
* (V8 can't vectorize them, so fusing them is slower than per-op calls).
|
|
70
|
+
*/
|
|
71
|
+
export declare function findFusibleChains(stmts: JitStmt[], paramTensors: ReadonlySet<string>, allTensorVars: ReadonlySet<string>, allowedUnaryOps?: ReadonlySet<string>): FusibleChain[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fusible-operation name sets for JIT fusion analysis.
|
|
3
|
+
*
|
|
4
|
+
* Both the C-JIT and JS-JIT fusion paths use these to determine which
|
|
5
|
+
* tensor Call nodes are fusible element-wise unary ops or absorbable
|
|
6
|
+
* trailing reductions. The numeric op codes live in their respective
|
|
7
|
+
* backend files (feasibility.ts for C, jitHelpersTensor.ts for JS).
|
|
8
|
+
*/
|
|
9
|
+
/** Tensor unary builtins fusible into per-element loops. */
|
|
10
|
+
export declare const FUSIBLE_TENSOR_UNARY_OPS: ReadonlySet<string>;
|
|
11
|
+
/**
|
|
12
|
+
* JS-JIT-safe subset: excludes transcendentals (exp, sin, cos, tan, etc.)
|
|
13
|
+
* which V8 can't SIMD-vectorize. Fusing these into a scalar per-element
|
|
14
|
+
* loop is slower than calling libnumbl_ops per-op (which uses -fopenmp-simd).
|
|
15
|
+
* The C-JIT uses the full set because GCC/Clang vectorize via #pragma omp simd.
|
|
16
|
+
*/
|
|
17
|
+
export declare const FUSIBLE_TENSOR_UNARY_OPS_JS: ReadonlySet<string>;
|
|
18
|
+
/**
|
|
19
|
+
* Two-argument tensor element-wise builtins fusible into per-element loops.
|
|
20
|
+
* These are parsed as Call nodes (not Binary nodes) and need separate
|
|
21
|
+
* recognition in isPureElementwise / emitScalarExpr.
|
|
22
|
+
*/
|
|
23
|
+
export declare const FUSIBLE_TENSOR_BINARY_OPS: ReadonlySet<string>;
|
|
24
|
+
/** Tensor reduction builtins absorbable as trailing reductions. */
|
|
25
|
+
export declare const FUSIBLE_TENSOR_REDUCTION_OPS: ReadonlySet<string>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* JIT compilation entry point for interpreter function calls.
|
|
3
3
|
*/
|
|
4
|
-
import type { Interpreter } from "../interpreter.js";
|
|
5
|
-
import type { FunctionDef } from "../types.js";
|
|
4
|
+
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
5
|
+
import type { FunctionDef } from "../interpreter/types.js";
|
|
6
6
|
export declare const JIT_SKIP: unique symbol;
|
|
7
7
|
export declare function tryJitCall(interp: Interpreter, fn: FunctionDef, args: unknown[], nargout: number): unknown | typeof JIT_SKIP;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bail-safety gate for JIT bodies that contain I/O side effects.
|
|
3
|
+
*
|
|
4
|
+
* Mid-execution bails (JitBailToInterpreter / JitFuncHandleBailError)
|
|
5
|
+
* cause the interpreter to re-run the body from the top. If the body
|
|
6
|
+
* already emitted I/O before the bail, that output gets duplicated —
|
|
7
|
+
* which the user would notice.
|
|
8
|
+
*
|
|
9
|
+
* Rule: a body with any I/O statement may only be JIT-compiled if we
|
|
10
|
+
* can prove no bail can happen during execution. If there's no I/O,
|
|
11
|
+
* the body can be JIT'd normally (a bail just restarts silently).
|
|
12
|
+
*
|
|
13
|
+
* Walkers are IR-level — they see the actual lowered constructs that
|
|
14
|
+
* map 1:1 to runtime bail sites. The walkers recurse into the bodies
|
|
15
|
+
* of `UserCall`-ed functions (via `generatedIRBodies`), since a bail
|
|
16
|
+
* inside a callee still forces the caller to re-run.
|
|
17
|
+
*/
|
|
18
|
+
import type { JitStmt } from "./jitTypes.js";
|
|
19
|
+
import type { GeneratedFn } from "./jitLower.js";
|
|
20
|
+
/**
|
|
21
|
+
* Names of I/O-emitting builtins that the JIT is willing to lower as
|
|
22
|
+
* ExprStmt calls. Any `Call` to one of these in the lowered IR marks
|
|
23
|
+
* the body as having observable I/O.
|
|
24
|
+
*/
|
|
25
|
+
export declare const JIT_IO_BUILTINS: Set<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Walk a body + its transitively called function bodies and return
|
|
28
|
+
* whether the combined execution graph contains an I/O call.
|
|
29
|
+
*/
|
|
30
|
+
export declare function irHasIO(body: JitStmt[], generatedIRBodies: Map<string, GeneratedFn>): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Walk a body + its transitively called function bodies and return
|
|
33
|
+
* whether any construct exists that can throw `JitBailToInterpreter`
|
|
34
|
+
* or `JitFuncHandleBailError` at runtime.
|
|
35
|
+
*
|
|
36
|
+
* Bail-risky constructs:
|
|
37
|
+
* - AssignIndex / AssignIndexCol: may bail on out-of-bounds grow.
|
|
38
|
+
* - FuncHandleCall / UserDispatchCall: return-type check may bail.
|
|
39
|
+
* - UserCall: recurse into callee body.
|
|
40
|
+
*/
|
|
41
|
+
export declare function irHasBailRisk(body: JitStmt[], generatedIRBodies: Map<string, GeneratedFn>): boolean;
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* inside the loop body. On success the compiled code runs and output
|
|
8
8
|
* values are written back to the interpreter environment.
|
|
9
9
|
*/
|
|
10
|
-
import type { Interpreter } from "../interpreter.js";
|
|
11
|
-
import type { Stmt } from "
|
|
10
|
+
import type { Interpreter } from "../interpreter/interpreter.js";
|
|
11
|
+
import type { Stmt } from "../parser/types.js";
|
|
12
12
|
/**
|
|
13
13
|
* Attempt to JIT-compile and execute a for-loop statement.
|
|
14
14
|
* Returns true if JIT succeeded, false to fall back to interpretation.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - referenced: variables read inside the loop
|
|
7
7
|
* - hasReturn: whether the loop body contains a return statement
|
|
8
8
|
*/
|
|
9
|
-
import type { Stmt } from "
|
|
9
|
+
import type { Stmt } from "../parser/types.js";
|
|
10
10
|
export interface LoopVarInfo {
|
|
11
11
|
/** Variables referenced in the loop that must come from enclosing scope */
|
|
12
12
|
inputs: string[];
|
|
@@ -19,6 +19,18 @@ export interface LoopVarInfo {
|
|
|
19
19
|
export declare function analyzeForLoop(stmt: Stmt & {
|
|
20
20
|
type: "For";
|
|
21
21
|
}): LoopVarInfo;
|
|
22
|
+
/**
|
|
23
|
+
* Collect the names of all variables read in a sibling-tail starting at
|
|
24
|
+
* `startIdx` of the given stmt list. Used by the loop JIT to filter the
|
|
25
|
+
* loop's output set so that loop-internal temporaries don't get written
|
|
26
|
+
* back when no later code reads them.
|
|
27
|
+
*/
|
|
28
|
+
export declare function collectReadsFromSiblings(stmts: Stmt[], startIdx: number, out: Set<string>): void;
|
|
29
|
+
/**
|
|
30
|
+
* Analyze a top-level script body (list of statements) for JIT compilation.
|
|
31
|
+
* Used by `tryJitTopLevel` to wrap the whole main script as a synthetic fn.
|
|
32
|
+
*/
|
|
33
|
+
export declare function analyzeTopLevel(stmts: Stmt[]): LoopVarInfo;
|
|
22
34
|
/** Analyze a while loop statement for JIT compilation. */
|
|
23
35
|
export declare function analyzeWhileLoop(stmt: Stmt & {
|
|
24
36
|
type: "While";
|