summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-01-27 06:49:04 +0800
committerGitHub <noreply@github.com>2023-01-26 23:49:04 +0100
commit4647c7b59634e0d8bd24d815337e7a7a1f0830bd (patch)
treec15ac02375e826fee4f4b6031038ff7d42338285
parentfc068ee06d058b35d2d5890cf1fa3c356e549d1f (diff)
downloadNim-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.nim4
-rw-r--r--compiler/vmdef.nim18
-rw-r--r--compiler/vmgen.nim34
-rw-r--r--compiler/vmops.nim2
-rw-r--r--tests/compilerapi/tcompilerapi.nim2
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()