mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-25 06:24:27 +08:00
ThreadSlots<K, V> holds one value per key and thread, like a WeakMap that each thread has its own copy of; under Node.js it is a WeakMap per name and thread. Setting a value never writes the key, so values can be set on published keys. Classes used as keys carry a 32-bit slot word after their header words, assigned on the first set for a key (with a compare-and-swap for a published key) and never reused. Each family has one block per thread that maps slot indices to values through pages of 1024 entries. get and has are inline reads of the slot word, the page and the entry; set and delete call scr_slots.c, which holds one reference to each value. A key class's free paths release the key's values, and thread exit releases the rest.
164 lines
5.5 KiB
JavaScript
164 lines
5.5 KiB
JavaScript
import { withWorkerRuntimeVariants } from "./worker-matrix.mjs";
|
|
import { withLibraryRuntimeFlavors } from "./library-matrix.mjs";
|
|
|
|
/**
|
|
* Shared release-runtime pack matrix. Platform package scripts provide the
|
|
* target descriptor, then this module fixes feature reachability and the
|
|
* compile/link flags required by every generated runtime object.
|
|
*/
|
|
const any = (...features) => ({ any: features });
|
|
const all = (...features) => ({ all: features });
|
|
|
|
const BASE_RUNTIME_SOURCES = [
|
|
"scr_context.c",
|
|
"scr_shared.c",
|
|
"scr_number.c",
|
|
"scr_bigint.c",
|
|
"scr_string.c",
|
|
"scr_grapheme.c",
|
|
"scr_array.c",
|
|
"scr_bytes.c",
|
|
"scr_bytes_io.c",
|
|
"scr_fs_cp.c",
|
|
"scr_map.c",
|
|
"scr_closure.c",
|
|
"scr_ffi.c",
|
|
"scr_object.c",
|
|
"scr_union.c",
|
|
"scr_exception.c",
|
|
"scr_error.c",
|
|
"scr_console.c",
|
|
"scr_lib.c",
|
|
"scr_hash.c",
|
|
"scr_path.c",
|
|
"scr_os.c",
|
|
"scr_url.c",
|
|
"scr_url_params.c",
|
|
"scr_json.c",
|
|
"scr_node_builtin.c",
|
|
"scr_async.c",
|
|
"scr_crypto_async.c",
|
|
"scr_child.c",
|
|
"scr_cycle.c",
|
|
"scr_publish.c",
|
|
"scr_region.c",
|
|
"scr_itable.c",
|
|
"scr_slots.c",
|
|
"scr_alloc.c",
|
|
];
|
|
|
|
const OPTIONAL = [
|
|
["scr_copying.c", "copying"],
|
|
["scr_file_handle.c", "fileHandle"],
|
|
["scr_regex.c", "regex"],
|
|
["scr_glob.c", "regex"],
|
|
["scr_idna.c", "regex"],
|
|
["scr_assert.c", any("assert", "regex", "symbol")],
|
|
["scr_inspect.c", "inspect"],
|
|
["scr_console_native.c", "inspect"],
|
|
["scr_dyn_invoke.c", any("dynInvoke", "nativeFetch")],
|
|
["scr_dc.c", "dc"],
|
|
["scr_event_target.c", any("eventTarget", "nativeFetch")],
|
|
["scr_async_dyn.c", any("dynAsync", "dynInvoke", "dc", "fileHandle", "nativeFetch")],
|
|
// The performance timeline emits its buffer warning through scr_async_dyn.c.
|
|
["scr_perf.c", "dynAsync"],
|
|
// Blob and File box their reads as dyn promises through scr_async_dyn.c.
|
|
["scr_blob.c", "dynAsync"],
|
|
["scr_zlib.c", "zlib"],
|
|
["scr_events.c", "events"],
|
|
["scr_readline.c", "events"],
|
|
["scr_readline_tty.c", all("events", "regex")],
|
|
["scr_events_emitter.c", "emitter"],
|
|
["scr_dyn_handle.c", any("emitter", "netEffective")],
|
|
["scr_symbol.c", "symbol"],
|
|
["scr_bigint_assert.c", all("assert", "bigint")],
|
|
["scr_qs.c", "qs"],
|
|
// The legacy url unit lowercases and normalizes through the regex unit
|
|
// and warns through the dyn-async one.
|
|
["scr_url_legacy.c", all("regex", "qs", "dynAsync")],
|
|
["scr_util.c", "parseArgs"],
|
|
// Utility objects must only reference runtime families selected with them.
|
|
["scr_util_compare.c", all("parseArgs", "symbol")],
|
|
["scr_util_style.c", all("parseArgs", "inspect", "dynAsync")],
|
|
["scr_util_callable.c", all("parseArgs", "inspect", "dynAsync", "dynInvoke", "regex")],
|
|
["scr_stream.c", "stream"],
|
|
// The zlib stream classes reference both the zlib engine and the stream unit.
|
|
["scr_zlib_stream.c", all("zlib", "stream")],
|
|
// The Readable operators await through the dyn-async unit.
|
|
["scr_stream_ops.c", all("stream", "dynAsync")],
|
|
// fs.ReadStream / fs.WriteStream reference only the stream unit and base units.
|
|
["scr_fs_stream.c", "stream"],
|
|
// FileHandle streams reference both the stream unit and FileHandle.
|
|
["scr_fs_stream_fh.c", all("stream", "fileHandle")],
|
|
["scr_loop_kqueue.c", any("netEffective", "dgram")],
|
|
["scr_loop_epoll.c", any("netEffective", "dgram")],
|
|
["scr_loop_wsapoll.c", any("netEffective", "dgram")],
|
|
["scr_net.c", "netEffective"],
|
|
["scr_http.c", "httpEffective"],
|
|
["scr_http2.c", "http2"],
|
|
["scr_dgram.c", "dgram"],
|
|
["scr_watch.c", "watch"],
|
|
["scr_ffi_queue.c", "foreignFfi"],
|
|
["scr_test.c", "nodeTest"],
|
|
["scr_tls_ca.c", "tlsCaEffective"],
|
|
["scr_tls.c", "tlsEffective"],
|
|
["scr_cipher.c", "cipher"],
|
|
["scr_fetch.c", "nativeFetch"],
|
|
];
|
|
|
|
function variantsFor(source) {
|
|
const variants = [{ id: "default", when: {}, defines: [] }];
|
|
if (source === "scr_bytes.c") {
|
|
variants.push({
|
|
id: "text-decoder-legacy",
|
|
when: { textDecoderLegacy: true },
|
|
defines: ["SCR_TEXT_DECODER_LEGACY"],
|
|
});
|
|
}
|
|
return variants;
|
|
}
|
|
|
|
export function createRuntimePackMatrix({
|
|
target,
|
|
compileFlags,
|
|
systemLibraries,
|
|
extraRuntimeSources = [],
|
|
omitRuntimeSources = [],
|
|
omitOptionalSources = [],
|
|
omitArchives = [],
|
|
libraryOnly = false,
|
|
}) {
|
|
const vendorArchives = [
|
|
{ id: "quickjs", predicate: false },
|
|
{ id: "libregexp", predicate: "regex" },
|
|
{ id: "zlib", predicate: "zlibEffective" },
|
|
{ id: "mbedtls", predicate: any("tlsEffective", "cipher") },
|
|
];
|
|
const matrix = withLibraryRuntimeFlavors(
|
|
withWorkerRuntimeVariants({
|
|
schema: "scriptc.runtime-pack-matrix.v1",
|
|
target,
|
|
flavors: { release: { optimization: "-O2" }, dev: { optimization: "-O0" } },
|
|
executable_section_elimination: { compile_flags: compileFlags },
|
|
runtime_units: [
|
|
...BASE_RUNTIME_SOURCES.filter((source) => !omitRuntimeSources.includes(source)).map(
|
|
(source) => ({ source, predicate: true }),
|
|
),
|
|
...extraRuntimeSources.map((source) => ({ source, predicate: true })),
|
|
...OPTIONAL.filter(([source]) => !omitOptionalSources.includes(source)).map(
|
|
([source, predicate]) => ({ source, predicate }),
|
|
),
|
|
].map((unit) => ({ ...unit, variants: variantsFor(unit.source) })),
|
|
archives: vendorArchives.filter(({ id }) => !omitArchives.includes(id)),
|
|
system_libraries: systemLibraries,
|
|
}),
|
|
);
|
|
if (libraryOnly) {
|
|
matrix.flavors = Object.fromEntries(
|
|
Object.entries(matrix.flavors).filter(([name]) => name.startsWith("library-")),
|
|
);
|
|
matrix.archives = matrix.archives.filter(({ id }) => id === "libregexp" || id === "zlib");
|
|
}
|
|
return matrix;
|
|
}
|