replaced seq with a custom stack object for performance

This commit is contained in:
prod2 2022-01-27 18:54:02 +01:00
parent 01de21e32e
commit 90d04f13f6
4 changed files with 101 additions and 13 deletions

View File

@ -5,5 +5,8 @@ template padd*[T](x: ptr T, num: int): ptr T =
template psub*[T](x: ptr T, num: int): ptr T =
cast[ptr T](cast[int](x) - num)
template pdiff*[T](x: ptr T, y: ptr): int =
cast[int](x) - cast[int](y)
template pdiff*[T](x: ptr T, y: ptr T): int =
cast[int](x) - cast[int](y)
template pless*[T](x: ptr T, y: ptr T): bool =
cast[uint](x) < cast[uint](y)

View File

@ -178,13 +178,10 @@ proc scanToken*(scanner: Scanner): Token =
of '*': return scanner.makeToken(tkStar)
of '!':
return if scanner.match('='): scanner.makeToken(tkBangEqual) else: scanner.makeToken(tkBang)
of '=':
return if scanner.match('='): scanner.makeToken(tkEqualEqual) else: scanner.makeToken(tkEqual)
of '<':
return if scanner.match('='): scanner.makeToken(tkLessEqual) else: scanner.makeToken(tkLess)
of '>':
return if scanner.match('='): scanner.makeToken(tkGreaterEqual) else: scanner.makeToken(tkGreater)
of '\"':

84
types/stack.nim Normal file
View File

@ -0,0 +1,84 @@
import ../pointerutils
# configure stacks here
const boundsChecks = false
const growthFactor = 2
type
Stack*[T] = object
top: ptr T
start: ptr T
cap: int
proc newStack*[T](startingCap: int): Stack[T] =
result.start = cast[ptr T](alloc(startingCap * sizeof(T)))
result.top = result.start.psub(sizeof(T))
result.cap = startingCap
proc destroyStack*[T](stack: var Stack[T]) =
## dealloc's the stack object
## if the stack contains pointers, those should be freed before destroying the stack
stack.cap = 0
stack.start.dealloc()
stack.start = nil
stack.top = nil
proc grow[T](stack: var Stack[T], len: int) {.inline.} =
## growth the stack's capacity and increments the top's index by one
stack.start = cast[ptr T](realloc(stack.start, stack.cap * growthFactor))
stack.cap *= growthFactor
stack.top = stack.start.padd(len * sizeof(T))
proc shrink[T](stack: var Stack[T]) {.inline.} =
discard
template high*[T](stack: Stack[T]): int =
stack.top.pdiff(stack.start) div sizeof(T)
template len*[T](stack: Stack[T]): int =
stack.high() + 1
proc push*[T](stack: var Stack[T], item: T) {.inline.} =
let len = stack.len()
if len == stack.cap:
stack.grow(len)
else:
stack.top = stack.top.padd(sizeof(T))
stack.top[]= item
template add*[T](stack: var Stack[T], item: T) =
stack.push(item)
proc pop*[T](stack: var Stack[T]): T {.inline.} =
when boundsChecks:
if stack.top == nil or stack.top.pless(stack.start):
raise newException(Defect, "Stacktop is nil or smaller than start.")
result = stack.top[]
stack.top = stack.top.psub(sizeof(T))
proc peek*[T](stack: Stack[T]): var T {.inline.} =
stack.top[]
proc deleteTopN*[T](stack: var Stack[T], n: Natural) =
stack.top = stack.top.psub(sizeof(T) * n)
when boundsChecks:
if stack.top.pless(stack.start):
raise newException(Defect, "Stacktop sunk below the start after a deleteTopN.")
proc getIndex*[T](stack: Stack[T], index: int): T =
when boundsChecks:
if index < 0 or index >= stack.len():
raise newException(Defect, "Attempt to getIndex with an index out of bounds.")
stack.start.padd(index * sizeof(T))[]
template `[]`*[T](stack: Stack[T], index: int): T =
stack.getIndex(index)
proc setIndex*[T](stack: var Stack[T], index: int, item: T) =
when boundsChecks:
if index < 0 or index >= stack.len():
raise newException(Defect, "Attempt to getIndex with an index out of bounds.")
stack.start.padd(index * sizeof(T))[]= item
template `[]=`*[T](stack: var Stack[T], index: int, item: T) =
stack.setIndex(index, item)

20
vm.nim
View File

@ -6,6 +6,8 @@ import chunk
import config
import pointerutils
import types/stack
when profileInstructions:
import times
import std/monotimes
@ -28,7 +30,8 @@ proc run*(chunk: Chunk): InterpretResult =
var
ip: ptr uint8 = chunk.code[0].unsafeAddr
stack: seq[NdValue] = newSeqOfCap[NdValue](256)
#stack: seq[NdValue] = newSeqOfCap[NdValue](256)
stack: Stack[NdValue] = newStack[NdValue](256)
hadError: bool
globals: Table[string, NdValue]
frames: seq[Frame] = newSeqOfCap[Frame](4)
@ -39,12 +42,14 @@ proc run*(chunk: Chunk): InterpretResult =
write stderr, &"[line: {line}] {msg}\n"
hadError = true
template peek(stack: seq[NdValue]): NdValue =
stack[stack.high]
#template peek(stack: seq[NdValue]): NdValue =
# stack[stack.high]
proc popn(stack: var seq[NdValue], amt: int) {.inline.} =
for i in countup(1, amt):
discard stack.pop()
#proc popn(stack: var seq[NdValue], amt: int) {.inline.} =
# for i in countup(1, amt):
# discard stack.pop()
template popn(stack: var Stack[NdValue], amt: int) =
stack.deleteTopN(amt)
proc readUI8(): int =
result = ip[].int
@ -58,7 +63,6 @@ proc run*(chunk: Chunk): InterpretResult =
let index = readDU8()
chunk.constants[index]
template frameBottom: int = frames[frames.high].stackBottom
while true:
@ -72,7 +76,7 @@ proc run*(chunk: Chunk): InterpretResult =
let opname = ($ins)
var msg = &"[{ii:4}] {opname}"
msg &= " Stack: [ "
for i in 0 .. stack.high:
for i in 0 .. stack.high():
let e = stack[i]
if i == frameBottom:
msg &= &"<{e}> "