summary refs log tree commit diff stats
path: root/lib/system/arc.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/arc.nim')
-rw-r--r--lib/system/arc.nim28
1 files changed, 26 insertions, 2 deletions
diff --git a/lib/system/arc.nim b/lib/system/arc.nim
index d66f4b997..17142b277 100644
--- a/lib/system/arc.nim
+++ b/lib/system/arc.nim
@@ -227,10 +227,34 @@ template tearDownForeignThreadGc* =
   ## With `--gc:arc` a nop.
   discard
 
+type ObjCheckCache = array[0..1, PNimTypeV2]
+
+proc memcmp(str1, str2: cstring, n: csize_t): cint {.importc, header: "<string.h>".}
+
+func endsWith(s, suffix: cstring): bool {.inline.} =
+  let
+    sLen = s.len
+    suffixLen = suffix.len
+
+  if suffixLen <= sLen:
+    result = memcmp(cstring(addr s[sLen - suffixLen]), suffix, csize_t(suffixLen)) == 0
+
 proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
-  proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
+  result = endsWith(obj.name, subclass)
 
-  result = strstr(obj.name, subclass) != nil
+proc isObjSlowPath(obj: PNimTypeV2, subclass: cstring, cache: var ObjCheckCache): bool {.compilerRtl, inline.} =
+  if endsWith(obj.name, subclass):
+    cache[1] = obj
+    result = true
+  else:
+    cache[0] = obj
+    result = false
+
+proc isObjWithCache(obj: PNimTypeV2, subclass: cstring, cache: var ObjCheckCache): bool {.compilerRtl.} =
+  if cache[0] == obj: result = false
+  elif cache[1] == obj: result = true
+  else:
+    result = isObjSlowPath(obj, subclass, cache)
 
 proc chckObj(obj: PNimTypeV2, subclass: cstring) {.compilerRtl.} =
   # checks if obj is of type subclass: