VMConfig
Defined in: packages/engine/src/constants/Configuration.ts:148
Virtual Machine configuration. Controls the internal bytecode VM that executes compiled expressions.
Properties
Section titled “Properties”maxAllocatedElements
Section titled “maxAllocatedElements”readonly maxAllocatedElements: number;Defined in: packages/engine/src/constants/Configuration.ts:186
Maximum elements (collection Values, matrix cells) one evaluation may materialize in total.
maxCollectionSize above bounds a single collection. This bounds the sum
of everything an expression asks for, which is a different question and
the one that actually protects the host: two collections that are
individually legal are legal together, and an operation whose result is
the PRODUCT of two legal operands is bounded by neither of them. A matrix
multiply is exactly that shape, so three lines within every other limit
(:a = map(1*x, 0:20000), :b = transpose(a), b * a) asked for four
hundred million cells and aborted the process.
Counted in elements rather than bytes, because a count is what a call site has before it allocates. An element is 8 bytes as a numeric matrix cell and closer to a hundred as a full Value, so the default is worth roughly 16 MB of matrix or 200 MB of expanded collection: far past any document and far short of what an editor cannot survive.
maxCollectionSize
Section titled “maxCollectionSize”readonly maxCollectionSize: number;Defined in: packages/engine/src/constants/Configuration.ts:166
Maximum elements a collection may be expanded to before map/reduce/
sum/prod will iterate it.
A Range is stored as its two bounds and costs nothing until something
materializes it, at which point it becomes one Value per element. Twenty
characters (sum(x, 1:100000000)) therefore asked for a hundred million
of them, and neither maxInstructions nor maxStackDepth could see it:
the expansion happens inside a single opcode, so the instruction counter
is never consulted while it runs, and the elements never reach the value
stack. V8 aborted the whole process with “Reached heap limit”, which a
host embedding the engine cannot catch.
maxFunctionCalls
Section titled “maxFunctionCalls”readonly maxFunctionCalls: number;Defined in: packages/engine/src/constants/Configuration.ts:206
Maximum user-defined-function calls one evaluation may make in TOTAL, however deeply or widely they nest.
maxFunctionRecursionDepth bounds how DEEP calls nest and cannot see
how MANY there are, and those are different numbers. Twenty-two lines of
f(n)(v) = f(n-1)(v) + f(n-1)(v) reach a depth of only 22 against a
limit of 50, and make 2,097,152 calls doing it: a fatal heap abort in
under a second. maxInstructions cannot bound it either, because
executeBytecode() re-enters itself per call and each reentrant call
gets its OWN instruction count, so recursion refreshes its allowance on
the way in. This is the tally that does not refresh; see
vm/AllocationBudget.ts, which holds it for the same reason it holds
the element tally.
Counted in calls rather than in the instructions they run, because the call is the thing that multiplies: every call allocates a frame, its arguments and its result whatever its body says.
maxInstructions
Section titled “maxInstructions”readonly maxInstructions: number;Defined in: packages/engine/src/constants/Configuration.ts:152
Maximum opcodes executed per expression, halts runaway infinite loops
maxStackDepth
Section titled “maxStackDepth”readonly maxStackDepth: number;Defined in: packages/engine/src/constants/Configuration.ts:150
Maximum stack depth (value slots) for VM execution, prevents stack overflow in recursive/pratt-parser generated bytecode