From 5da72efbdeab965dbbcc992285be8a3ed5bf601b Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 12 Nov 2025 19:04:21 +0100 Subject: [PATCH] VM: refactoring [backport] (#25280) Note to @narimiran backport because IC requires it. --- compiler/vm.nim | 22 ++++++++++------------ compiler/vmdef.nim | 10 +++++++++- compiler/vmgen.nim | 28 ++++++++++------------------ 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 258c233345..4572f7a522 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -480,9 +480,9 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): else: asgnComplex(dest, src) -proc compile(c: PCtx, s: PSym): int = +proc compile(c: PCtx, s: PSym): VmProcInfo = result = vmgen.genProc(c, s) - when debugEchoCode: c.echoCode result + when debugEchoCode: c.echoCode result.pc #c.echoCode template handleJmpBack() {.dirty.} = @@ -1435,13 +1435,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = else: globalError(c.config, c.debug[pc], "VM not built with FFI support") elif prc.kind != skTemplate: - let newPc = compile(c, prc) + let procInfo = compile(c, prc) # tricky: a recursion is also a jump back, so we use the same # logic as for loops: - if newPc < pc: handleJmpBack() + if procInfo.pc < pc: handleJmpBack() #echo "new pc ", newPc, " calling: ", prc.name.s var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos) - newSeq(newFrame.slots, prc.offset+ord(isClosure)) + newSeq(newFrame.slots, procInfo.usedRegisters+ord(isClosure)) # setup slot for proc result: let ret {.cursor.} = prc.typ.returnType # hot spot ahead! @@ -1467,7 +1467,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = tos = newFrame updateRegsAlias # -1 for the following 'inc pc' - pc = newPc-1 + pc = procInfo.pc-1 else: # for 'getAst' support we need to support template expansion here: let genSymOwner = if tos.next != nil and tos.next.prc != nil: @@ -2351,8 +2351,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = let start = genProc(c, sym) var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil) - let maxSlots = sym.offset - newSeq(tos.slots, maxSlots) + newSeq(tos.slots, start.usedRegisters) # setup parameters: if not isEmptyType(sym.typ.returnType) or sym.kind == skMacro: @@ -2361,7 +2360,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = for i in 0..= 0 and c.code[last].opcode == opcEof: eofInstr = c.code[last] c.code.setLen(last) c.debug.setLen(last) #c.removeLastEof - result = c.code.len+1 # skip the jump instruction + result.pc = (c.code.len+1).int32 # skip the jump instruction c.procToCodePos[s.id] = result # thanks to the jmp we can add top level statements easily and also nest # procs easily: @@ -2457,12 +2449,12 @@ proc genProc(c: PCtx; s: PSym): int = c.gABC(body, opcRet) c.patch(procStart) c.gABC(body, opcEof, eofInstr.regA) - c.optimizeJumps(result) - s.offset = c.prc.regInfo.len.int32 + c.optimizeJumps(result.pc) + result.usedRegisters = c.prc.regInfo.len.int32 + c.procToCodePos[s.id] = result #if s.name.s == "main" or s.name.s == "[]": # echo renderTree(body) # c.echoCode(result) c.prc = oldPrc else: - c.prc.regInfo.setLen s.offset - result = pos + c.prc.regInfo.setLen result.usedRegisters