@amritk/nish-x86_64-linux 0.26.0 → 0.28.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/INSTALL.md +13 -8
- package/bin/nish +0 -0
- package/docs/AI.md +27 -5
- package/package.json +1 -1
- package/runtime/core.d.ts +47 -0
- package/runtime/core.mjs +67 -0
- package/runtime/nish.d.ts +54 -5
- package/runtime/nish.h +67 -8
- package/runtime/nish.mjs +6 -0
- package/runtime/runtime-checksum.c +270 -0
- package/runtime/runtime-os.c +9 -4
- package/runtime/runtime-parallel.c +21 -0
- package/runtime/runtime-sandbox.c +470 -0
- package/runtime/runtime-sha256.c +239 -0
- package/runtime/runtime-simd.c +63 -2
- package/runtime/runtime-wasm.c +18 -0
- package/scripts/build.sh +60 -24
- package/std/README.md +16 -10
- package/std/compress/checksum.ts +88 -75
- package/std/compress/deflate.ts +224 -0
- package/std/compress/gzip.ts +52 -0
- package/std/crypto/bcrypt.ts +816 -280
- package/std/crypto/sha256.ts +335 -188
- package/std/json-equal.ts +335 -0
- package/std/json-format.ts +1070 -0
- package/std/json-number.ts +428 -0
- package/std/json-pointer.ts +245 -0
- package/std/json-value.ts +510 -17
- package/std/net/http-client.ts +1645 -0
- package/std/net/http-compress.ts +259 -16
- package/std/net/http1-client.ts +104 -19
- package/std/net/http1-server.ts +61 -12
- package/std/net/postgres.ts +576 -8
- package/std/net/websocket.ts +295 -14
- package/std/regex.ts +613 -52
- package/std/term-io.ts +35 -8
- package/std/yaml-json.ts +841 -0
package/INSTALL.md
CHANGED
|
@@ -254,7 +254,8 @@ routes are
|
|
|
254
254
|
# on the musl host, with its own clang and the runtime from this repository
|
|
255
255
|
clang app.ll runtime/runtime.c runtime/runtime-os.c runtime/runtime-parallel.c \
|
|
256
256
|
runtime/runtime-cross.c runtime/runtime-host.c runtime/runtime-net.c \
|
|
257
|
-
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-
|
|
257
|
+
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-sha256.c runtime/runtime-term.c \
|
|
258
|
+
runtime/runtime-bytes.c runtime/runtime-checksum.c runtime/runtime-sandbox.c -lm -o app
|
|
258
259
|
```
|
|
259
260
|
|
|
260
261
|
`--link`ing inside the container is the mistake to avoid: it shells out to the
|
|
@@ -390,7 +391,7 @@ it into `build/seed/`; `NISH_BOOTSTRAP=<path>` names one you already have and
|
|
|
390
391
|
skips the download. §2a has what the build does with it.
|
|
391
392
|
|
|
392
393
|
The published package ships `bin/` (the `nish` command, which is a launcher),
|
|
393
|
-
`runtime/` (the C runtime —
|
|
394
|
+
`runtime/` (the C runtime — thirteen translation units, the wasm subset and their
|
|
394
395
|
header — and `runtime/sqlite/`, SQLite's vendored source),
|
|
395
396
|
`scripts/build.sh` (the link pipeline), `std/` (the standard library) and
|
|
396
397
|
`docs/AI.md` (the rules card). The
|
|
@@ -403,12 +404,13 @@ working directory — and the binary runs from inside its own platform package
|
|
|
403
404
|
for exactly that reason.
|
|
404
405
|
|
|
405
406
|
Building the IR yourself rather than through `--link` means naming the runtime
|
|
406
|
-
on the `clang` line, and it is
|
|
407
|
+
on the `clang` line, and it is thirteen files:
|
|
407
408
|
|
|
408
409
|
```bash
|
|
409
410
|
clang app.ll runtime/runtime.c runtime/runtime-os.c runtime/runtime-parallel.c \
|
|
410
411
|
runtime/runtime-cross.c runtime/runtime-host.c runtime/runtime-net.c \
|
|
411
|
-
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-
|
|
412
|
+
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-sha256.c runtime/runtime-term.c \
|
|
413
|
+
runtime/runtime-bytes.c runtime/runtime-checksum.c runtime/runtime-sandbox.c -lm -o app
|
|
412
414
|
```
|
|
413
415
|
|
|
414
416
|
`runtime.c` is the part every program touches — the arena, strings, arrays,
|
|
@@ -421,14 +423,17 @@ the strings and arrays a task answers, a channel sends or a `Mutex` keeps out
|
|
|
421
423
|
of the arena they were made in, `runtime-host.c` holds the wall clock,
|
|
422
424
|
entropy, file times and signals, `runtime-net.c` the sockets of `nish:net`,
|
|
423
425
|
`runtime-simd.c` and `runtime-aes.c` the vector text search and AES-GCM,
|
|
424
|
-
`runtime-
|
|
426
|
+
`runtime-sha256.c` the SHA-256 block kernel `nish/crypto/sha256` hands its
|
|
427
|
+
blocks to on a CPU with the SHA instructions (`NISH_SHA256=soft` keeps the
|
|
428
|
+
portable path), `runtime-term.c` the stdin reads and terminal calls of `nish:term`,
|
|
425
429
|
`runtime-bytes.c` the byte-class runs of `nish/bytes`, which `nish/json` steps
|
|
426
|
-
over.
|
|
430
|
+
over, `runtime-checksum.c` the CRC-32 kernels of `nish/compress/checksum`,
|
|
431
|
+
and `runtime-sandbox.c` the confinement a `--sandbox` build applies.
|
|
427
432
|
They are separate so that each carries its own measured size ceiling
|
|
428
433
|
([docs/wp7-runtime.md](wp7-runtime.md)); nothing in the core calls into the
|
|
429
434
|
others, so a line that names only `runtime.c` and `runtime-os.c` still links a
|
|
430
|
-
program that uses none of the other
|
|
431
|
-
|
|
435
|
+
program that uses none of the other nine. `scripts/build.sh` compiles the other
|
|
436
|
+
nine beside any
|
|
432
437
|
`runtime.c` it is handed, so a build that goes through it — every `--link`,
|
|
433
438
|
and every `--profile` recipe in these documents — needs to name only the one.
|
|
434
439
|
|
package/bin/nish
CHANGED
|
Binary file
|
package/docs/AI.md
CHANGED
|
@@ -2181,8 +2181,9 @@ also watches the signal fd. None of `spawn`, `kill`, `waitPid` may be called in
|
|
|
2181
2181
|
a task or a parallel body; the two host facts may. `availableParallelism()` (`i32`, at least 1, no `--threads` needed) and
|
|
2182
2182
|
`totalMemory()` (`i64` bytes, or `-1`) size a program to the machine. None of
|
|
2183
2183
|
the five exists on a wasm target, and `spawn` and `waitPid` throw under Node.
|
|
2184
|
-
`setNice(n)` sets the nice value
|
|
2185
|
-
|
|
2184
|
+
`setNice(n)` sets the nice value, and it is lower-only even as root: `n` takes
|
|
2185
|
+
0..19 (`-22` outside it) and a value below the current one is `-13`, with no
|
|
2186
|
+
system call either way. `setIdlePriority()` moves the program to Linux's `SCHED_IDLE`
|
|
2186
2187
|
(`-95` on Darwin); each answers 0 or a negative errno. Call them at the top of
|
|
2187
2188
|
`main`, never in a task. An unprivileged process can never leave `SCHED_IDLE`
|
|
2188
2189
|
and an idle one can starve on a saturated machine, so keep a normal-priority
|
|
@@ -2201,6 +2202,10 @@ wait for it to be writable, then `connectResult(fd)` is 0 or the failure. Buffer
|
|
|
2201
2202
|
are `u8[]` only; an address is 18 bytes of one (IPv4 as `::ffff:a.b.c.d`, then
|
|
2202
2203
|
the port big-endian); hosts are numeric literals; to reach a name, resolve it first with
|
|
2203
2204
|
`nish/net/dns` (`DnsClient` on your loop, or the blocking `resolveHost`).
|
|
2205
|
+
To fetch a URL from a CLI, skip all of this: `nish/net/http-client`'s
|
|
2206
|
+
`httpFetch(new HttpRequest("GET", url), new HttpOptions())` blocks until the
|
|
2207
|
+
response's head is in and answers it with `body.readAll(limit)`, or null on a
|
|
2208
|
+
failure (an `HttpClient` keeps the connection and says why in `error`).
|
|
2204
2209
|
`netRead` / `netWrite` panic on a range outside the buffer.
|
|
2205
2210
|
`tcpListenFlags(host, port, backlog, flags)` is `tcpListen` with flag 1
|
|
2206
2211
|
`SO_REUSEPORT`, so several listeners, in one process or many, share a port (Linux
|
|
@@ -2614,7 +2619,8 @@ negative `DEFLATE_ERR_*` / `GZIP_ERR_*` code for any malformed stream, so test
|
|
|
2614
2619
|
it before reading `out`. `GzipWriter` and `GzipReader` stream. On HTTP/1.1,
|
|
2615
2620
|
`conn.respondEncoded(status, names, values, body, off, len, enc,
|
|
2616
2621
|
conn.acceptEncoding())` with an `HttpCompressor` from `nish/net/http-compress`
|
|
2617
|
-
negotiates, compresses
|
|
2622
|
+
negotiates, compresses when it pays (`minLength`, `minSavingPercent`,
|
|
2623
|
+
`segmentMode`; `enc.decision` says why not) and sets the fields. Do not compress a secret beside
|
|
2618
2624
|
text the client chose (BREACH). (No block, as for `nish/text`;
|
|
2619
2625
|
`tests/link/std_compress` is its program, and the user guide's
|
|
2620
2626
|
[compression page](guide/using-nish/compression.md) its walk-through.)
|
|
@@ -2654,13 +2660,13 @@ a `PgBatcher` built from a `PgBatchConfig` (`name`, `select` reading the key as
|
|
|
2654
2660
|
queue is full, or for a text key too long for `maxBytes`, with no room left in
|
|
2655
2661
|
`queueBytes`, with a NUL or not UTF-8 — and `take(conn)`
|
|
2656
2662
|
binds the waiting ones, each key once, as one execution of its `sql` over
|
|
2657
|
-
`unnest($1) with ordinality`, answering a run handle or -1. Hand that
|
|
2663
|
+
`unnest($1) with ordinality`, answering a run handle or -1. Set `binary` in the `PgBatchConfig` and each batch comes in binary: `take` opens its bind with `bindStartBinary`, and `row` reads the routing ordinal with `binaryInt` (`binary.failed` is saved and restored, so the caller's own decoding is untouched). Hand that
|
|
2658
2664
|
execution's `PG_ROW` to `row(run, conn)`, `PG_COMPLETE` to `end(run)`, an error
|
|
2659
2665
|
or `PG_LOST` to `fail(run)` (on a spent handle these do nothing and count in
|
|
2660
2666
|
`stray`), and after each call `next(run)` until
|
|
2661
2667
|
`PG_BATCH_NONE`: `PG_BATCH_ROW` (the connection's row answers request `tag`),
|
|
2662
2668
|
then one of `PG_BATCH_DONE`, `PG_BATCH_MISSING` or `PG_BATCH_FAILED` per
|
|
2663
|
-
request. It reads no clock: when to take is the loop's choice. (No block;
|
|
2669
|
+
request. It reads no clock: when to take is the loop's choice, or a `PgBatchClock`'s (`PgBatchClockConfig`: `minCount`, `factor` × the moving average of batch sizes, `maxWaitUs`, the idle bypass `lightCount`; defaults are a fixed window), which `takeDue(conn, clock, nowUs, pool.inFlight())` consults after `clock.arrived(nowUs)` per add; `PgBatchTurns` wakes one collecting connection only when its batch is due. (No block;
|
|
2664
2670
|
`tests/postgres/live`'s `batch` scenario runs it against a server, and the user
|
|
2665
2671
|
guide's [PostgreSQL page](guide/using-nish/postgres.md#batching-keyed-reads)
|
|
2666
2672
|
its walk-through.)
|
|
@@ -2817,6 +2823,22 @@ const settings = (): string => readFileSync("settings.txt");
|
|
|
2817
2823
|
export const main = (): i32 => settings().length;
|
|
2818
2824
|
```
|
|
2819
2825
|
|
|
2826
|
+
The policy judges the source; `--sandbox` (Linux, `--link` and `nish run`)
|
|
2827
|
+
makes the kernel hold the running binary to the same set. Before any C
|
|
2828
|
+
constructor runs, it withholds every file, process and socket operation `main`
|
|
2829
|
+
does not reach, C code it links included. A file operation it refuses fails
|
|
2830
|
+
like a missing permission; a refused process or socket call ends the program
|
|
2831
|
+
with `SIGSYS` (status 159); a kernel that cannot apply it exits 126 before
|
|
2832
|
+
`main` unless built with `--sandbox=best-effort`. A darwin target, a library
|
|
2833
|
+
with no `main` and `--emit-napi` refuse the flag
|
|
2834
|
+
([LANGUAGE.md](LANGUAGE.md#the-sandbox)). Only under `--sandbox` may an
|
|
2835
|
+
`--allow` list scope `fs.read` or `fs.write` to a directory
|
|
2836
|
+
(`--allow fs.read=/srv/data`): the directory must exist at build time, and
|
|
2837
|
+
the kernel grants the capability beneath it alone — except that a `main`
|
|
2838
|
+
reaching `process.spawn` can still read every file beneath `/`, so that
|
|
2839
|
+
`exec` can load a program. Any other scope, a scope
|
|
2840
|
+
in `--deny` and a scope without `--sandbox` are usage errors, exit 2.
|
|
2841
|
+
|
|
2820
2842
|
## Before you say it compiles
|
|
2821
2843
|
|
|
2822
2844
|
Run it. `nish file.ts --json` is one command and it is the only proof.
|
package/package.json
CHANGED
package/runtime/core.d.ts
CHANGED
|
@@ -7,3 +7,50 @@ export * from "./core/host.js";
|
|
|
7
7
|
export * from "./core/numbers.js";
|
|
8
8
|
export * from "./core/result.js";
|
|
9
9
|
export * from "./core/strings.js";
|
|
10
|
+
|
|
11
|
+
// `nish:simd`: what `--emit-ts` writes for a program's `import ... from "nish:simd"`.
|
|
12
|
+
import type { f32, f64, i32, u16, u32, u8 } from "./core/numbers.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A sixteen-byte vector of lanes. Opaque: TypeScript refuses `+` on one, as
|
|
16
|
+
* `nish` does, but lets `===` and `<` through, which `nish` refuses. Under
|
|
17
|
+
* Node it is a typed array made once and never written after.
|
|
18
|
+
*/
|
|
19
|
+
export interface u8x16 { readonly __nishSimd: "u8x16"; readonly __lane: u8 }
|
|
20
|
+
export interface u16x8 { readonly __nishSimd: "u16x8"; readonly __lane: u16 }
|
|
21
|
+
export interface i32x4 { readonly __nishSimd: "i32x4"; readonly __lane: i32 }
|
|
22
|
+
export interface u32x4 { readonly __nishSimd: "u32x4"; readonly __lane: u32 }
|
|
23
|
+
export interface f32x4 { readonly __nishSimd: "f32x4"; readonly __lane: f32 }
|
|
24
|
+
export interface f64x2 { readonly __nishSimd: "f64x2"; readonly __lane: f64 }
|
|
25
|
+
/** Any of the six. */
|
|
26
|
+
export type SimdVector = u8x16 | u16x8 | i32x4 | u32x4 | f32x4 | f64x2;
|
|
27
|
+
/** One value per lane, lane 0 first. */
|
|
28
|
+
export declare function u8x16(
|
|
29
|
+
a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8,
|
|
30
|
+
a8: u8, a9: u8, a10: u8, a11: u8, a12: u8, a13: u8, a14: u8, a15: u8
|
|
31
|
+
): u8x16;
|
|
32
|
+
export declare function u16x8(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16): u16x8;
|
|
33
|
+
export declare function i32x4(a0: i32, a1: i32, a2: i32, a3: i32): i32x4;
|
|
34
|
+
export declare function u32x4(a0: u32, a1: u32, a2: u32, a3: u32): u32x4;
|
|
35
|
+
export declare function f32x4(a0: f32, a1: f32, a2: f32, a3: f32): f32x4;
|
|
36
|
+
export declare function f64x2(a0: f64, a1: f64): f64x2;
|
|
37
|
+
/** `x` in every lane. */
|
|
38
|
+
export declare function splatU8x16(x: u8): u8x16;
|
|
39
|
+
export declare function splatU16x8(x: u16): u16x8;
|
|
40
|
+
export declare function splatI32x4(x: i32): i32x4;
|
|
41
|
+
export declare function splatU32x4(x: u32): u32x4;
|
|
42
|
+
export declare function splatF32x4(x: f32): f32x4;
|
|
43
|
+
export declare function splatF64x2(x: f64): f64x2;
|
|
44
|
+
/** `xs[i]` to `xs[i + N - 1]`, bounds-checked once for the whole vector. */
|
|
45
|
+
export declare function loadU8x16(xs: readonly u8[], i: i32): u8x16;
|
|
46
|
+
export declare function loadU16x8(xs: readonly u16[], i: i32): u16x8;
|
|
47
|
+
export declare function loadI32x4(xs: readonly i32[], i: i32): i32x4;
|
|
48
|
+
export declare function loadU32x4(xs: readonly u32[], i: i32): u32x4;
|
|
49
|
+
export declare function loadF32x4(xs: readonly f32[], i: i32): f32x4;
|
|
50
|
+
export declare function loadF64x2(xs: readonly f64[], i: i32): f64x2;
|
|
51
|
+
/** The lanes of `v` into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
52
|
+
export declare function store<V extends SimdVector>(v: V, xs: V["__lane"][], i: i32): void;
|
|
53
|
+
/** Lane `k`, an integer literal in range. */
|
|
54
|
+
export declare function extract<V extends SimdVector>(v: V, k: i32): V["__lane"];
|
|
55
|
+
/** A new vector: `v` with lane `k` set to `x`. */
|
|
56
|
+
export declare function replace<V extends SimdVector>(v: V, k: i32, x: V["__lane"]): V;
|
package/runtime/core.mjs
CHANGED
|
@@ -48,8 +48,75 @@
|
|
|
48
48
|
*
|
|
49
49
|
* The rewrite rules that call these helpers are listed in docs/wp13-differential.md.
|
|
50
50
|
*/
|
|
51
|
+
import { panicIndex, toIndex } from "./core/checks.mjs";
|
|
52
|
+
|
|
51
53
|
export * from "./core/arrays.mjs";
|
|
52
54
|
export * from "./core/host.mjs";
|
|
53
55
|
export * from "./core/numbers.mjs";
|
|
54
56
|
export * from "./core/result.mjs";
|
|
55
57
|
export * from "./core/strings.mjs";
|
|
58
|
+
|
|
59
|
+
// ---- `nish:simd` ------------------------------------------------------------
|
|
60
|
+
// A vector is a fresh typed array of its lanes, made once and never written
|
|
61
|
+
// after: `replace` copies, so a vector held in two places stays one value, as
|
|
62
|
+
// the native `<N x T>` register is. The array type does the lane arithmetic a
|
|
63
|
+
// native lane does: a `u8` lane wraps through `Uint8Array`, an `f32` lane rounds
|
|
64
|
+
// through `Float32Array`. `load…` and `store` check the whole vector once, and
|
|
65
|
+
// panic with the native words: the first index, and the array's length.
|
|
66
|
+
|
|
67
|
+
const simdMake = (Lanes) => (...lanes) => new Lanes(lanes);
|
|
68
|
+
const simdSplat = (Lanes) => (x) => new Lanes(16 / Lanes.BYTES_PER_ELEMENT).fill(x);
|
|
69
|
+
// The first index of `count` lanes at `i` in `xs`, or the native panic naming
|
|
70
|
+
// a lane that is out of range: the first when it is, else the last. A negative
|
|
71
|
+
// index prints as the unsigned 64-bit number the native compare saw.
|
|
72
|
+
const simdAt = (xs, i, count) => {
|
|
73
|
+
const k = toIndex(i);
|
|
74
|
+
if (k < 0) panicIndex(BigInt.asUintN(64, BigInt(k)), xs.length);
|
|
75
|
+
if (k >= xs.length) panicIndex(k, xs.length);
|
|
76
|
+
if (k + count > xs.length) panicIndex(k + count - 1, xs.length);
|
|
77
|
+
return k;
|
|
78
|
+
};
|
|
79
|
+
const simdLoad = (Lanes) => (xs, i) => {
|
|
80
|
+
const count = 16 / Lanes.BYTES_PER_ELEMENT;
|
|
81
|
+
const k = simdAt(xs, i, count);
|
|
82
|
+
const out = new Lanes(count);
|
|
83
|
+
for (let j = 0; j < count; j++) out[j] = xs[k + j];
|
|
84
|
+
return out;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const u8x16 = simdMake(Uint8Array);
|
|
88
|
+
export const u16x8 = simdMake(Uint16Array);
|
|
89
|
+
export const i32x4 = simdMake(Int32Array);
|
|
90
|
+
export const u32x4 = simdMake(Uint32Array);
|
|
91
|
+
export const f32x4 = simdMake(Float32Array);
|
|
92
|
+
export const f64x2 = simdMake(Float64Array);
|
|
93
|
+
export const splatU8x16 = simdSplat(Uint8Array);
|
|
94
|
+
export const splatU16x8 = simdSplat(Uint16Array);
|
|
95
|
+
export const splatI32x4 = simdSplat(Int32Array);
|
|
96
|
+
export const splatU32x4 = simdSplat(Uint32Array);
|
|
97
|
+
export const splatF32x4 = simdSplat(Float32Array);
|
|
98
|
+
export const splatF64x2 = simdSplat(Float64Array);
|
|
99
|
+
export const loadU8x16 = simdLoad(Uint8Array);
|
|
100
|
+
export const loadU16x8 = simdLoad(Uint16Array);
|
|
101
|
+
export const loadI32x4 = simdLoad(Int32Array);
|
|
102
|
+
export const loadU32x4 = simdLoad(Uint32Array);
|
|
103
|
+
export const loadF32x4 = simdLoad(Float32Array);
|
|
104
|
+
export const loadF64x2 = simdLoad(Float64Array);
|
|
105
|
+
|
|
106
|
+
/** `store(v, xs, i)`: the lanes into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
107
|
+
export function store(v, xs, i) {
|
|
108
|
+
const k = simdAt(xs, i, v.length);
|
|
109
|
+
for (let j = 0; j < v.length; j++) xs[k + j] = v[j];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** `extract(v, k)`: lane `k`, a constant the checker held in range. */
|
|
113
|
+
export function extract(v, k) {
|
|
114
|
+
return v[k];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** `replace(v, k, x)`: a new vector, `v` with lane `k` set to `x`. */
|
|
118
|
+
export function replace(v, k, x) {
|
|
119
|
+
const out = v.slice();
|
|
120
|
+
out[k] = x;
|
|
121
|
+
return out;
|
|
122
|
+
}
|
package/runtime/nish.d.ts
CHANGED
|
@@ -356,10 +356,10 @@ declare function availableParallelism(): i32;
|
|
|
356
356
|
/** Bytes of physical memory, or -1 when the host does not say. */
|
|
357
357
|
declare function totalMemory(): i64;
|
|
358
358
|
/**
|
|
359
|
-
* Set this process's nice value to `n
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
* it. Throws under Node.
|
|
359
|
+
* Set this process's nice value to `n`, which must be 0..19: 0, or a negative
|
|
360
|
+
* errno. Lower-only, even as root: `n` outside 0..19 is -22 (EINVAL), and `n`
|
|
361
|
+
* below the current value is -13 (EACCES), both with no system call. Children
|
|
362
|
+
* started afterwards inherit it. Throws under Node.
|
|
363
363
|
*/
|
|
364
364
|
declare function setNice(n: i32): i32;
|
|
365
365
|
/**
|
|
@@ -588,7 +588,7 @@ declare module "nish:process" {
|
|
|
588
588
|
export function availableParallelism(): i32;
|
|
589
589
|
/** Bytes of physical memory, or -1. */
|
|
590
590
|
export function totalMemory(): i64;
|
|
591
|
-
/** Set this process's nice value
|
|
591
|
+
/** Set this process's nice value, 0..19 only: 0, -22 outside it, or -13 below the current value (lower-only, even as root). */
|
|
592
592
|
export function setNice(n: i32): i32;
|
|
593
593
|
/**
|
|
594
594
|
* Move this process to `SCHED_IDLE`: 0, a negative errno, or -95 off Linux.
|
|
@@ -698,6 +698,55 @@ declare module "nish:unsafe" {
|
|
|
698
698
|
export function readCString(p: CPtr): string;
|
|
699
699
|
}
|
|
700
700
|
|
|
701
|
+
// `nish:simd` (docs/LANGUAGE.md -> Vectors): the six sixteen-byte vector
|
|
702
|
+
// types and the calls that make, load, store and take one apart. Under Node,
|
|
703
|
+
// `runtime/nish.mjs` answers the import with `runtime/core.mjs`'s names.
|
|
704
|
+
declare module "nish:simd" {
|
|
705
|
+
/**
|
|
706
|
+
* A sixteen-byte vector of lanes. Opaque: TypeScript refuses `+` on one, as
|
|
707
|
+
* `nish` does, but lets `===` and `<` through, which `nish` refuses. Under
|
|
708
|
+
* Node it is a typed array made once and never written after.
|
|
709
|
+
*/
|
|
710
|
+
export interface u8x16 { readonly __nishSimd: "u8x16"; readonly __lane: u8 }
|
|
711
|
+
export interface u16x8 { readonly __nishSimd: "u16x8"; readonly __lane: u16 }
|
|
712
|
+
export interface i32x4 { readonly __nishSimd: "i32x4"; readonly __lane: i32 }
|
|
713
|
+
export interface u32x4 { readonly __nishSimd: "u32x4"; readonly __lane: u32 }
|
|
714
|
+
export interface f32x4 { readonly __nishSimd: "f32x4"; readonly __lane: f32 }
|
|
715
|
+
export interface f64x2 { readonly __nishSimd: "f64x2"; readonly __lane: f64 }
|
|
716
|
+
/** Any of the six. */
|
|
717
|
+
export type SimdVector = u8x16 | u16x8 | i32x4 | u32x4 | f32x4 | f64x2;
|
|
718
|
+
/** One value per lane, lane 0 first. */
|
|
719
|
+
export function u8x16(
|
|
720
|
+
a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8,
|
|
721
|
+
a8: u8, a9: u8, a10: u8, a11: u8, a12: u8, a13: u8, a14: u8, a15: u8
|
|
722
|
+
): u8x16;
|
|
723
|
+
export function u16x8(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16): u16x8;
|
|
724
|
+
export function i32x4(a0: i32, a1: i32, a2: i32, a3: i32): i32x4;
|
|
725
|
+
export function u32x4(a0: u32, a1: u32, a2: u32, a3: u32): u32x4;
|
|
726
|
+
export function f32x4(a0: f32, a1: f32, a2: f32, a3: f32): f32x4;
|
|
727
|
+
export function f64x2(a0: f64, a1: f64): f64x2;
|
|
728
|
+
/** `x` in every lane. */
|
|
729
|
+
export function splatU8x16(x: u8): u8x16;
|
|
730
|
+
export function splatU16x8(x: u16): u16x8;
|
|
731
|
+
export function splatI32x4(x: i32): i32x4;
|
|
732
|
+
export function splatU32x4(x: u32): u32x4;
|
|
733
|
+
export function splatF32x4(x: f32): f32x4;
|
|
734
|
+
export function splatF64x2(x: f64): f64x2;
|
|
735
|
+
/** `xs[i]` to `xs[i + N - 1]`, bounds-checked once for the whole vector. */
|
|
736
|
+
export function loadU8x16(xs: readonly u8[], i: i32): u8x16;
|
|
737
|
+
export function loadU16x8(xs: readonly u16[], i: i32): u16x8;
|
|
738
|
+
export function loadI32x4(xs: readonly i32[], i: i32): i32x4;
|
|
739
|
+
export function loadU32x4(xs: readonly u32[], i: i32): u32x4;
|
|
740
|
+
export function loadF32x4(xs: readonly f32[], i: i32): f32x4;
|
|
741
|
+
export function loadF64x2(xs: readonly f64[], i: i32): f64x2;
|
|
742
|
+
/** The lanes of `v` into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
743
|
+
export function store<V extends SimdVector>(v: V, xs: V["__lane"][], i: i32): void;
|
|
744
|
+
/** Lane `k`, an integer literal in range. */
|
|
745
|
+
export function extract<V extends SimdVector>(v: V, k: i32): V["__lane"];
|
|
746
|
+
/** A new vector: `v` with lane `k` set to `x`. */
|
|
747
|
+
export function replace<V extends SimdVector>(v: V, k: i32, x: V["__lane"]): V;
|
|
748
|
+
}
|
|
749
|
+
|
|
701
750
|
declare module "nish:io" {
|
|
702
751
|
/** `s` to stdout with no trailing newline and no conversion. */
|
|
703
752
|
export function write(s: string): void;
|
package/runtime/nish.h
CHANGED
|
@@ -9,14 +9,17 @@
|
|
|
9
9
|
* functions, the directory and subprocess calls, `nish_getenv`, the monotonic
|
|
10
10
|
* clock, `nish_platform` / `nish_arch` — and runtime-parallel.c, runtime-host.c,
|
|
11
11
|
* runtime-net.c, runtime-simd.c (the byte searches that read a vector at a
|
|
12
|
-
* time), runtime-aes.c (AES-GCM on the CPU's AES instructions)
|
|
13
|
-
* runtime-
|
|
12
|
+
* time), runtime-aes.c (AES-GCM on the CPU's AES instructions),
|
|
13
|
+
* runtime-sha256.c (SHA-256 on the CPU's SHA instructions), runtime-checksum.c
|
|
14
|
+
* (CRC-32 on its carry-less multiply or CRC instructions) and runtime-term.c
|
|
15
|
+
* (stdin and the terminal, `nish:term`) split off
|
|
14
16
|
* the same way since. They are separate so that each carries its own measured
|
|
15
17
|
* code-size ceiling (docs/wp7-runtime.md, "Runtime additions and budget"); a
|
|
16
18
|
* host links all of them, which `scripts/build.sh` does for you when handed
|
|
17
|
-
* runtime.c, runtime-aes.c included: the
|
|
18
|
-
* std/crypto/aes.ts,
|
|
19
|
-
*
|
|
19
|
+
* runtime.c, runtime-aes.c, runtime-sha256.c and runtime-checksum.c included: the
|
|
20
|
+
* compiler calls their kernels from std/crypto/aes.ts, std/crypto/sha256.ts and
|
|
21
|
+
* std/compress/checksum.ts, so `scripts/build.sh` pairs each of them with
|
|
22
|
+
* runtime.c and `src/run-cache.ts` caches them like the others. `tests/run.js` checks that every runtime function
|
|
20
23
|
* declared in runtime.ts has a prototype in this file.
|
|
21
24
|
*
|
|
22
25
|
* Headers generated by `nish --emit-header` include this one, so keep
|
|
@@ -282,6 +285,20 @@ nish_array *nish_alloc_array(uint64_t elem_size, uint64_t len);
|
|
|
282
285
|
Variable-time: never call it on a secret. */
|
|
283
286
|
int64_t nish_regex_scan(const nish_str *s, const nish_array *masks, int64_t depth, int64_t off, int64_t width,
|
|
284
287
|
int64_t from);
|
|
288
|
+
/* `Math.floor`, `Math.ceil` and `Math.trunc`, and the floor `Math.round`
|
|
289
|
+
takes (#943): each answers as C's `floor`, `ceil` and `trunc` do, -0, the
|
|
290
|
+
infinities and NaN included. A module for x86-64 calls them and registers a
|
|
291
|
+
constructor in `@llvm.global_ctors` that passes `nish_round_init` libm's
|
|
292
|
+
`floor`, `ceil` and `trunc`; it asks the CPU for SSE4.1 once before `main`
|
|
293
|
+
and keeps them on a machine without it, or under `NISH_SIMD=scalar`. Each
|
|
294
|
+
is otherwise SSE4.1's `roundsd`, so the constructor must run first. The
|
|
295
|
+
runtime references no libm symbol: the module that rounds does. They live
|
|
296
|
+
in runtime/runtime-simd.c; runtime-wasm.c has the wasm32 ones for host IR
|
|
297
|
+
that `scripts/build.sh --profile wasm` links. */
|
|
298
|
+
void nish_round_init(double (*floor_fn)(double), double (*ceil_fn)(double), double (*trunc_fn)(double));
|
|
299
|
+
double nish_floor(double x);
|
|
300
|
+
double nish_ceil(double x);
|
|
301
|
+
double nish_trunc(double x);
|
|
285
302
|
/* No array grows past 2^31 - 1 elements and no string past 2^31 - 1 bytes:
|
|
286
303
|
* `nish_array_grow`, `nish_alloc_array` and `nish_str_concat` fail as an
|
|
287
304
|
* allocation does (`nish: out of memory`, exit 1; a trap on wasm) rather than
|
|
@@ -334,6 +351,40 @@ void nish_aes_ctr(const nish_array *rk, int32_t rounds, const nish_array *j0, co
|
|
|
334
351
|
`rk` instead, and they are the same H. 0 <= length <= data.len. */
|
|
335
352
|
void nish_aes_ghash(nish_array *y, uint64_t hHi, uint64_t hLo, const nish_array *rk, const nish_array *data,
|
|
336
353
|
int32_t length);
|
|
354
|
+
/* ---- SHA-256 on the CPU's SHA instructions --------------------------------
|
|
355
|
+
* runtime/runtime-sha256.c: SHA-NI on x86-64, the ARMv8 SHA-256 instructions
|
|
356
|
+
* on AArch64. The compiler calls the kernel in place of std/crypto/sha256.ts's
|
|
357
|
+
* private `sha256Compress`, behind `nish_sha256_hw`, and calls the Nish
|
|
358
|
+
* function itself when either answers 0. Constant time in the state and the
|
|
359
|
+
* block. */
|
|
360
|
+
/* 1 when this process runs the kernel, 0 when it runs the Nish code. Resolved
|
|
361
|
+
on the first call and fixed from then on: `NISH_SHA256=soft` pins 0; unset,
|
|
362
|
+
`hw` or any other value is the best this machine has, read on that call from
|
|
363
|
+
CPUID (leaf 7's SHA, leaf 1's SSE4.1 and SSSE3), AArch64 Linux's AT_HWCAP
|
|
364
|
+
(SHA2) or macOS's `hw.optional.arm.FEAT_SHA256`. Always 0 on other targets,
|
|
365
|
+
wasm32 among them. */
|
|
366
|
+
int32_t nish_sha256_hw(void);
|
|
367
|
+
/* FIPS 180-4 §6.2.2 on the 64 bytes at src[at..at + 64) (u8[]), into the hash
|
|
368
|
+
value h[0..8) (u32[]); 1 when it ran. Answers 0 and writes nothing unless
|
|
369
|
+
h.len >= 8, w.len >= 64 and 0 <= at <= src.len - 64, `sha256Compress`'s
|
|
370
|
+
guard, so the caller's fallback panics as the Nish function does. `w` (u32[],
|
|
371
|
+
the message schedule the Nish code fills) is neither read nor written. */
|
|
372
|
+
int32_t nish_sha256_compress(nish_array *h, const nish_array *w, const nish_array *src, int32_t at);
|
|
373
|
+
/* ---- CRC-32 on the CPU's carry-less multiply or CRC instructions ---------
|
|
374
|
+
* runtime/runtime-checksum.c: PCLMULQDQ folding on x86-64, the ARMv8 CRC32
|
|
375
|
+
* instructions on AArch64. The compiler calls the kernel in
|
|
376
|
+
* place of std/compress/checksum.ts's private `crc32Walk`, behind
|
|
377
|
+
* `nish_crc32_hw`, and calls the Nish walker itself when that answers 0. */
|
|
378
|
+
/* 1 when this process runs the kernel, 0 when it runs the Nish tables.
|
|
379
|
+
Resolved on the first call and fixed from then on: `NISH_CRC32=soft` pins 0;
|
|
380
|
+
unset or any other value is the best this machine has, read on that call
|
|
381
|
+
from CPUID leaf 1 (PCLMULQDQ, SSE4.1), AArch64's AT_HWCAP (CRC32) or
|
|
382
|
+
Darwin's hw.optional sysctls. Always 0 on other targets, wasm32 among them. */
|
|
383
|
+
int32_t nish_crc32_hw(void);
|
|
384
|
+
/* The CRC-32 (ISO 3309, RFC 1952) `crc` extended over buf[off..off+len)
|
|
385
|
+
(u8[]), conditioned as zlib's crc32(): 0 starts a message, and the answer
|
|
386
|
+
continues one. The caller has checked 0 <= off <= off + len <= buf.len. */
|
|
387
|
+
uint32_t nish_crc32_update(uint32_t crc, const nish_array *buf, int32_t off, int32_t len);
|
|
337
388
|
|
|
338
389
|
/* `secureZero(bytes)` (#385): sets every byte of `bytes` to zero through
|
|
339
390
|
* `volatile` stores, out of line, so that neither `-O2` nor `-flto` can drop
|
|
@@ -480,9 +531,9 @@ nish_array *nish_wait_pid(int32_t pid, int32_t flags);
|
|
|
480
531
|
* page size; Darwin: `hw.memsize`), or -1 where the host does not say. */
|
|
481
532
|
int64_t nish_total_memory(void);
|
|
482
533
|
/* `setNice(n)`: this process's nice value set to `n` (`setpriority`), 0 or a
|
|
483
|
-
* negative errno.
|
|
484
|
-
*
|
|
485
|
-
* WASI. */
|
|
534
|
+
* negative errno. Lower-only, as root too: `n` takes 0..19, and anything else
|
|
535
|
+
* is -22 (-EINVAL) with no system call; `n` below the current value is -13
|
|
536
|
+
* (-EACCES) with none either. -ENOSYS under WASI. */
|
|
486
537
|
int32_t nish_set_nice(int32_t n);
|
|
487
538
|
/* `setIdlePriority()`: this process moved to `SCHED_IDLE` (Linux), 0 or a
|
|
488
539
|
* negative errno; -95 (Linux's EOPNOTSUPP) elsewhere, -ENOSYS under WASI. An
|
|
@@ -727,6 +778,14 @@ int64_t nish_cpu_count(void);
|
|
|
727
778
|
* rounded up, and `NISH_NUM_THREADS` when it is set to a positive number. At
|
|
728
779
|
* least 1; 1 under WASI. Read each call (runtime-os.c). */
|
|
729
780
|
int64_t nish_cpu_online(void);
|
|
781
|
+
/* WP37 `--sandbox` (runtime-sandbox.c): `nish_sandbox` confines the process to
|
|
782
|
+
the capability mask `caps` from `.preinit_array`, `mode` 1 strict and 2
|
|
783
|
+
best-effort, and `nish_sandbox_check` refuses to run at the top of `main`
|
|
784
|
+
when it never ran. The directory lists are a later stage's and are null.
|
|
785
|
+
`nish_cpu_prime` caches the pool's CPU count while /sys is still readable. */
|
|
786
|
+
void nish_sandbox(int32_t caps, int32_t mode, const char *read_dirs, const char *write_dirs);
|
|
787
|
+
void nish_sandbox_check(void);
|
|
788
|
+
void nish_cpu_prime(void);
|
|
730
789
|
void nish_parallel_range(nish_par_body body, void *ctx, int64_t len, int64_t grain);
|
|
731
790
|
/* Keeps every later region and join on threads created and joined per call,
|
|
732
791
|
* as before the pool existed, so no parked worker outlives the code it would
|
package/runtime/nish.mjs
CHANGED
|
@@ -314,6 +314,9 @@ provide("arena", shim.arena);
|
|
|
314
314
|
// zero-fills it. `nish:unsafe` and `nish:term` are each answered by a module
|
|
315
315
|
// that hands back the globals installed above: its functions are globals of this module either
|
|
316
316
|
// way, and the import is what the compiler requires a program to write.
|
|
317
|
+
// `nish:simd` is `runtime/core.mjs`, whose vectors are typed arrays made once
|
|
318
|
+
// and never written after, so `--emit-ts` output and a program run as it was
|
|
319
|
+
// written share one implementation.
|
|
317
320
|
const UNSAFE_EXPORTS = ["uncheckedGet", "uncheckedSet", "wrappingAdd", "wrappingSub", "wrappingMul"];
|
|
318
321
|
const unsafeSource = UNSAFE_EXPORTS.map((name) => `export const ${name} = globalThis.${name};`).join("\n");
|
|
319
322
|
const TERM_EXPORTS = ["readStdin", "waitStdin", "isTerminal", "terminalSize", "setRawMode", "setTerminalRestore"];
|
|
@@ -326,6 +329,9 @@ registerHooks({
|
|
|
326
329
|
if (specifier === "nish:unsafe") {
|
|
327
330
|
return { url: `data:text/javascript,${encodeURIComponent(unsafeSource)}`, shortCircuit: true };
|
|
328
331
|
}
|
|
332
|
+
if (specifier === "nish:simd") {
|
|
333
|
+
return next(new URL("./core.mjs", import.meta.url).href, context);
|
|
334
|
+
}
|
|
329
335
|
if (specifier === "nish:term") {
|
|
330
336
|
return { url: `data:text/javascript,${encodeURIComponent(termSource)}`, shortCircuit: true };
|
|
331
337
|
}
|