summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-09-08 23:11:12 +0300
committerGitHub <noreply@github.com>2024-09-08 22:11:12 +0200
commitebcfd96ae1ba10cdf31cb3167a12d4d76d75a8c9 (patch)
tree536cedc8a81414d8b3bf65458f1df3475fe039fb
parentcd22560af5f13a7c024b97e2f3de2b1fe2439eb3 (diff)
downloadNim-ebcfd96ae1ba10cdf31cb3167a12d4d76d75a8c9.tar.gz
improve compiler performance on dot fields after #24005 (#24074)
I noticed after #24005 the auto-reported boot time in PRs increased from
around 8 seconds to 8.8 seconds, but I wasn't sure what could cause a
performance problem that made the compiler itself compile slower, most
of the changes were related to `static` which the compiler code doesn't
use too often. So I figured it was unrelated.

However there is still a performance problem with the changes to
`tryReadingGenericParam`. If an expression like `a.b` doesn't match any
of the default dot field behavior (for example, is actually a call
`b(a)`), the compiler does a final check to see if `b` is a generic
parameter of `a`. Since #24005, if the type of `a` is not
`tyGenericInst` or an old concept type, the compiler does a full
traversal of the type of `a` to see if it contains a generic type, only
then checking for `c.inGenericContext > 0` to not return `nil`. This
happens on *every* dot call.

Instead, we now check for `c.inGenericContext > 0` first, only then
checking if it contains a generic type, saving performance by virtue of
`c.inGenericContext > 0` being both cheap and less commonly true. The
`containsGenericType` could also be swapped out for more generic type
kind checks, but I think this is incorrect even if it might pass CI.
-rw-r--r--compiler/semexprs.nim9
1 files changed, 3 insertions, 6 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 737a846c0..081eb6847 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1504,12 +1504,9 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
       result.typ = makeTypeFromExpr(c, copyTree(result))
     else:
       result = nil
-  elif t.containsGenericType:
-    if c.inGenericContext > 0:
-      result = semGenericStmt(c, n)
-      result.typ = makeTypeFromExpr(c, copyTree(result))
-    else:
-      result = nil
+  elif c.inGenericContext > 0 and t.containsGenericType:
+    result = semGenericStmt(c, n)
+    result.typ = makeTypeFromExpr(c, copyTree(result))
   else:
     result = nil