optimalization: op popn
This commit is contained in:
parent
9fed85928d
commit
d64a63dc27
18
chunk.nim
18
chunk.nim
|
@ -6,7 +6,7 @@ import value
|
|||
type
|
||||
OpCode* = enum
|
||||
opReturn, opCall, # functions
|
||||
opPop, # pop
|
||||
opPop, opPopSA, opPopA # pop
|
||||
opPrint, # print
|
||||
opNegate, opNot # unary
|
||||
opAdd, opSubtract, opMultiply, opDivide, # math
|
||||
|
@ -25,8 +25,14 @@ type
|
|||
|
||||
DoubleUint8* = array[2, uint8]
|
||||
|
||||
|
||||
# WARNING! short args can safely assumed to be 1 byte long outside of chunk.nim
|
||||
const shortArgSize* = 1
|
||||
const shortArgMax* = 256 # despite the name, this is one larger than the max
|
||||
|
||||
# modules outside chunk.nim should not assume any length of argSize, however code inside chunk.nim can make such assumptions
|
||||
const argSize* = 2
|
||||
const argMax*: int = 256*256
|
||||
const argMax*: int = 256*256 # despite the name, this is one larger than the max
|
||||
|
||||
proc initChunk*(name: string): Chunk =
|
||||
Chunk(code: @[], name: name, lines: @[], constants: @[])
|
||||
|
@ -78,7 +84,11 @@ const constantInstructions = {
|
|||
opConstant,
|
||||
opDefineGlobal, opGetGlobal, opSetGlobal,
|
||||
}
|
||||
const shortArgInstructions = {
|
||||
opPopSA,
|
||||
}
|
||||
const argInstructions = {
|
||||
opPopA,
|
||||
opCall,
|
||||
opGetLocal, opSetLocal,
|
||||
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop,
|
||||
|
@ -94,6 +104,7 @@ proc disassembleChunk*(ch: Chunk) =
|
|||
template instruction: uint8 = ch.code[c]
|
||||
template line: int = ch.lines[c]
|
||||
template double: DoubleUint8 = [ch.code[c+1], ch.code[c+2]]
|
||||
template shortArg: uint8 = ch.code[c+1]
|
||||
let cFmt = &"{c:04}"
|
||||
let lineFmt = if lastLine == line: " | " else: &"{line:04}"
|
||||
try:
|
||||
|
@ -101,6 +112,9 @@ proc disassembleChunk*(ch: Chunk) =
|
|||
case instruction.OpCode:
|
||||
of simpleInstructions:
|
||||
write stdout, ")\n"
|
||||
of shortArgInstructions:
|
||||
write stdout, &" {shortArg.toHex(2)}"
|
||||
c += 1
|
||||
of argInstructions:
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
c += 2
|
||||
|
|
38
compiler.nim
38
compiler.nim
|
@ -131,12 +131,30 @@ proc synchronize(comp: Compiler) =
|
|||
return
|
||||
comp.advance()
|
||||
|
||||
proc writeChunk(comp: Compiler, dStackIndex: int, ch: OpCode | DoubleUint8) =
|
||||
proc writeChunk(comp: Compiler, dStackIndex: int, ch: OpCode | DoubleUint8 | uint8) =
|
||||
comp.stackIndex += dStackIndex
|
||||
when debugCompiler:
|
||||
debugEcho &"new stackindex: {comp.stackIndex}, delta: {dStackIndex} due to {ch.repr}"
|
||||
comp.chunk.writeChunk(ch, comp.previous.line)
|
||||
|
||||
proc writePops(comp: Compiler, count: int) =
|
||||
if count > argMax:
|
||||
comp.error("Too many local variables in block.")
|
||||
if count == 0:
|
||||
return
|
||||
when debugCompiler:
|
||||
debugEcho &"Emitting {count}xPop."
|
||||
|
||||
if count == 1:
|
||||
comp.writeChunk(-1, opPop)
|
||||
elif count < shortArgMax:
|
||||
comp.writeChunk(-count, opPopSA)
|
||||
comp.writeChunk(0, count.uint8)
|
||||
else:
|
||||
comp.writeChunk(-count, opPopA)
|
||||
comp.writeChunk(0, count.toDU8())
|
||||
|
||||
|
||||
proc writeConstant(comp: Compiler, constant: KonValue) =
|
||||
comp.stackIndex.inc
|
||||
let index = comp.chunk.writeConstant(constant, comp.previous.line)
|
||||
|
@ -248,8 +266,7 @@ proc beginScope(comp: Compiler, function: bool = false) =
|
|||
|
||||
proc restore(comp: Compiler, scope: Scope) =
|
||||
let delta = comp.stackIndex - scope.goalStackIndex
|
||||
for i in countup(1, delta):
|
||||
comp.writeChunk(-1, opPop)
|
||||
comp.writePops(delta)
|
||||
when assertionsCompiler:
|
||||
if not comp.stackIndex == scope.goalStackIndex:
|
||||
comp.error("Assertion failed in restore")
|
||||
|
@ -257,15 +274,9 @@ proc restore(comp: Compiler, scope: Scope) =
|
|||
debugEcho &"Restored scope: delta {delta}"
|
||||
|
||||
proc restoreInFunct(comp: Compiler, scope: Scope) =
|
||||
when debugCompiler:
|
||||
var pops = 0
|
||||
while comp.stackIndex > 0:
|
||||
comp.writeChunk(-1, opPop)
|
||||
when debugCompiler:
|
||||
inc pops
|
||||
when assertionsCompiler:
|
||||
if not comp.stackIndex == 0:
|
||||
comp.error("Assertion failed in restoreInFunct")
|
||||
|
||||
let pops = comp.stackIndex
|
||||
comp.writePops(pops)
|
||||
|
||||
comp.stackIndex = scope.goalStackIndex
|
||||
when debugCompiler:
|
||||
|
@ -273,8 +284,7 @@ proc restoreInFunct(comp: Compiler, scope: Scope) =
|
|||
|
||||
proc jumpToEnd(comp: Compiler, scope: Scope) =
|
||||
let delta = comp.stackIndex - scope.goalStackIndex
|
||||
for i in countup(1, delta):
|
||||
comp.writeChunk(0, opPop)
|
||||
comp.writePops(delta)
|
||||
let jmp = comp.emitJump(0, opJump)
|
||||
scope.jumps.add(jmp)
|
||||
|
||||
|
|
15
vm.nim
15
vm.nim
|
@ -42,6 +42,10 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
template peek(stack: seq[KonValue]): KonValue =
|
||||
stack[stack.high]
|
||||
|
||||
proc popn(stack: var seq[KonValue], amt: int) {.inline.} =
|
||||
for i in countup(1, amt):
|
||||
discard stack.pop()
|
||||
|
||||
proc pushSafe(stack: var seq[KonValue], val: KonValue): bool =
|
||||
## returns if the value is not a runtime error
|
||||
## prints the error if it is a runtime error
|
||||
|
@ -53,6 +57,10 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
stack.add(val)
|
||||
true
|
||||
|
||||
proc readUI8(): int =
|
||||
result = ip[].int
|
||||
ip = ip.padd(1)
|
||||
|
||||
proc readDU8(): int =
|
||||
result = ip.DU8ptrToInt
|
||||
ip = ip.padd(argSize)
|
||||
|
@ -60,6 +68,7 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
proc readConstant(): KonValue =
|
||||
let index = readDU8()
|
||||
chunk.constants[index]
|
||||
|
||||
|
||||
template frameBottom: int = frames[frames.high].stackBottom
|
||||
while true:
|
||||
|
@ -88,6 +97,12 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
case ins:
|
||||
of opPop:
|
||||
discard stack.pop()
|
||||
of opPopA:
|
||||
let amt = readDU8()
|
||||
stack.popn(amt)
|
||||
of opPopSA:
|
||||
let amt = readUI8()
|
||||
stack.popn(amt)
|
||||
of opConstant:
|
||||
let val: KonValue = readConstant()
|
||||
stack.add(val)
|
||||
|
|
Loading…
Reference in New Issue