The cache behind the compile-asm door: persistent emitted native code, over the JIT compiler it falls back to.
asm-cache-groupRun THUNK, a (fn (_)), with every compile-asm in it grouped under KEY, a string naming the set: the same key in a later process loads every entry the group kept from one file into the heap before THUNK runs, so each of its compiles hits without hashing its key or opening a file. Every entry is still matched by its whole key text, so a stale group costs misses, never a wrong function. Groups do not nest.
Returns: ANY — What THUNK answers
asm-cache-group-heldInside a group’s thunk, the key texts the group already held, oldest first – the order they were compiled in – and the extra the group carried, a string or nil.
Returns: ANY — (TEXTS . EXTRA), or nil outside a group
Examples:
(import x/tool/asm-cache asm-cache-group-held) (null? (asm-cache-group-held)) => #tasm-cache-group-extra!Inside a group’s thunk, set the string the group writes after its entries, which a later process reads back through asm-cache-group-held.
Returns: BOOL — #f outside a group
Examples:
(import x/tool/asm-cache asm-cache-group-extra!) (asm-cache-group-extra! "note") => #fasm-cache-last-textThe key text of the last compile-asm through the cache, which asm-cache-held-pour takes to load the same entry again; nil when that compile stood aside from the cache.
Returns: ANY — A string, or nil
asm-cache-held-pourThe held entry whose key text is TEXT, poured with FVARS: a load by key, with no expression printed or hashed. Nil when no entry is held for the text. The text is noted in the open group, as a compile’s is. FVARS are (NAME . VALUE) with every NAME a symbol, or every NAME the symbol’s text.
Returns: ANY — X-lang callable prim, or nil
Examples:
(import x/tool/asm-cache asm-cache-held-pour) (null? (asm-cache-held-pour "no such key" ())) => #tasm-cache-held-fvar-namesThe names, as text and in slot order, of the free variables the held entry whose key text is TEXT patches into its code: what a pour of it needs of the FVARS it is given, and the order asm-cache-entry-pour takes their values in. #f when no entry is held for the text.
Returns: ANY — A list of strings, or #f
Examples:
(import x/tool/asm-cache asm-cache-held-fvar-names) (asm-cache-held-fvar-names "no such key") => #fasm-cache-held-entryThe entry held for the key text TEXT, which asm-cache-entry-pour pours: found once, it is poured again with no text matched. Nil when no entry is held for the text. An image carries it with the held entries.
Returns: ANY — An entry, or nil
Examples:
(import x/tool/asm-cache asm-cache-held-entry) (null? (asm-cache-held-entry "no such key")) => #tasm-cache-entry-pourThe entry E from asm-cache-held-entry, poured as asm-cache-held-pour pours, its fvar slots given FVALS: their values, unnamed, in the slot order asm-cache-held-fvar-names lists. Nil on a miss, a list too short included. Nothing is noted in the open group, and a group whose thunk noted nothing and set no extra keeps its file as it is.
Returns: ANY — X-lang callable prim, or nil
Examples:
(import x/tool/asm-cache asm-cache-entry-pour) (null? (asm-cache-entry-pour () ())) => #tasm-fn-valuesasm-compile-cachedJIT compile an x-lang (fn …) expression to a native prim, through a persistent byte cache. This is the function behind compile-asm, the door in x/tool/compile, which loads this module on its first call and hands every call here. Accepts an optional fvar alist for free variable support, and a third argument declaring the calling mode: #f for an integer function called from x, #t for an analyse callback the tokenizer calls, or the symbol object for an object function called from x. A compile with fvars must declare it and refuses without it; one with neither fvars nor a declaration is an integer function. In analyser mode nothing evaluates the arguments and the result is not boxed, and arithmetic or an ordered comparison on a leading param refuses rather than answering. In object mode the arguments evaluate and stay the objects they evaluate to, the result is returned as one, and every param is an object param: (= p 0) is the nil test, (first p) reads through the trampoline, arithmetic on a param refuses, and a value tested for truth is false when it is nil or #f. The symbol operative declares an object function whose one param is its argument list as the call wrote it: (%eval x) evaluates one argument in the caller’s environment, and a self-call in tail position loops. (run TYPE …) declares a routine for a slot of the base’s slot vector – see (Base slots) and (Base slot!): its arguments arrive as a run of words with no self in front, one TYPE a parameter, each object, integer or string; a word is read as it is, an object-typed param refuses arithmetic, the result is returned as it is, and only a self-call in tail position compiles. An fvar holding a prim may be called by name; (%call HEAD arg …) calls a prim the code computes, and refuses at run time if the head is not one. The compiled function works with map, fold, closures, etc. The cache keeps two files per entry, in /tmp or in the directory the X_ASM_CACHE_DIR environment variable names, and holds each entry in the heap as well, where a state image carries it.
Returns: CALLABLE — X-lang callable prim
asm-compile-keptasm-compile-cached for a caller that compiles the same EXPR over the same FVARS more than once in a process or across a state image, as an entry of x/tool/compiled does each time it is compiled again. The first compile keeps the entry held for it and its fvars’ values in the entry’s slot order in KEPT; a later one pours from that, with no key printed and no name matched. KEPT answers for nothing else: a different EXPR or FVARS takes a cell of its own.
Parameters:
LIST — A cell the caller owns, (pair () ()) before the first compile: what this compile found is kept in itLIST — The (fn (params…) body), as compile-asm takes itLIST — The free variables, ((NAME . VALUE) …)ANY — The calling world, as compile-asm’s third argument names itReturns: CALLABLE — The compiled function