Memory Optimize
-optimize-memory: object literals the escape analysis proves never outlive their block are stack-allocated instead of heap-allocated. Semantics are identical with or without the flag — this example compiles and behaves the same either way; compile it with `klainmain -optimize-memory` to get the stack-allocation lowering.
interface Point { x: number; y: number }
function dist2(ax: number, ay: number): number {
// Non-escaping: only field reads — stack-allocated under the flag.
const p: Point = { x: ax, y: ay }
return p.x * p.x + p.y * p.y
}
const kept: Point[] = []
function stash(i: number): void {
// Escaping (stored into an outer array) — always heap-allocated.
const q: Point = { x: i, y: i }
kept.push(q)
}
let total = 0
for (let i = 0; i < 100000; i++) {
// Non-escaping in a loop: the single stack slot is reused (and re-zeroed)
// every iteration.
const r: Point = { x: i, y: i + 1 }
total += r.x + r.y
if (i % 25000 === 0) { stash(i) }
}
console.log(total + dist2(3, 4))
console.log(kept.length)
function tally(base: number): number {
// Non-escaping closure: its {fn,env} header and env stack-allocate under
// the flag; the shared cell holding `acc` stays heap.
let acc = 0
const add = (x: number): void => { acc += x + base }
add(1)
add(2)
return acc
}
console.log(tally(10))
class Vec2 {
x: number
y: number
constructor(x: number, y: number) { this.x = x; this.y = y }
dot(ox: number, oy: number): number { return this.x * ox + this.y * oy }
}
function measure(i: number): number {
// Tuple + this-clean class instance: both stack-allocate under the flag.
const pair: [number, number] = [i, i * 2]
const v = new Vec2(pair[0], pair[1])
return v.dot(1, 1)
}
console.log(measure(7))
function divmod(a: number, b: number): [number, number] {
// Stage 3: a small tuple (≤2 scalar fields) returned from a top-level
// function goes back BY VALUE — a register-passable struct aggregate, no
// allocation for the literal at all. The Go-style destructuring consumer
// below is allocation-free too (extractvalue, no memory traffic).
return [Math.floor(a / b), a % b]
}
const [quot, rem] = divmod(17, 5)
console.log(quot, rem)View source on GitHubexamples/memory/memory_optimize.ts