diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2023-01-27 06:49:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-26 23:49:04 +0100 |
commit | 4647c7b59634e0d8bd24d815337e7a7a1f0830bd (patch) | |
tree | c15ac02375e826fee4f4b6031038ff7d42338285 | |
parent | fc068ee06d058b35d2d5890cf1fa3c356e549d1f (diff) | |
download | Nim-4647c7b59634e0d8bd24d815337e7a7a1f0830bd.tar.gz |
fixes #14409; fixes #10674 VM callbacks switch to table-index seqs (#21297)
* fixes #14409; fixes#10674 VM callbacks switch to table-index seqs * fixes package name * reduce runtime cost
-rw-r--r-- | compiler/vm.nim | 4 | ||||
-rw-r--r-- | compiler/vmdef.nim | 18 | ||||
-rw-r--r-- | compiler/vmgen.nim | 34 | ||||
-rw-r--r-- | compiler/vmops.nim | 2 | ||||
-rw-r--r-- | tests/compilerapi/tcompilerapi.nim | 2 |
5 files changed, 37 insertions, 23 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index c6ca228ff..4f5f8485b 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1351,7 +1351,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let prc = if not isClosure: bb.sym else: bb[0].sym if prc.offset < -1: # it's a callback: - c.callbacks[-prc.offset-2].value( + c.callbacks[-prc.offset-2]( VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[ptr UncheckedArray[TFullReg]](addr regs[0]), currentException: c.currentExceptionA, currentLineInfo: c.debug[pc]) @@ -1674,7 +1674,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = rb = instr.regB rc = instr.regC idx = int(regs[rb+rc-1].intVal) - callback = c.callbacks[idx].value + callback = c.callbacks[idx] args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[ptr UncheckedArray[TFullReg]](addr regs[0]), currentException: c.currentExceptionA, currentLineInfo: c.debug[pc]) diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 0af15e5c9..f369908ba 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -10,7 +10,7 @@ ## This module contains the type definitions for the new evaluation engine. ## An instruction is 1-3 int32s in memory, it is a register based VM. -import tables +import std/[tables, strutils] import ast, idents, options, modulegraphs, lineinfos @@ -259,7 +259,8 @@ type traceActive*: bool loopIterations*: int comesFromHeuristic*: TLineInfo # Heuristic for better macro stack traces - callbacks*: seq[tuple[key: string, value: VmCallback]] + callbacks*: seq[VmCallback] + callbackIndex*: Table[string, int] errorFlag*: string cache*: IdentCache config*: ConfigRef @@ -292,7 +293,7 @@ proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM, - comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "", + comesFromHeuristic: unknownLineInfo, callbacks: @[], callbackIndex: initTable[string, int](), errorFlag: "", cache: cache, config: g.config, graph: g, idgen: idgen) proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) = @@ -301,9 +302,18 @@ proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) = c.loopIterations = c.config.maxLoopIterationsVM c.idgen = idgen +proc reverseName(s: string): string = + result = newStringOfCap(s.len) + let y = s.split('.') + for i in 1..y.len: + result.add y[^i] + if i != y.len: + result.add '.' + proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = result = c.callbacks.len - c.callbacks.add((name, callback)) + c.callbacks.add(callback) + c.callbackIndex[reverseName(name)] = result const firstABxInstr* = opcTJmp diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index ba3a05481..bca961a63 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -2011,25 +2011,29 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) = proc genProc*(c: PCtx; s: PSym): int -proc matches(s: PSym; x: string): bool = - let y = x.split('.') +proc toKey(s: PSym): string = var s = s - for i in 1..y.len: - if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"): - return false - s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner - while s != nil and s.kind == skPackage and s.owner != nil: s = s.owner - result = true + while s != nil: + result.add s.name.s + if s.owner != nil: + if sfFromGeneric in s.flags: + s = s.owner.owner + else: + s = s.owner + result.add "." + else: + break proc procIsCallback(c: PCtx; s: PSym): bool = if s.offset < -1: return true - var i = -2 - for key, value in items(c.callbacks): - if s.matches(key): - doAssert s.offset == -1 - s.offset = i - return true - dec i + let key = toKey(s) + if c.callbackIndex.contains(key): + let index = c.callbackIndex[key] + doAssert s.offset == -1 + s.offset = -2 - index + result = true + else: + result = false proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = when defined(nimCompilerStacktraceHints): diff --git a/compiler/vmops.nim b/compiler/vmops.nim index 2b5b2c938..f1a2e1e69 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -256,7 +256,7 @@ proc registerAdditionalOps*(c: PCtx) = wrap2si(readLines, ioop) systemop getCurrentExceptionMsg systemop getCurrentException - registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} = + registerCallback c, "stdlib.osdirs.staticWalkDir", proc (a: VmArgs) {.nimcall.} = setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1))) registerCallback c, "stdlib.compilesettings.querySetting", proc (a: VmArgs) = setResult(a, querySettingImpl(c.config, getInt(a, 0))) diff --git a/tests/compilerapi/tcompilerapi.nim b/tests/compilerapi/tcompilerapi.nim index ab995cb6d..828dcd0d9 100644 --- a/tests/compilerapi/tcompilerapi.nim +++ b/tests/compilerapi/tcompilerapi.nim @@ -23,7 +23,7 @@ proc initInterpreter(script: string): Interpreter = proc main() = let i = initInterpreter("myscript.nim") - i.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) = + i.implementRoutine("nim", "exposed", "addFloats", proc (a: VmArgs) = setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2)) ) i.evalScript() |