profiling opcodes

This commit is contained in:
prod2 2022-01-22 17:28:53 +01:00
parent ab64d31271
commit 5b23d27c0a
5 changed files with 34 additions and 7 deletions

View File

@ -632,7 +632,7 @@ proc parseFunct(comp: Compiler) =
dec comp.stackIndex # the previous end scope did not put anything on the stack, it is jumped over
# get konvalue functions:
let konFunct = newKonFunction(comp.chunk.name, functII, params.len)
let konFunct = newKonFunction(functII, params.len)
# end of function declaration:
comp.patchJump(jumpOverBody)

View File

@ -10,6 +10,7 @@ const debugCompiler* = false
const debugDumpChunk* = false
const assertionsVM* = false # sanity checks in the VM, such as the stack being empty at the end
const assertionsCompiler* = false # sanity checks in the compiler
const profileInstructions* = false # if true, the time spent on every opcode is measured
# choose a line editor for the repl
const lineEditor = leRdstdin

View File

@ -37,8 +37,13 @@ proc runFile(path: string) =
of rsOK:
quit 0
const hardcodedPath* = ""
if paramCount() == 0:
repl()
if hardcodedPath == "":
repl()
else:
runFile(hardcodedPath)
elif paramCount() == 1:
runFile(paramStr(1))
else:

View File

@ -20,7 +20,6 @@ type
of ktString:
stringValue*: string
of ktFunct:
module*: string # which chunk the function is compiled in
entryII*: int # entry instruction index
arity*: int # number of arguments
of errorTypes:
@ -39,7 +38,7 @@ proc `$`*(val: KonValue): string =
of ktString:
return val.stringValue
of ktFunct:
return &"Function object: {val.module}/{val.entryII}"
return &"Function object: {val.entryII}"
of errorTypes:
let ename = $val.konType
return &"{ename[2..^1]}: {val.message}"
@ -67,7 +66,7 @@ proc equal*(val, right: KonValue): bool =
of ktString:
val.stringValue == right.stringValue
of ktFunct:
val.module == right.module and val.entryII == right.entryII
val.entryII == right.entryII
# same entry II/module but diff arity is a bug
of errorTypes:
false # error comparison is undefined
@ -83,8 +82,8 @@ proc toKonValue*(val: bool): KonValue =
proc toKonValue*(val: string): KonValue =
KonValue(konType: ktString, stringValue: val)
proc newKonFunction*(module: string, ii: int, arity: int): KonValue =
KonValue(konType: ktFunct, module: module, entryII: ii, arity: arity)
proc newKonFunction*(ii: int, arity: int): KonValue =
KonValue(konType: ktFunct, entryII: ii, arity: arity)
proc toKonValue*: KonValue =
KonValue(konType: ktNil)

22
vm.nim
View File

@ -5,6 +5,9 @@ import value
import chunk
import config
import pointerutils
when profileInstructions:
import times
import std/monotimes
type
Frame = object
@ -78,6 +81,12 @@ proc binary(op: OpCode, left: KonValue, right: KonValue): KonValue =
else:
discard #unreachable
when profileInstructions:
# not a perfect profiling approach, doing random stacktrace dumps
# x amount of times per second to get the current source line
# would be better
var durations: array[OpCode, Duration]
proc run*(vm: VM): InterpretResult =
template frameBottom: int = vm.frames[vm.frames.high].stackBottom
@ -98,6 +107,10 @@ proc run*(vm: VM): InterpretResult =
msg &= &"{e} "
msg &= "]"
echo msg
when profileInstructions:
let startTime = getMonoTime()
case ins:
of opPop:
discard vm.pop()
@ -200,9 +213,18 @@ proc run*(vm: VM): InterpretResult =
vm.ip = vm.chunk.code[0].unsafeAddr.padd(funct.entryII) # jump to the entry point
when profileInstructions:
durations[ins] += getMonoTime() - startTime
when assertionsVM:
if not vm.hadError and vm.stack.len > 0:
vm.runtimeError(&"VM Assertion failed: stack is of non-zero length {vm.stack.len} after execution has finished.")
when profileInstructions:
for op in OpCode:
let dur = durations[op].inMilliseconds
echo &"OpCode: {op} total duration {dur} ms"
if vm.hadError:
irRuntimeError
else: