From eceb1692567b2bb92c694fa478697851aaffacd9 Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Mon, 3 Feb 2020 15:55:51 -0800 Subject: [PATCH 1/7] turn off stack check for small functions without non-tail-calls and add reserve --- compiler/stz-compiler-main.stanza | 15 +- compiler/stz-reg-alloc.stanza | 603 ++++++++++++++++-------------- 2 files changed, 330 insertions(+), 288 deletions(-) diff --git a/compiler/stz-compiler-main.stanza b/compiler/stz-compiler-main.stanza index 773a56178..6cc8d6e34 100644 --- a/compiler/stz-compiler-main.stanza +++ b/compiler/stz-compiler-main.stanza @@ -179,8 +179,17 @@ public defn compile (proj-manager:ProjManager, switch(situation) : `optimized-asm : val packages = Vector() + val opt-timer = MillisecondTimer("Opt") + start(opt-timer) add(packages, combine-and-lower(/packages(result) as Tuple)) + stop(opt-timer) + println(opt-timer) + val backend-timer = MillisecondTimer("Backend") + start(backend-timer) compile-vmpackages({false}, to-tuple(packages), bindings(result), output as String, false) + stop(backend-timer) + println(backend-timer) + println("NUM-STRIPPED %_ NUM-ASSEMBLED %_: %_%%" % [num-stripped, num-assembled, 100.0 * to-double(num-stripped) / to-double(num-assembled)]) `optimized-pkgs : ;Already done false @@ -286,6 +295,10 @@ public defn compile (proj-manager:ProjManager, for f in funcs(vmpackage(npkg)) do : emit(emitter, LinkLabel(id(f))) allocate-registers(func(f), emitter, backend, stubs, false) + val sizes = get-smap-sizes() + val keys = qsort(keys(sizes)) + for key in keys do : + println("/* %_ => %_ */" % [key, sizes[key]]) defn emit-all-system-stubs (stitcher:Stitcher, stubs:AsmStubs) : val emitter = file-emitter() @@ -341,4 +354,4 @@ public defstruct CompilationResult : compiled-packages: Tuple binding-packages: Tuple package-stamps: Tuple - output-pkgs: Tuple \ No newline at end of file + output-pkgs: Tuple diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 96df04b2a..9357d443c 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -204,6 +204,10 @@ defpackage stz/reg-alloc : ;===================== Driver =============================== ;============================================================ +val SMALL-SMAP-SIZE = 16 ;; SIZE OF SMAP WHICH CAN BE CALLED WITHOUT CHECKING STACK-SIZE + +val smap-sizes = IntTable(0) + public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Backend, stubs:AsmStubs, print?:True|False) -> False : take-ids(ins) @@ -252,7 +256,10 @@ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Bac ;if print? : ; println("==== Stack Map ====") ; println(smap) + smap-sizes[size(smap)] = smap-sizes[size(smap)] + 1 + + collapse-blocks() if print? : println("==== Collapse Blocks ====") @@ -261,6 +268,8 @@ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Bac assemble(emitter, smap, stubs) clear-working-set() +public defn get-smap-sizes () : smap-sizes + ;============================================================ ;========================== IR ============================== ;============================================================ @@ -2365,6 +2374,9 @@ defn load-mem-arg-offset (op:LoadCArgOp, backend:Backend) : ;====================== Assemble ============================ ;============================================================ +public var num-assembled:Int = 0 +public var num-stripped:Int = 0 + defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : ;============================ ;==== Assembly Utilities ==== @@ -2391,296 +2403,313 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : ;============== ;==== Body ==== ;============== - for e in ins(BLOCKS[0]) do : - ;println("//Assembling: %_" % [e]) - match(e) : - (e:Set) : - match(y(e)) : - (v:Val) : - match(value(v)) : - (v:ConstId) : load-const(id(v)) - (v) : set-value(y(e)) - (v) : set-value(v) - where : - defn load-const (id:Int) : - val x = V(x(e)) - E $ LoadL(x, asm-LinkId(id)) - defn set-value (v:Imm) : - val t = T(x(e)) - val x = V(x(e)) - val y = I(v) - E(asm-SetIns(t, x, y)) when x != y - (e:Return) : - match(ctxt(e)) : - (c:StanzaContext) : - E $ asm-Return() - (c:CContext) : - ;Save current context - E $ StoreL(M(stack-pointer(stubs)), RSP) - - ;Restore C context - E $ SetL(RSP, R(c-rsp-arg(backend(stubs)))) - for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : - val o = -8 - (8 * i) - E $ LoadL(R(reg), RSP, o) - E $ asm-Return() - (e:Args) : - match(ctxt(e)) : - (ctxt:StanzaContext) : - ;Everything is set up already - false - (ctxt:CContext) : - false - (e:Call) : - match(type(e)) : - (t:ExtendStack) : - val return-lbl = unique-id(stubs) - E $ SetL(R0, LM(return-lbl)) - E $ SetL(R1, INT(size(stackmap) + 8)) - E $ asm-Goto(M(extend-stack(stubs))) - E $ asm-Label(return-lbl) - (t:CollectGarbage) : - val return-lbl = unique-id(stubs) - E $ SetL(R0, LM(return-lbl)) - E $ asm-Goto(M(collect-garbage(stubs))) - E $ asm-Label(return-lbl) - (t:StanzaCall) : - val frame-size = INT(size(stackmap) + 8) - E $ AddL(RSP, RSP, frame-size) - E $ asm-Call(I(f(e))) - match(info(t):FileInfo) : - E $ asm-Label(unique-id(stubs), info(t)) - E $ SubL(RSP, RSP, frame-size) - (t:StanzaTCall) : - E $ asm-Goto(I(f(e))) - (t:CCall) : - ;Push frame: - E $ AddL(RSP, RSP, INT(size(stackmap))) - - ;Save RSP - E $ StoreL(M(stack-pointer(stubs)), RSP) - - ;Restore the C context: - E $ LoadL(RSP, M(saved-c-rsp(stubs))) - - ;Call C function with right convention - val num-float-args = for y in ys(e) count : reg?(y as Var) is FReg - E $ SubL(RSP, RSP, INT(frame-size(num-mem-args(t), backend(stubs)))) - E $ SetL(R0, INT(num-float-args)) - E $ asm-Call(I(f(e))) - - ;Load RSP - E $ LoadL(RSP, M(stack-pointer(stubs))) - - ;Pop frame: - E $ SubL(RSP, RSP, INT(size(stackmap))) - (t:YieldCall) : - val lbl = unique-id(stubs) - val TMP = to-asm-loc(scratch-regs(t)[0]) - val TMP2 = to-asm-loc(scratch-regs(t)[1]) - val F = I(f(e)) - - ;Save current stack progress - val size-offset = -1 + 8 - val frames-offset = -1 + 8 + 8 - val sp-offset = -1 + 8 + 8 + 8 - val pc-offset = -1 + 8 + 8 + 8 + 8 - E $ LoadL(TMP, M(current-stack(stubs))) - E $ SetL(TMP2, LM(lbl)) - E $ StoreL(TMP, TMP2, pc-offset) - E $ StoreL(TMP, RSP, sp-offset) - - ;Load given stack - E $ StoreL(M(current-stack(stubs)), F) - if enter?(t) : E $ LoadL(RSP, F, frames-offset) - else : E $ LoadL(RSP, F, sp-offset) - E $ LoadL(TMP, F, frames-offset) - E $ LoadL(TMP2, F, size-offset) - E $ AddL(TMP, TMP, TMP2) - E $ StoreL(M(stack-limit(stubs)), TMP) - - E $ LoadL(TMP, F, pc-offset) - E $ asm-Goto(TMP) - E $ asm-Label(lbl, info(t)) - (e:Op) : ;[2] - match(op(e)) : - (op:SaveCContextOp) : - ;Save C preserved registers - for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : - val o = -8 - (8 * i) - E $ StoreL(RSP, R(reg), o) - ;Move RSP to special register for holding CRSP - E $ SetL(R(c-rsp-arg(backend(stubs))), RSP) - ;Load Stanza RSP - E $ LoadL(RSP, M(stack-pointer(stubs))) - (op:RecordLiveOp) : - val indices = qsort $ - for v in live-vars(op) seq? : - if type(v) is VMRef : - val o = offset(stackmap, n(v)) - 16 - fatal("Wrong alignment for ref on stack.") when o % 8 != 0 - One(o / 8) - else : None() - E $ StoreL(RSP, asm-StackMap(size(stackmap), indices), 8) - (op:AllocOp) : - val x = V(xs(e)[0]) - val size = I(ys(e)[0]) + + val start-body-label = + match(ins(BLOCKS[0])[1]) : ;; LABEL IS 1st INST THEN BREAK / HASSTACKOP IS 2nd + (e:Break) : n(e) when op(e) is HasStackOp else -1 + (e) : -1 + var stripping?:True|False = if size(stackmap) <= 16 and start-body-label >= 0 : + for e in ins(BLOCKS[0]) any? : match(e:Call) : type(e) is-not StanzaTCall + + ;; println("/* STRIPPING? %_: SS %_ */" % [stripping?, size(stackmap)]) + num-assembled = num-assembled + 1 + if stripping? : num-stripped = num-stripped + 1 + + for (e in ins(BLOCKS[0]), i in 0 to false) do : + if stripping? and i > 0 : + ;; println("/* --- Stripping: %_ */" % [e]) + match(e:Label) : + if n(e) == start-body-label: stripping? = false + else : + ;; println("/* --- Assembling: %_ */" % [e]) + match(e) : + (e:Set) : + match(y(e)) : + (v:Val) : + match(value(v)) : + (v:ConstId) : load-const(id(v)) + (v) : set-value(y(e)) + (v) : set-value(v) + where : + defn load-const (id:Int) : + val x = V(x(e)) + E $ LoadL(x, asm-LinkId(id)) + defn set-value (v:Imm) : + val t = T(x(e)) + val x = V(x(e)) + val y = I(v) + E(asm-SetIns(t, x, y)) when x != y + (e:Return) : + match(ctxt(e)) : + (c:StanzaContext) : + E $ asm-Return() + (c:CContext) : + ;Save current context + E $ StoreL(M(stack-pointer(stubs)), RSP) + + ;Restore C context + E $ SetL(RSP, R(c-rsp-arg(backend(stubs)))) + for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : + val o = -8 - (8 * i) + E $ LoadL(R(reg), RSP, o) + E $ asm-Return() + (e:Args) : + match(ctxt(e)) : + (ctxt:StanzaContext) : + ;Everything is set up already + false + (ctxt:CContext) : + false + (e:Call) : + match(type(e)) : + (t:ExtendStack) : + val return-lbl = unique-id(stubs) + E $ SetL(R0, LM(return-lbl)) + E $ SetL(R1, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) + E $ asm-Goto(M(extend-stack(stubs))) + E $ asm-Label(return-lbl) + (t:CollectGarbage) : + val return-lbl = unique-id(stubs) + E $ SetL(R0, LM(return-lbl)) + E $ asm-Goto(M(collect-garbage(stubs))) + E $ asm-Label(return-lbl) + (t:StanzaCall) : + val frame-size = INT(size(stackmap) + 8) + E $ AddL(RSP, RSP, frame-size) + E $ asm-Call(I(f(e))) + match(info(t):FileInfo) : + E $ asm-Label(unique-id(stubs), info(t)) + E $ SubL(RSP, RSP, frame-size) + (t:StanzaTCall) : + E $ asm-Goto(I(f(e))) + (t:CCall) : + ;Push frame: + E $ AddL(RSP, RSP, INT(size(stackmap))) + + ;Save RSP + E $ StoreL(M(stack-pointer(stubs)), RSP) + + ;Restore the C context: + E $ LoadL(RSP, M(saved-c-rsp(stubs))) + + ;Call C function with right convention + val num-float-args = for y in ys(e) count : reg?(y as Var) is FReg + E $ SubL(RSP, RSP, INT(frame-size(num-mem-args(t), backend(stubs)))) + E $ SetL(R0, INT(num-float-args)) + E $ asm-Call(I(f(e))) + + ;Load RSP + E $ LoadL(RSP, M(stack-pointer(stubs))) + + ;Pop frame: + E $ SubL(RSP, RSP, INT(size(stackmap))) + (t:YieldCall) : + val lbl = unique-id(stubs) + val TMP = to-asm-loc(scratch-regs(t)[0]) + val TMP2 = to-asm-loc(scratch-regs(t)[1]) + val F = I(f(e)) + + ;Save current stack progress + val size-offset = -1 + 8 + val frames-offset = -1 + 8 + 8 + val sp-offset = -1 + 8 + 8 + 8 + val pc-offset = -1 + 8 + 8 + 8 + 8 + E $ LoadL(TMP, M(current-stack(stubs))) + E $ SetL(TMP2, LM(lbl)) + E $ StoreL(TMP, TMP2, pc-offset) + E $ StoreL(TMP, RSP, sp-offset) + + ;Load given stack + E $ StoreL(M(current-stack(stubs)), F) + if enter?(t) : E $ LoadL(RSP, F, frames-offset) + else : E $ LoadL(RSP, F, sp-offset) + E $ LoadL(TMP, F, frames-offset) + E $ LoadL(TMP2, F, size-offset) + E $ AddL(TMP, TMP, TMP2) + E $ StoreL(M(stack-limit(stubs)), TMP) + + E $ LoadL(TMP, F, pc-offset) + E $ asm-Goto(TMP) + E $ asm-Label(lbl, info(t)) + (e:Op) : ;[2] + match(op(e)) : + (op:SaveCContextOp) : + ;Save C preserved registers + for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : + val o = -8 - (8 * i) + E $ StoreL(RSP, R(reg), o) + ;Move RSP to special register for holding CRSP + E $ SetL(R(c-rsp-arg(backend(stubs))), RSP) + ;Load Stanza RSP + E $ LoadL(RSP, M(stack-pointer(stubs))) + (op:RecordLiveOp) : + val indices = qsort $ + for v in live-vars(op) seq? : + if type(v) is VMRef : + val o = offset(stackmap, n(v)) - 16 + fatal("Wrong alignment for ref on stack.") when o % 8 != 0 + One(o / 8) + else : None() + E $ StoreL(RSP, asm-StackMap(size(stackmap), indices), 8) + (op:AllocOp) : + val x = V(xs(e)[0]) + val size = I(ys(e)[0]) + val TMP = R0 + val TMP2 = R1 + E $ LoadL(TMP, M(heap-top(stubs))) + E $ SetL(TMP2, size) + E $ AddL(x, TMP, INT(1)) + E $ AddL(TMP, TMP, TMP2) + E $ StoreL(M(heap-top(stubs)), TMP) + (op:NoOp) : + false + (op:ConvOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-ConvertIns(T(x), V(x), T(y), I(y)) + (op:InterpretOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-InterpretIns(T(x), V(x), T(y), I(y)) + (op:LoadOp) : + val [x, y, o] = [head(xs(e)), head(ys(e)), offset(op)] + E $ asm-Load(T(x), V(x), I(y), o) + (op:StoreOp) : + val [x, y, o] = [ys(e)[0], ys(e)[1], offset(op)] + E $ asm-Store(T(y), I(x), I(y), o) + (op:LoadArgOp) : + val x = xs(e)[0] + E $ asm-Load(T(x), V(x), M(registers(stubs)), 8 * index(op)) + (op:StoreArgOp) : + val y = ys(e)[0] + E $ asm-Store(T(y), M(registers(stubs)), I(y), 8 * index(op)) + (op:StoreCArgOp) : + val crsp = ys(e)[0] + val y = ys(e)[1] + E $ asm-Store(T(y), I(crsp), I(y), store-mem-arg-offset(op,backend(stubs))) + (op:LoadCArgOp) : + val crsp = ys(e)[0] + val x = xs(e)[0] + E $ asm-Load(T(x), V(x), I(crsp), load-mem-arg-offset(op,backend(stubs))) + (op:CRSPOp) : + val x = xs(e)[0] + E $ LoadL(V(x), M(saved-c-rsp(stubs))) + (op:StoreCRSPOp) : + val y = ys(e)[0] + E $ StoreL(M(saved-c-rsp(stubs)), I(y)) + (op:VMOp&Binary) : + val [x, y, z] = [head(xs(e)), ys(e)[0], ys(e)[1]] + E $ asm-BinOp(T(y), V(x), to-asm-op(op), I(y), I(z)) + (op:VMOp&Unary) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) + (op:DivModOp) : + val [x1, x2, y, z] = [xs(e)[0], xs(e)[1], ys(e)[0], ys(e)[1]] + E $ asm-DualOp(T(x1), V(x1), V(x2), to-asm-op(op), I(y), I(z)) + (op:InstanceofOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) + (op:FlushVMOp) : + val x = V(head(xs(e))) + val stack-pointer-offset = -1 + 8 + 16 + E $ LoadL(x, M(current-stack(stubs))) + E $ StoreL(x, RSP, stack-pointer-offset) + E $ SetL(x, M(vmstate(stubs))) + (op) : + fatal("Not yet implemented") + + (e:Save) : + val x = x(e) + val offset = offset(stackmap, n(x)) + E $ asm-Store(T(x), RSP, I(x), offset) + (e:Load) : + val x = x(e) + val offset = offset(stackmap, n(x)) + E $ asm-Load(T(x), V(x), RSP, offset) + (e:Xchg) : + val [x, y] = [x(e), y(e)] + match(swap(e)) : + (s:FReg) : + E $ SetD(F(n(s)), I(x)) + E $ SetD(V(x), I(y)) + E $ SetD(V(y), F(n(s))) + (s:False) : + E $ asm-XchgIns(V(x), V(y)) + (e:ShuffleReg) : + if xs(e) != ys(e) : + shuffle(num-regs(backend(stubs)), xs(e), ys(e), + fn (src:Int, dst:Int) : + E $ asm-SetIns(LT, R(dst), R(src)) + fn (src:Int, dst:Int) : + E $ asm-XchgIns(R(dst), R(src))) + (e:ShuffleFReg) : + if xs(e) != ys(e) : + shuffle(num-fregs(backend(stubs)), xs(e), ys(e), + fn (src:Int, dst:Int) : + E $ asm-SetIns(DT, F(dst), F(src)) + fn (n:Int) : + E $ asm-Store(DT, M(swap-lbl(stubs)), F(n), 0) + fn (n:Int) : + E $ asm-Load(DT, F(n), M(swap-lbl(stubs)), 0)) + (e:Label) : + val l = label-table[n(e)] + E $ asm-Label(asm-n(l)) + (e:Goto) : + E $ asm-Goto(label-table[n(e)]) + (e:Break) : ;[1] + defn cmp-stack-limit (le-op:asm-Op) : + val TMP = R0 + val TMP2 = R1 + E $ AddL(TMP, RSP, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) + E $ LoadL(TMP2, M(stack-limit(stubs))) + E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) + defn cmp-heap-limit (le-op:asm-Op) : val TMP = R0 val TMP2 = R1 + val size = I(xs(e)[0]) E $ LoadL(TMP, M(heap-top(stubs))) - E $ SetL(TMP2, size) - E $ AddL(x, TMP, INT(1)) - E $ AddL(TMP, TMP, TMP2) - E $ StoreL(M(heap-top(stubs)), TMP) - (op:NoOp) : - false - (op:ConvOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-ConvertIns(T(x), V(x), T(y), I(y)) - (op:InterpretOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-InterpretIns(T(x), V(x), T(y), I(y)) - (op:LoadOp) : - val [x, y, o] = [head(xs(e)), head(ys(e)), offset(op)] - E $ asm-Load(T(x), V(x), I(y), o) - (op:StoreOp) : - val [x, y, o] = [ys(e)[0], ys(e)[1], offset(op)] - E $ asm-Store(T(y), I(x), I(y), o) - (op:LoadArgOp) : - val x = xs(e)[0] - E $ asm-Load(T(x), V(x), M(registers(stubs)), 8 * index(op)) - (op:StoreArgOp) : - val y = ys(e)[0] - E $ asm-Store(T(y), M(registers(stubs)), I(y), 8 * index(op)) - (op:StoreCArgOp) : - val crsp = ys(e)[0] - val y = ys(e)[1] - E $ asm-Store(T(y), I(crsp), I(y), store-mem-arg-offset(op,backend(stubs))) - (op:LoadCArgOp) : - val crsp = ys(e)[0] - val x = xs(e)[0] - E $ asm-Load(T(x), V(x), I(crsp), load-mem-arg-offset(op,backend(stubs))) - (op:CRSPOp) : - val x = xs(e)[0] - E $ LoadL(V(x), M(saved-c-rsp(stubs))) - (op:StoreCRSPOp) : - val y = ys(e)[0] - E $ StoreL(M(saved-c-rsp(stubs)), I(y)) - (op:VMOp&Binary) : - val [x, y, z] = [head(xs(e)), ys(e)[0], ys(e)[1]] - E $ asm-BinOp(T(y), V(x), to-asm-op(op), I(y), I(z)) - (op:VMOp&Unary) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) - (op:DivModOp) : - val [x1, x2, y, z] = [xs(e)[0], xs(e)[1], ys(e)[0], ys(e)[1]] - E $ asm-DualOp(T(x1), V(x1), V(x2), to-asm-op(op), I(y), I(z)) - (op:InstanceofOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) - (op:FlushVMOp) : - val x = V(head(xs(e))) - val stack-pointer-offset = -1 + 8 + 16 - E $ LoadL(x, M(current-stack(stubs))) - E $ StoreL(x, RSP, stack-pointer-offset) - E $ SetL(x, M(vmstate(stubs))) - (op) : - fatal("Not yet implemented") - - (e:Save) : - val x = x(e) - val offset = offset(stackmap, n(x)) - E $ asm-Store(T(x), RSP, I(x), offset) - (e:Load) : - val x = x(e) - val offset = offset(stackmap, n(x)) - E $ asm-Load(T(x), V(x), RSP, offset) - (e:Xchg) : - val [x, y] = [x(e), y(e)] - match(swap(e)) : - (s:FReg) : - E $ SetD(F(n(s)), I(x)) - E $ SetD(V(x), I(y)) - E $ SetD(V(y), F(n(s))) - (s:False) : - E $ asm-XchgIns(V(x), V(y)) - (e:ShuffleReg) : - if xs(e) != ys(e) : - shuffle(num-regs(backend(stubs)), xs(e), ys(e), - fn (src:Int, dst:Int) : - E $ asm-SetIns(LT, R(dst), R(src)) - fn (src:Int, dst:Int) : - E $ asm-XchgIns(R(dst), R(src))) - (e:ShuffleFReg) : - if xs(e) != ys(e) : - shuffle(num-fregs(backend(stubs)), xs(e), ys(e), - fn (src:Int, dst:Int) : - E $ asm-SetIns(DT, F(dst), F(src)) - fn (n:Int) : - E $ asm-Store(DT, M(swap-lbl(stubs)), F(n), 0) - fn (n:Int) : - E $ asm-Load(DT, F(n), M(swap-lbl(stubs)), 0)) - (e:Label) : - val l = label-table[n(e)] - E $ asm-Label(asm-n(l)) - (e:Goto) : - E $ asm-Goto(label-table[n(e)]) - (e:Break) : ;[1] - defn cmp-stack-limit (le-op:asm-Op) : - val TMP = R0 - val TMP2 = R1 - E $ AddL(TMP, RSP, INT(size(stackmap) + 8)) - E $ LoadL(TMP2, M(stack-limit(stubs))) - E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) - defn cmp-heap-limit (le-op:asm-Op) : - val TMP = R0 - val TMP2 = R1 - val size = I(xs(e)[0]) - E $ LoadL(TMP, M(heap-top(stubs))) - E $ AddL(TMP, TMP, size) - E $ LoadL(TMP2, M(heap-limit(stubs))) - E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) - defn cmp-arity (arg:Int, value:Int, eq-op:asm-Op) : - val arg-reg = R(call-regs(backend(stubs))[arg]) - E $ BreakL(label-table[n(e)], eq-op, arg-reg, INT(value)) + E $ AddL(TMP, TMP, size) + E $ LoadL(TMP2, M(heap-limit(stubs))) + E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) + defn cmp-arity (arg:Int, value:Int, eq-op:asm-Op) : + val arg-reg = R(call-regs(backend(stubs))[arg]) + E $ BreakL(label-table[n(e)], eq-op, arg-reg, INT(value)) - match(op(e)) : - (op:HasStackOp) : - cmp-stack-limit(asm-UleOp()) - (op:HasHeapOp) : - cmp-heap-limit(asm-UleOp()) - (op:ArgEqOp) : - cmp-arity(arg(op), value(op), asm-EqOp()) - (fop:FlipOp) : - match(op(fop)) : - (op:HasStackOp) : - cmp-stack-limit(asm-flip(asm-UleOp())) - (op:HasHeapOp) : - cmp-heap-limit(asm-flip(asm-UleOp())) - (op:ArgEqOp) : - cmp-arity(arg(op), value(op), asm-flip(asm-EqOp())) - (op) : - val [x, y] = [xs(e)[0], xs(e)[1]] - E $ asm-Break(T(x), label-table[n(e)], to-asm-op(op), I(x), I(y)) - (e:Match) : - if dispatch?(e) : - val no-branch = label-table[ns(e)[0]] - val amb-branch = label-table[ns(e)[1]] - val branch-ns = tailn(ns(e), 2) - val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) - val xs = map(I, xs(e)) - E $ asm-Dispatch(xs, bs, no-branch, amb-branch) - else : - val no-branch = label-table[head(ns(e))] - val branch-ns = tail(ns(e)) - val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) - val xs = map(I, xs(e)) - E $ asm-Match(xs, bs, no-branch) - (e:MethodDispatch) : - val no-branch = label-table[default(e)] - val amb-branch = label-table[amb(e)] - E $ asm-MethodDispatch(multi(e), num-header-args(e), no-branch, amb-branch) - (e) : fatal("Not yet implemented: %_" % [e]) + match(op(e)) : + (op:HasStackOp) : + cmp-stack-limit(asm-UleOp()) + (op:HasHeapOp) : + cmp-heap-limit(asm-UleOp()) + (op:ArgEqOp) : + cmp-arity(arg(op), value(op), asm-EqOp()) + (fop:FlipOp) : + match(op(fop)) : + (op:HasStackOp) : + cmp-stack-limit(asm-flip(asm-UleOp())) + (op:HasHeapOp) : + cmp-heap-limit(asm-flip(asm-UleOp())) + (op:ArgEqOp) : + cmp-arity(arg(op), value(op), asm-flip(asm-EqOp())) + (op) : + val [x, y] = [xs(e)[0], xs(e)[1]] + E $ asm-Break(T(x), label-table[n(e)], to-asm-op(op), I(x), I(y)) + (e:Match) : + if dispatch?(e) : + val no-branch = label-table[ns(e)[0]] + val amb-branch = label-table[ns(e)[1]] + val branch-ns = tailn(ns(e), 2) + val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) + val xs = map(I, xs(e)) + E $ asm-Dispatch(xs, bs, no-branch, amb-branch) + else : + val no-branch = label-table[head(ns(e))] + val branch-ns = tail(ns(e)) + val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) + val xs = map(I, xs(e)) + E $ asm-Match(xs, bs, no-branch) + (e:MethodDispatch) : + val no-branch = label-table[default(e)] + val amb-branch = label-table[amb(e)] + E $ asm-MethodDispatch(multi(e), num-header-args(e), no-branch, amb-branch) + (e) : fatal("Not yet implemented: %_" % [e]) defn asm-type (x:Imm) : to-asm-type(type(x)) @@ -2757,4 +2786,4 @@ defn to-asm-op (op:VMOp) -> asm-Op : ;============================================================ defn keys (xs:Vector>) : to-list(seq(key,xs)) -defn values (xs:Vector>) : to-list(seq(value,xs)) \ No newline at end of file +defn values (xs:Vector>) : to-list(seq(value,xs)) From 75d04668c2cfc1d8e8272f3036fba994bf6c7454 Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Tue, 4 Feb 2020 17:49:59 -0800 Subject: [PATCH 2/7] cleanup code ready for pull request --- compiler/stz-compiler-main.stanza | 4 - compiler/stz-reg-alloc.stanza | 607 +++++++++++++++--------------- 2 files changed, 298 insertions(+), 313 deletions(-) diff --git a/compiler/stz-compiler-main.stanza b/compiler/stz-compiler-main.stanza index 6cc8d6e34..9a002134c 100644 --- a/compiler/stz-compiler-main.stanza +++ b/compiler/stz-compiler-main.stanza @@ -295,10 +295,6 @@ public defn compile (proj-manager:ProjManager, for f in funcs(vmpackage(npkg)) do : emit(emitter, LinkLabel(id(f))) allocate-registers(func(f), emitter, backend, stubs, false) - val sizes = get-smap-sizes() - val keys = qsort(keys(sizes)) - for key in keys do : - println("/* %_ => %_ */" % [key, sizes[key]]) defn emit-all-system-stubs (stitcher:Stitcher, stubs:AsmStubs) : val emitter = file-emitter() diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 9357d443c..6489a6a4d 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -206,8 +206,6 @@ defpackage stz/reg-alloc : val SMALL-SMAP-SIZE = 16 ;; SIZE OF SMAP WHICH CAN BE CALLED WITHOUT CHECKING STACK-SIZE -val smap-sizes = IntTable(0) - public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Backend, stubs:AsmStubs, print?:True|False) -> False : take-ids(ins) @@ -256,9 +254,6 @@ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Bac ;if print? : ; println("==== Stack Map ====") ; println(smap) - smap-sizes[size(smap)] = smap-sizes[size(smap)] + 1 - - collapse-blocks() if print? : @@ -268,8 +263,6 @@ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Bac assemble(emitter, smap, stubs) clear-working-set() -public defn get-smap-sizes () : smap-sizes - ;============================================================ ;========================== IR ============================== ;============================================================ @@ -2374,9 +2367,6 @@ defn load-mem-arg-offset (op:LoadCArgOp, backend:Backend) : ;====================== Assemble ============================ ;============================================================ -public var num-assembled:Int = 0 -public var num-stripped:Int = 0 - defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : ;============================ ;==== Assembly Utilities ==== @@ -2404,312 +2394,311 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : ;==== Body ==== ;============== + defn emit (e:EIns) : + match(e) : + (e:Set) : + match(y(e)) : + (v:Val) : + match(value(v)) : + (v:ConstId) : load-const(id(v)) + (v) : set-value(y(e)) + (v) : set-value(v) + where : + defn load-const (id:Int) : + val x = V(x(e)) + E $ LoadL(x, asm-LinkId(id)) + defn set-value (v:Imm) : + val t = T(x(e)) + val x = V(x(e)) + val y = I(v) + E(asm-SetIns(t, x, y)) when x != y + (e:Return) : + match(ctxt(e)) : + (c:StanzaContext) : + E $ asm-Return() + (c:CContext) : + ;Save current context + E $ StoreL(M(stack-pointer(stubs)), RSP) + + ;Restore C context + E $ SetL(RSP, R(c-rsp-arg(backend(stubs)))) + for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : + val o = -8 - (8 * i) + E $ LoadL(R(reg), RSP, o) + E $ asm-Return() + (e:Args) : + match(ctxt(e)) : + (ctxt:StanzaContext) : + ;Everything is set up already + false + (ctxt:CContext) : + false + (e:Call) : + match(type(e)) : + (t:ExtendStack) : + val return-lbl = unique-id(stubs) + E $ SetL(R0, LM(return-lbl)) + E $ SetL(R1, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) + E $ asm-Goto(M(extend-stack(stubs))) + E $ asm-Label(return-lbl) + (t:CollectGarbage) : + val return-lbl = unique-id(stubs) + E $ SetL(R0, LM(return-lbl)) + E $ asm-Goto(M(collect-garbage(stubs))) + E $ asm-Label(return-lbl) + (t:StanzaCall) : + val frame-size = INT(size(stackmap) + 8) + E $ AddL(RSP, RSP, frame-size) + E $ asm-Call(I(f(e))) + match(info(t):FileInfo) : + E $ asm-Label(unique-id(stubs), info(t)) + E $ SubL(RSP, RSP, frame-size) + (t:StanzaTCall) : + E $ asm-Goto(I(f(e))) + (t:CCall) : + ;Push frame: + E $ AddL(RSP, RSP, INT(size(stackmap))) + + ;Save RSP + E $ StoreL(M(stack-pointer(stubs)), RSP) + + ;Restore the C context: + E $ LoadL(RSP, M(saved-c-rsp(stubs))) + + ;Call C function with right convention + val num-float-args = for y in ys(e) count : reg?(y as Var) is FReg + E $ SubL(RSP, RSP, INT(frame-size(num-mem-args(t), backend(stubs)))) + E $ SetL(R0, INT(num-float-args)) + E $ asm-Call(I(f(e))) + + ;Load RSP + E $ LoadL(RSP, M(stack-pointer(stubs))) + + ;Pop frame: + E $ SubL(RSP, RSP, INT(size(stackmap))) + (t:YieldCall) : + val lbl = unique-id(stubs) + val TMP = to-asm-loc(scratch-regs(t)[0]) + val TMP2 = to-asm-loc(scratch-regs(t)[1]) + val F = I(f(e)) + + ;Save current stack progress + val size-offset = -1 + 8 + val frames-offset = -1 + 8 + 8 + val sp-offset = -1 + 8 + 8 + 8 + val pc-offset = -1 + 8 + 8 + 8 + 8 + E $ LoadL(TMP, M(current-stack(stubs))) + E $ SetL(TMP2, LM(lbl)) + E $ StoreL(TMP, TMP2, pc-offset) + E $ StoreL(TMP, RSP, sp-offset) + + ;Load given stack + E $ StoreL(M(current-stack(stubs)), F) + if enter?(t) : E $ LoadL(RSP, F, frames-offset) + else : E $ LoadL(RSP, F, sp-offset) + E $ LoadL(TMP, F, frames-offset) + E $ LoadL(TMP2, F, size-offset) + E $ AddL(TMP, TMP, TMP2) + E $ StoreL(M(stack-limit(stubs)), TMP) + + E $ LoadL(TMP, F, pc-offset) + E $ asm-Goto(TMP) + E $ asm-Label(lbl, info(t)) + (e:Op) : ;[2] + match(op(e)) : + (op:SaveCContextOp) : + ;Save C preserved registers + for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : + val o = -8 - (8 * i) + E $ StoreL(RSP, R(reg), o) + ;Move RSP to special register for holding CRSP + E $ SetL(R(c-rsp-arg(backend(stubs))), RSP) + ;Load Stanza RSP + E $ LoadL(RSP, M(stack-pointer(stubs))) + (op:RecordLiveOp) : + val indices = qsort $ + for v in live-vars(op) seq? : + if type(v) is VMRef : + val o = offset(stackmap, n(v)) - 16 + fatal("Wrong alignment for ref on stack.") when o % 8 != 0 + One(o / 8) + else : None() + E $ StoreL(RSP, asm-StackMap(size(stackmap), indices), 8) + (op:AllocOp) : + val x = V(xs(e)[0]) + val size = I(ys(e)[0]) + val TMP = R0 + val TMP2 = R1 + E $ LoadL(TMP, M(heap-top(stubs))) + E $ SetL(TMP2, size) + E $ AddL(x, TMP, INT(1)) + E $ AddL(TMP, TMP, TMP2) + E $ StoreL(M(heap-top(stubs)), TMP) + (op:NoOp) : + false + (op:ConvOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-ConvertIns(T(x), V(x), T(y), I(y)) + (op:InterpretOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-InterpretIns(T(x), V(x), T(y), I(y)) + (op:LoadOp) : + val [x, y, o] = [head(xs(e)), head(ys(e)), offset(op)] + E $ asm-Load(T(x), V(x), I(y), o) + (op:StoreOp) : + val [x, y, o] = [ys(e)[0], ys(e)[1], offset(op)] + E $ asm-Store(T(y), I(x), I(y), o) + (op:LoadArgOp) : + val x = xs(e)[0] + E $ asm-Load(T(x), V(x), M(registers(stubs)), 8 * index(op)) + (op:StoreArgOp) : + val y = ys(e)[0] + E $ asm-Store(T(y), M(registers(stubs)), I(y), 8 * index(op)) + (op:StoreCArgOp) : + val crsp = ys(e)[0] + val y = ys(e)[1] + E $ asm-Store(T(y), I(crsp), I(y), store-mem-arg-offset(op,backend(stubs))) + (op:LoadCArgOp) : + val crsp = ys(e)[0] + val x = xs(e)[0] + E $ asm-Load(T(x), V(x), I(crsp), load-mem-arg-offset(op,backend(stubs))) + (op:CRSPOp) : + val x = xs(e)[0] + E $ LoadL(V(x), M(saved-c-rsp(stubs))) + (op:StoreCRSPOp) : + val y = ys(e)[0] + E $ StoreL(M(saved-c-rsp(stubs)), I(y)) + (op:VMOp&Binary) : + val [x, y, z] = [head(xs(e)), ys(e)[0], ys(e)[1]] + E $ asm-BinOp(T(y), V(x), to-asm-op(op), I(y), I(z)) + (op:VMOp&Unary) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) + (op:DivModOp) : + val [x1, x2, y, z] = [xs(e)[0], xs(e)[1], ys(e)[0], ys(e)[1]] + E $ asm-DualOp(T(x1), V(x1), V(x2), to-asm-op(op), I(y), I(z)) + (op:InstanceofOp) : + val [x, y] = [head(xs(e)), head(ys(e))] + E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) + (op:FlushVMOp) : + val x = V(head(xs(e))) + val stack-pointer-offset = -1 + 8 + 16 + E $ LoadL(x, M(current-stack(stubs))) + E $ StoreL(x, RSP, stack-pointer-offset) + E $ SetL(x, M(vmstate(stubs))) + (op) : + fatal("Not yet implemented") + + (e:Save) : + val x = x(e) + val offset = offset(stackmap, n(x)) + E $ asm-Store(T(x), RSP, I(x), offset) + (e:Load) : + val x = x(e) + val offset = offset(stackmap, n(x)) + E $ asm-Load(T(x), V(x), RSP, offset) + (e:Xchg) : + val [x, y] = [x(e), y(e)] + match(swap(e)) : + (s:FReg) : + E $ SetD(F(n(s)), I(x)) + E $ SetD(V(x), I(y)) + E $ SetD(V(y), F(n(s))) + (s:False) : + E $ asm-XchgIns(V(x), V(y)) + (e:ShuffleReg) : + if xs(e) != ys(e) : + shuffle(num-regs(backend(stubs)), xs(e), ys(e), + fn (src:Int, dst:Int) : + E $ asm-SetIns(LT, R(dst), R(src)) + fn (src:Int, dst:Int) : + E $ asm-XchgIns(R(dst), R(src))) + (e:ShuffleFReg) : + if xs(e) != ys(e) : + shuffle(num-fregs(backend(stubs)), xs(e), ys(e), + fn (src:Int, dst:Int) : + E $ asm-SetIns(DT, F(dst), F(src)) + fn (n:Int) : + E $ asm-Store(DT, M(swap-lbl(stubs)), F(n), 0) + fn (n:Int) : + E $ asm-Load(DT, F(n), M(swap-lbl(stubs)), 0)) + (e:Label) : + val l = label-table[n(e)] + E $ asm-Label(asm-n(l)) + (e:Goto) : + E $ asm-Goto(label-table[n(e)]) + (e:Break) : ;[1] + defn cmp-stack-limit (le-op:asm-Op) : + val TMP = R0 + val TMP2 = R1 + E $ AddL(TMP, RSP, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) + E $ LoadL(TMP2, M(stack-limit(stubs))) + E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) + defn cmp-heap-limit (le-op:asm-Op) : + val TMP = R0 + val TMP2 = R1 + val size = I(xs(e)[0]) + E $ LoadL(TMP, M(heap-top(stubs))) + E $ AddL(TMP, TMP, size) + E $ LoadL(TMP2, M(heap-limit(stubs))) + E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) + defn cmp-arity (arg:Int, value:Int, eq-op:asm-Op) : + val arg-reg = R(call-regs(backend(stubs))[arg]) + E $ BreakL(label-table[n(e)], eq-op, arg-reg, INT(value)) + + match(op(e)) : + (op:HasStackOp) : + cmp-stack-limit(asm-UleOp()) + (op:HasHeapOp) : + cmp-heap-limit(asm-UleOp()) + (op:ArgEqOp) : + cmp-arity(arg(op), value(op), asm-EqOp()) + (fop:FlipOp) : + match(op(fop)) : + (op:HasStackOp) : + cmp-stack-limit(asm-flip(asm-UleOp())) + (op:HasHeapOp) : + cmp-heap-limit(asm-flip(asm-UleOp())) + (op:ArgEqOp) : + cmp-arity(arg(op), value(op), asm-flip(asm-EqOp())) + (op) : + val [x, y] = [xs(e)[0], xs(e)[1]] + E $ asm-Break(T(x), label-table[n(e)], to-asm-op(op), I(x), I(y)) + (e:Match) : + if dispatch?(e) : + val no-branch = label-table[ns(e)[0]] + val amb-branch = label-table[ns(e)[1]] + val branch-ns = tailn(ns(e), 2) + val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) + val xs = map(I, xs(e)) + E $ asm-Dispatch(xs, bs, no-branch, amb-branch) + else : + val no-branch = label-table[head(ns(e))] + val branch-ns = tail(ns(e)) + val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) + val xs = map(I, xs(e)) + E $ asm-Match(xs, bs, no-branch) + (e:MethodDispatch) : + val no-branch = label-table[default(e)] + val amb-branch = label-table[amb(e)] + E $ asm-MethodDispatch(multi(e), num-header-args(e), no-branch, amb-branch) + (e) : fatal("Not yet implemented: %_" % [e]) + + ;find target of body from hasstackop break label in inst 1, where inst 0 is top body label val start-body-label = - match(ins(BLOCKS[0])[1]) : ;; LABEL IS 1st INST THEN BREAK / HASSTACKOP IS 2nd + match(ins(BLOCKS[0])[1]) : (e:Break) : n(e) when op(e) is HasStackOp else -1 (e) : -1 - var stripping?:True|False = if size(stackmap) <= 16 and start-body-label >= 0 : - for e in ins(BLOCKS[0]) any? : match(e:Call) : type(e) is-not StanzaTCall + var stripping-preamble?:True|False = if size(stackmap) <= SMALL-SMAP-SIZE and start-body-label >= 0 : + for e in ins(BLOCKS[0]) any? : + match(e:Call) : type(e) is-not StanzaTCall - ;; println("/* STRIPPING? %_: SS %_ */" % [stripping?, size(stackmap)]) - num-assembled = num-assembled + 1 - if stripping? : num-stripped = num-stripped + 1 - for (e in ins(BLOCKS[0]), i in 0 to false) do : - if stripping? and i > 0 : - ;; println("/* --- Stripping: %_ */" % [e]) + if stripping-preamble? and i > 0 : match(e:Label) : - if n(e) == start-body-label: stripping? = false + if n(e) == start-body-label: stripping-preamble? = false else : - ;; println("/* --- Assembling: %_ */" % [e]) - match(e) : - (e:Set) : - match(y(e)) : - (v:Val) : - match(value(v)) : - (v:ConstId) : load-const(id(v)) - (v) : set-value(y(e)) - (v) : set-value(v) - where : - defn load-const (id:Int) : - val x = V(x(e)) - E $ LoadL(x, asm-LinkId(id)) - defn set-value (v:Imm) : - val t = T(x(e)) - val x = V(x(e)) - val y = I(v) - E(asm-SetIns(t, x, y)) when x != y - (e:Return) : - match(ctxt(e)) : - (c:StanzaContext) : - E $ asm-Return() - (c:CContext) : - ;Save current context - E $ StoreL(M(stack-pointer(stubs)), RSP) - - ;Restore C context - E $ SetL(RSP, R(c-rsp-arg(backend(stubs)))) - for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : - val o = -8 - (8 * i) - E $ LoadL(R(reg), RSP, o) - E $ asm-Return() - (e:Args) : - match(ctxt(e)) : - (ctxt:StanzaContext) : - ;Everything is set up already - false - (ctxt:CContext) : - false - (e:Call) : - match(type(e)) : - (t:ExtendStack) : - val return-lbl = unique-id(stubs) - E $ SetL(R0, LM(return-lbl)) - E $ SetL(R1, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) - E $ asm-Goto(M(extend-stack(stubs))) - E $ asm-Label(return-lbl) - (t:CollectGarbage) : - val return-lbl = unique-id(stubs) - E $ SetL(R0, LM(return-lbl)) - E $ asm-Goto(M(collect-garbage(stubs))) - E $ asm-Label(return-lbl) - (t:StanzaCall) : - val frame-size = INT(size(stackmap) + 8) - E $ AddL(RSP, RSP, frame-size) - E $ asm-Call(I(f(e))) - match(info(t):FileInfo) : - E $ asm-Label(unique-id(stubs), info(t)) - E $ SubL(RSP, RSP, frame-size) - (t:StanzaTCall) : - E $ asm-Goto(I(f(e))) - (t:CCall) : - ;Push frame: - E $ AddL(RSP, RSP, INT(size(stackmap))) - - ;Save RSP - E $ StoreL(M(stack-pointer(stubs)), RSP) - - ;Restore the C context: - E $ LoadL(RSP, M(saved-c-rsp(stubs))) - - ;Call C function with right convention - val num-float-args = for y in ys(e) count : reg?(y as Var) is FReg - E $ SubL(RSP, RSP, INT(frame-size(num-mem-args(t), backend(stubs)))) - E $ SetL(R0, INT(num-float-args)) - E $ asm-Call(I(f(e))) - - ;Load RSP - E $ LoadL(RSP, M(stack-pointer(stubs))) - - ;Pop frame: - E $ SubL(RSP, RSP, INT(size(stackmap))) - (t:YieldCall) : - val lbl = unique-id(stubs) - val TMP = to-asm-loc(scratch-regs(t)[0]) - val TMP2 = to-asm-loc(scratch-regs(t)[1]) - val F = I(f(e)) - - ;Save current stack progress - val size-offset = -1 + 8 - val frames-offset = -1 + 8 + 8 - val sp-offset = -1 + 8 + 8 + 8 - val pc-offset = -1 + 8 + 8 + 8 + 8 - E $ LoadL(TMP, M(current-stack(stubs))) - E $ SetL(TMP2, LM(lbl)) - E $ StoreL(TMP, TMP2, pc-offset) - E $ StoreL(TMP, RSP, sp-offset) - - ;Load given stack - E $ StoreL(M(current-stack(stubs)), F) - if enter?(t) : E $ LoadL(RSP, F, frames-offset) - else : E $ LoadL(RSP, F, sp-offset) - E $ LoadL(TMP, F, frames-offset) - E $ LoadL(TMP2, F, size-offset) - E $ AddL(TMP, TMP, TMP2) - E $ StoreL(M(stack-limit(stubs)), TMP) - - E $ LoadL(TMP, F, pc-offset) - E $ asm-Goto(TMP) - E $ asm-Label(lbl, info(t)) - (e:Op) : ;[2] - match(op(e)) : - (op:SaveCContextOp) : - ;Save C preserved registers - for (reg in c-preserved-regs(backend(stubs)), i in 0 to false) do : - val o = -8 - (8 * i) - E $ StoreL(RSP, R(reg), o) - ;Move RSP to special register for holding CRSP - E $ SetL(R(c-rsp-arg(backend(stubs))), RSP) - ;Load Stanza RSP - E $ LoadL(RSP, M(stack-pointer(stubs))) - (op:RecordLiveOp) : - val indices = qsort $ - for v in live-vars(op) seq? : - if type(v) is VMRef : - val o = offset(stackmap, n(v)) - 16 - fatal("Wrong alignment for ref on stack.") when o % 8 != 0 - One(o / 8) - else : None() - E $ StoreL(RSP, asm-StackMap(size(stackmap), indices), 8) - (op:AllocOp) : - val x = V(xs(e)[0]) - val size = I(ys(e)[0]) - val TMP = R0 - val TMP2 = R1 - E $ LoadL(TMP, M(heap-top(stubs))) - E $ SetL(TMP2, size) - E $ AddL(x, TMP, INT(1)) - E $ AddL(TMP, TMP, TMP2) - E $ StoreL(M(heap-top(stubs)), TMP) - (op:NoOp) : - false - (op:ConvOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-ConvertIns(T(x), V(x), T(y), I(y)) - (op:InterpretOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-InterpretIns(T(x), V(x), T(y), I(y)) - (op:LoadOp) : - val [x, y, o] = [head(xs(e)), head(ys(e)), offset(op)] - E $ asm-Load(T(x), V(x), I(y), o) - (op:StoreOp) : - val [x, y, o] = [ys(e)[0], ys(e)[1], offset(op)] - E $ asm-Store(T(y), I(x), I(y), o) - (op:LoadArgOp) : - val x = xs(e)[0] - E $ asm-Load(T(x), V(x), M(registers(stubs)), 8 * index(op)) - (op:StoreArgOp) : - val y = ys(e)[0] - E $ asm-Store(T(y), M(registers(stubs)), I(y), 8 * index(op)) - (op:StoreCArgOp) : - val crsp = ys(e)[0] - val y = ys(e)[1] - E $ asm-Store(T(y), I(crsp), I(y), store-mem-arg-offset(op,backend(stubs))) - (op:LoadCArgOp) : - val crsp = ys(e)[0] - val x = xs(e)[0] - E $ asm-Load(T(x), V(x), I(crsp), load-mem-arg-offset(op,backend(stubs))) - (op:CRSPOp) : - val x = xs(e)[0] - E $ LoadL(V(x), M(saved-c-rsp(stubs))) - (op:StoreCRSPOp) : - val y = ys(e)[0] - E $ StoreL(M(saved-c-rsp(stubs)), I(y)) - (op:VMOp&Binary) : - val [x, y, z] = [head(xs(e)), ys(e)[0], ys(e)[1]] - E $ asm-BinOp(T(y), V(x), to-asm-op(op), I(y), I(z)) - (op:VMOp&Unary) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) - (op:DivModOp) : - val [x1, x2, y, z] = [xs(e)[0], xs(e)[1], ys(e)[0], ys(e)[1]] - E $ asm-DualOp(T(x1), V(x1), V(x2), to-asm-op(op), I(y), I(z)) - (op:InstanceofOp) : - val [x, y] = [head(xs(e)), head(ys(e))] - E $ asm-UnaOp(T(x), V(x), to-asm-op(op), I(y)) - (op:FlushVMOp) : - val x = V(head(xs(e))) - val stack-pointer-offset = -1 + 8 + 16 - E $ LoadL(x, M(current-stack(stubs))) - E $ StoreL(x, RSP, stack-pointer-offset) - E $ SetL(x, M(vmstate(stubs))) - (op) : - fatal("Not yet implemented") - - (e:Save) : - val x = x(e) - val offset = offset(stackmap, n(x)) - E $ asm-Store(T(x), RSP, I(x), offset) - (e:Load) : - val x = x(e) - val offset = offset(stackmap, n(x)) - E $ asm-Load(T(x), V(x), RSP, offset) - (e:Xchg) : - val [x, y] = [x(e), y(e)] - match(swap(e)) : - (s:FReg) : - E $ SetD(F(n(s)), I(x)) - E $ SetD(V(x), I(y)) - E $ SetD(V(y), F(n(s))) - (s:False) : - E $ asm-XchgIns(V(x), V(y)) - (e:ShuffleReg) : - if xs(e) != ys(e) : - shuffle(num-regs(backend(stubs)), xs(e), ys(e), - fn (src:Int, dst:Int) : - E $ asm-SetIns(LT, R(dst), R(src)) - fn (src:Int, dst:Int) : - E $ asm-XchgIns(R(dst), R(src))) - (e:ShuffleFReg) : - if xs(e) != ys(e) : - shuffle(num-fregs(backend(stubs)), xs(e), ys(e), - fn (src:Int, dst:Int) : - E $ asm-SetIns(DT, F(dst), F(src)) - fn (n:Int) : - E $ asm-Store(DT, M(swap-lbl(stubs)), F(n), 0) - fn (n:Int) : - E $ asm-Load(DT, F(n), M(swap-lbl(stubs)), 0)) - (e:Label) : - val l = label-table[n(e)] - E $ asm-Label(asm-n(l)) - (e:Goto) : - E $ asm-Goto(label-table[n(e)]) - (e:Break) : ;[1] - defn cmp-stack-limit (le-op:asm-Op) : - val TMP = R0 - val TMP2 = R1 - E $ AddL(TMP, RSP, INT(size(stackmap) + (8 + SMALL-SMAP-SIZE))) - E $ LoadL(TMP2, M(stack-limit(stubs))) - E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) - defn cmp-heap-limit (le-op:asm-Op) : - val TMP = R0 - val TMP2 = R1 - val size = I(xs(e)[0]) - E $ LoadL(TMP, M(heap-top(stubs))) - E $ AddL(TMP, TMP, size) - E $ LoadL(TMP2, M(heap-limit(stubs))) - E $ BreakL(label-table[n(e)], le-op, TMP, TMP2) - defn cmp-arity (arg:Int, value:Int, eq-op:asm-Op) : - val arg-reg = R(call-regs(backend(stubs))[arg]) - E $ BreakL(label-table[n(e)], eq-op, arg-reg, INT(value)) - - match(op(e)) : - (op:HasStackOp) : - cmp-stack-limit(asm-UleOp()) - (op:HasHeapOp) : - cmp-heap-limit(asm-UleOp()) - (op:ArgEqOp) : - cmp-arity(arg(op), value(op), asm-EqOp()) - (fop:FlipOp) : - match(op(fop)) : - (op:HasStackOp) : - cmp-stack-limit(asm-flip(asm-UleOp())) - (op:HasHeapOp) : - cmp-heap-limit(asm-flip(asm-UleOp())) - (op:ArgEqOp) : - cmp-arity(arg(op), value(op), asm-flip(asm-EqOp())) - (op) : - val [x, y] = [xs(e)[0], xs(e)[1]] - E $ asm-Break(T(x), label-table[n(e)], to-asm-op(op), I(x), I(y)) - (e:Match) : - if dispatch?(e) : - val no-branch = label-table[ns(e)[0]] - val amb-branch = label-table[ns(e)[1]] - val branch-ns = tailn(ns(e), 2) - val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) - val xs = map(I, xs(e)) - E $ asm-Dispatch(xs, bs, no-branch, amb-branch) - else : - val no-branch = label-table[head(ns(e))] - val branch-ns = tail(ns(e)) - val bs = map(asm-Branch{_, label-table[_]}, type-lists(e), branch-ns) - val xs = map(I, xs(e)) - E $ asm-Match(xs, bs, no-branch) - (e:MethodDispatch) : - val no-branch = label-table[default(e)] - val amb-branch = label-table[amb(e)] - E $ asm-MethodDispatch(multi(e), num-header-args(e), no-branch, amb-branch) - (e) : fatal("Not yet implemented: %_" % [e]) + emit(e) defn asm-type (x:Imm) : to-asm-type(type(x)) From 14c1aa25a8e015d209ec039fb4ac4c66f2436f1d Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Wed, 5 Feb 2020 17:06:17 -0800 Subject: [PATCH 3/7] comment code --- compiler/stz-reg-alloc.stanza | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 6489a6a4d..1728c6d6e 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -2685,6 +2685,15 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : (e) : fatal("Not yet implemented: %_" % [e]) ;find target of body from hasstackop break label in inst 1, where inst 0 is top body label + ;fn looks like + ; 0: label fn-entry + ; 1: goto has-stack-lbl when HasStackop else no-stack-lbl + ; 2: label no-stack-lbl + ; 3: ExtendStackIns + ; 4: goto has-stack-lbl + ; 5: label has-stack-lbl + ; 6: ... + ;strip ins 1-5 when size(stackmap) <= SMALL-SMAP-SIZE and no non-tail-calls in body val start-body-label = match(ins(BLOCKS[0])[1]) : (e:Break) : n(e) when op(e) is HasStackOp else -1 From d73aa545b7c861188fc1b143da9b4b12d18dcd01 Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Wed, 5 Feb 2020 18:20:53 -0800 Subject: [PATCH 4/7] remove debug --- compiler/stz-compiler-main.stanza | 8 -------- compiler/stz-reg-alloc.stanza | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/stz-compiler-main.stanza b/compiler/stz-compiler-main.stanza index 9a002134c..6318c9a53 100644 --- a/compiler/stz-compiler-main.stanza +++ b/compiler/stz-compiler-main.stanza @@ -180,16 +180,8 @@ public defn compile (proj-manager:ProjManager, `optimized-asm : val packages = Vector() val opt-timer = MillisecondTimer("Opt") - start(opt-timer) add(packages, combine-and-lower(/packages(result) as Tuple)) - stop(opt-timer) - println(opt-timer) - val backend-timer = MillisecondTimer("Backend") - start(backend-timer) compile-vmpackages({false}, to-tuple(packages), bindings(result), output as String, false) - stop(backend-timer) - println(backend-timer) - println("NUM-STRIPPED %_ NUM-ASSEMBLED %_: %_%%" % [num-stripped, num-assembled, 100.0 * to-double(num-stripped) / to-double(num-assembled)]) `optimized-pkgs : ;Already done false diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 1728c6d6e..4217c0a9d 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -2394,7 +2394,7 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : ;==== Body ==== ;============== - defn emit (e:EIns) : + defn emit (e:Ins) : match(e) : (e:Set) : match(y(e)) : From 5b2d6e1b43df39103114f41ee1eeff175dbe332b Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Fri, 7 Feb 2020 11:38:47 -0800 Subject: [PATCH 5/7] move parameter to top, and remove old timer debug code --- compiler/stz-compiler-main.stanza | 1 - compiler/stz-reg-alloc.stanza | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/stz-compiler-main.stanza b/compiler/stz-compiler-main.stanza index 6318c9a53..29e592887 100644 --- a/compiler/stz-compiler-main.stanza +++ b/compiler/stz-compiler-main.stanza @@ -179,7 +179,6 @@ public defn compile (proj-manager:ProjManager, switch(situation) : `optimized-asm : val packages = Vector() - val opt-timer = MillisecondTimer("Opt") add(packages, combine-and-lower(/packages(result) as Tuple)) compile-vmpackages({false}, to-tuple(packages), bindings(result), output as String, false) `optimized-pkgs : diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 4217c0a9d..3db4039e8 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -201,10 +201,15 @@ defpackage stz/reg-alloc : prefix(Block) => Basic ;============================================================ -;===================== Driver =============================== +;=================== Parameters ============================= ;============================================================ -val SMALL-SMAP-SIZE = 16 ;; SIZE OF SMAP WHICH CAN BE CALLED WITHOUT CHECKING STACK-SIZE +;Size of smap which can be called without checking stack-size. +val SMALL-SMAP-SIZE = 16 + +;============================================================ +;===================== Driver =============================== +;============================================================ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Backend, stubs:AsmStubs, print?:True|False) -> False : take-ids(ins) From 41d95cd20e8a294ba350184509bdda8a266198be Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Fri, 7 Feb 2020 13:22:37 -0800 Subject: [PATCH 6/7] use SectionMarkerIns to improve robustness in stripping stack-check preambles --- compiler/stz-reg-alloc.stanza | 39 +++++++++++++++----------------- compiler/stz-vm-ir.stanza | 7 +++++- compiler/stz-vm-normalize.stanza | 4 +++- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 3db4039e8..9c11d8f34 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -400,6 +400,9 @@ public defstruct Break <: Ins : op: VMOp xs: List +public defstruct SectionMarker <: Ins : + marker: Symbol + defmethod killed? (i:Save|Load|Unload|NextUsed|Xchg| ShuffleReg|ShuffleFReg|Label|Goto|Break) : false @@ -623,6 +626,7 @@ defmethod print (o:OutputStream, i:Ins) : (i:Label) : "label %_" % [n(i)] (i:Goto) : "goto %_" % [n(i)] (i:Break) : "break %_ when %_(%,)" % [n(i), op(i), xs(i)] + (i:SectionMarker) : "section: %~" % [marker(i)] defmethod print (o:OutputStream, c:FnContext) : print{o, _} $ match(c) : @@ -949,6 +953,8 @@ defn load-instructions (function:VMFunc, backend:Backend) : push(Op(SaveCContextOp(), List(), List())) (e:CommentIns) : false + (e:SectionMarkerIns) : + push(SectionMarker(marker(e))) (e:UnreachableIns) : false val next = to-list $ @@ -2689,30 +2695,21 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : E $ asm-MethodDispatch(multi(e), num-header-args(e), no-branch, amb-branch) (e) : fatal("Not yet implemented: %_" % [e]) - ;find target of body from hasstackop break label in inst 1, where inst 0 is top body label - ;fn looks like - ; 0: label fn-entry - ; 1: goto has-stack-lbl when HasStackop else no-stack-lbl - ; 2: label no-stack-lbl - ; 3: ExtendStackIns - ; 4: goto has-stack-lbl - ; 5: label has-stack-lbl - ; 6: ... - ;strip ins 1-5 when size(stackmap) <= SMALL-SMAP-SIZE and no non-tail-calls in body - val start-body-label = - match(ins(BLOCKS[0])[1]) : - (e:Break) : n(e) when op(e) is HasStackOp else -1 - (e) : -1 - var stripping-preamble?:True|False = if size(stackmap) <= SMALL-SMAP-SIZE and start-body-label >= 0 : + ;When size(stackmap) <= SMALL-SMAP-SIZE and no non-tail-calls in body: + val stripping-preamble?:True|False = if size(stackmap) <= SMALL-SMAP-SIZE : for e in ins(BLOCKS[0]) any? : match(e:Call) : type(e) is-not StanzaTCall - - for (e in ins(BLOCKS[0]), i in 0 to false) do : - if stripping-preamble? and i > 0 : - match(e:Label) : - if n(e) == start-body-label: stripping-preamble? = false + ;Strip ins between preamble SectionMarkerIns'. + var stripping?:True|False = false + for e in ins(BLOCKS[0]) do : + if stripping? : + match(e:SectionMarker) : + if marker(e) == `preamble: stripping? = false else : - emit(e) + match(e:SectionMarker) : + stripping? = marker(e) == `preamble + else : + emit(e) defn asm-type (x:Imm) : to-asm-type(type(x)) diff --git a/compiler/stz-vm-ir.stanza b/compiler/stz-vm-ir.stanza index ea7ab4aa9..3bd09c0f4 100644 --- a/compiler/stz-vm-ir.stanza +++ b/compiler/stz-vm-ir.stanza @@ -260,7 +260,10 @@ public defstruct LiveIns <: VMIns : xs: Tuple public defstruct CommentIns <: VMIns : message: String +public defstruct SectionMarkerIns <: VMIns : + marker: Symbol public defstruct UnreachableIns <: VMIns + public deftype VMValue : Char <: VMValue @@ -676,6 +679,7 @@ defmethod print (o:OutputStream, i:VMIns) : (i:RecordLiveIns) : P $ "live (%,)" % [live(i)] (i:LiveIns) : P $ "mark-live (%,)" % [xs(i)] (i:CommentIns) : P $ "comment: %~" % [message(i)] + (i:SectionMarkerIns) : P $ "section: %~" % [marker(i)] (i:MatchIns) : print(o, "match(%,) :" % [ys(i)]) val o2 = IndentedStream(o) @@ -828,6 +832,7 @@ defsyntax vmcode : defrule ins = (live (?xs:#local ...)) : RecordLiveIns(to-tuple(xs)) defrule ins = (mark-live (?xs:#imm! ...)) : LiveIns(to-tuple(xs)) defrule ins = (comment: ?x:#string!) : CommentIns(x) + defrule ins = (section: ?x:#symbol!) : SectionMarkerIns(x) defrule ins = (match(?ys:#imm! ...) : (?bs:#vmbranch ... ?d:#defaultbranch)) : MatchIns(to-tuple(ys), to-tuple(bs), d) defrule ins = (dispatch(?ys:#imm! ...) : (?bs:#vmbranch ... ?d:#defaultbranch ?a:#ambbranch)) : DispatchIns(to-tuple(ys), to-tuple(bs), d, a) @@ -1057,4 +1062,4 @@ public defn dump (p:VMPackage, suffix:String|False) : dump(p, ".", suffix) public defn dump (p:VMPackage) : - dump(p, false) \ No newline at end of file + dump(p, false) diff --git a/compiler/stz-vm-normalize.stanza b/compiler/stz-vm-normalize.stanza index 86736db51..8a19ec176 100644 --- a/compiler/stz-vm-normalize.stanza +++ b/compiler/stz-vm-normalize.stanza @@ -70,11 +70,13 @@ defn normalize (f0:VMFunction, databuffer:DataBuffer, backend:Backend, iotable:I ;Check stack extension val has-stack-lbl = make-label(buffer) val no-stack-lbl = make-label(buffer) + load-instruction(SectionMarkerIns(`preamble)) load-instruction(Branch0Ins(has-stack-lbl, no-stack-lbl, HasStackOp())) load-instruction(LabelIns(no-stack-lbl)) load-instruction(ExtendStackIns()) load-instruction(GotoIns(has-stack-lbl)) load-instruction(LabelIns(has-stack-lbl)) + load-instruction(SectionMarkerIns(`preamble)) ;Get arguments val arg-rec = arg-extern-records(buffer, args(f), c-rsp-arg, backend) @@ -1438,4 +1440,4 @@ defn InsBuffer (function:VMFunction) : else : i def-table[n] = VMDef(n, t) Local(n) - \ No newline at end of file + From 97fecf891bb18c9201c54d9b7986be5494782101 Mon Sep 17 00:00:00 2001 From: jackbackrack Date: Fri, 7 Feb 2020 15:01:31 -0800 Subject: [PATCH 7/7] get robust SectionMarkerIns working in bootstrapped compiler --- compiler/stz-config.stanza | 2 ++ compiler/stz-params.stanza | 1 + compiler/stz-reg-alloc.stanza | 24 ++++++++++++++++-------- compiler/stz-vm-normalize.stanza | 2 ++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/stz-config.stanza b/compiler/stz-config.stanza index 701f78b63..0acf1b578 100644 --- a/compiler/stz-config.stanza +++ b/compiler/stz-config.stanza @@ -69,6 +69,8 @@ defsyntax stanza-config : STANZA-MAX-COMPILER-HEAP-SIZE = sz defrule entry = (experimental = ?b:#bool!) : EXPERIMENTAL = b + defrule entry = (strip-stack-checks? = ?b:#bool!) : + STRIP-STACK-CHECKS? = b fail-if entry = () : PE(closest-info(), "Invalid configuration rule.") diff --git a/compiler/stz-params.stanza b/compiler/stz-params.stanza index d6ecb2d75..57955febb 100644 --- a/compiler/stz-params.stanza +++ b/compiler/stz-params.stanza @@ -20,6 +20,7 @@ public var OUTPUT-PLATFORM:Symbol = `platform public var STANZA-PKG-DIRS:List = List() public val STANZA-PROJ-FILES = Vector() public var EXPERIMENTAL:True|False = false +public var STRIP-STACK-CHECKS?:True|False = false ;====== Compiler Configuration ===== public var STANZA-MAX-COMPILER-HEAP-SIZE = 4L * 1024L * 1024L * 1024L diff --git a/compiler/stz-reg-alloc.stanza b/compiler/stz-reg-alloc.stanza index 9c11d8f34..5a9149a05 100644 --- a/compiler/stz-reg-alloc.stanza +++ b/compiler/stz-reg-alloc.stanza @@ -256,9 +256,9 @@ public defn allocate-registers (ins:VMFunction, emitter:CodeEmitter, backend:Bac print-prog() val smap = stack-map() - ;if print? : - ; println("==== Stack Map ====") - ; println(smap) + ;; if print? : + ;; println("==== Stack Map ====") + ;; println(smap) collapse-blocks() if print? : @@ -363,6 +363,10 @@ public defstruct MethodDispatch <: Ins : amb?: Int|False with: (default => false) killed?: False|List with: (default => false, as-method => true) +public defstruct SectionMarker <: Ins : + marker: Symbol + killed?: False|List with: (default => false, as-method => true) + public defstruct Save <: Ins : x: Var @@ -400,9 +404,6 @@ public defstruct Break <: Ins : op: VMOp xs: List -public defstruct SectionMarker <: Ins : - marker: Symbol - defmethod killed? (i:Save|Load|Unload|NextUsed|Xchg| ShuffleReg|ShuffleFReg|Label|Goto|Break) : false @@ -666,6 +667,7 @@ defn do-defined (f: Var -> ?, e:Ins) : (e:Load) : f(x(e)) (e:Match) : false (e:MethodDispatch) : false + (e:SectionMarker) : false false defn do-used (gv: Var -> ?, e:Ins) : @@ -682,6 +684,7 @@ defn do-used (gv: Var -> ?, e:Ins) : (e:Load) : false (e:Match) : do(g, xs(e)) (e:MethodDispatch) : false + (e:SectionMarker) : false false defn used-vars (e:Ins) : @@ -727,6 +730,8 @@ defn reverse-sweep (e:Ins, define:Var -> ?, emit:Ins -> ?, use-var:Var -> ?) : do(use, xs(e)) (e:MethodDispatch) : emit(e) + (e:SectionMarker) : + emit(e) defn attach-killed (e:Ins, ks:List) : match(e) : @@ -739,6 +744,7 @@ defn attach-killed (e:Ins, ks:List) : (e:Branch) : Branch(op(e), xs(e), ks) (e:Match) : Match(dispatch?(e), type-lists(e), xs(e), ks, ns?(e)) (e:MethodDispatch) : MethodDispatch(multi(e), num-header-args(e), default?(e), amb?(e), ks) + (e:SectionMarker) : SectionMarker(marker(e), ks) ;============================================================ ;=================== Unique Labels ========================== @@ -1818,6 +1824,8 @@ defn register-assignment (blk:Block, b:Int, backend:Backend) : do(free-var, killed(e)) (e:MethodDispatch) : emit(e) + (e:SectionMarker) : + emit(e) (e:Op) : defn assign-prefs (pref:List -> Loc|List) : val ys* = map(annotate, ys(e)) @@ -2696,7 +2704,7 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : (e) : fatal("Not yet implemented: %_" % [e]) ;When size(stackmap) <= SMALL-SMAP-SIZE and no non-tail-calls in body: - val stripping-preamble?:True|False = if size(stackmap) <= SMALL-SMAP-SIZE : + val stripping-preamble?:True|False = if size(stackmap) <= SMALL-SMAP-SIZE and STRIP-STACK-CHECKS? : for e in ins(BLOCKS[0]) any? : match(e:Call) : type(e) is-not StanzaTCall ;Strip ins between preamble SectionMarkerIns'. @@ -2707,7 +2715,7 @@ defn assemble (emitter:CodeEmitter, stackmap:StackMap, stubs:AsmStubs) : if marker(e) == `preamble: stripping? = false else : match(e:SectionMarker) : - stripping? = marker(e) == `preamble + stripping? = stripping-preamble? and (marker(e) == `preamble) else : emit(e) diff --git a/compiler/stz-vm-normalize.stanza b/compiler/stz-vm-normalize.stanza index 8a19ec176..8c55d9118 100644 --- a/compiler/stz-vm-normalize.stanza +++ b/compiler/stz-vm-normalize.stanza @@ -135,11 +135,13 @@ defn normalize (f0:VMFunction, databuffer:DataBuffer, backend:Backend, iotable:I ;Check stack extension val has-stack-lbl = make-label(buffer) val no-stack-lbl = make-label(buffer) + load-instruction(SectionMarkerIns(`preamble)) load-instruction(Branch0Ins(has-stack-lbl, no-stack-lbl, HasStackOp())) load-instruction(LabelIns(no-stack-lbl)) load-instruction(ExtendStackIns()) load-instruction(GotoIns(has-stack-lbl)) load-instruction(LabelIns(has-stack-lbl)) + load-instruction(SectionMarkerIns(`preamble)) ;Get arguments within ret = normalize(ret-records(buffer, args(f), backend)) :