summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim7
-rw-r--r--lib/system/arc.nim28
-rw-r--r--tests/metatype/ttypedesc3.nim3
-rw-r--r--tests/method/tgeneric_methods.nim1
-rw-r--r--tests/method/tmethod_issues.nim1
-rw-r--r--tests/method/tmethod_various.nim1
-rw-r--r--tests/method/tsingle_methods.nim2
-rw-r--r--tests/misc/parsecomb.nim4
-rw-r--r--tests/pragmas/tlocks.nim3
9 files changed, 44 insertions, 6 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 5a58b4bcd..8e7a21c67 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1615,8 +1615,11 @@ proc genNewFinalize(p: BProc, e: PNode) =
 
 proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope =
   if optTinyRtti in p.config.globalOptions:
-    result = ropecg(p.module, "#isObj($1.m_type, $2)",
-      [a, genTypeInfo2Name(p.module, dest)])
+    let ti = genTypeInfo2Name(p.module, dest)
+    inc p.module.labels
+    let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
+    p.module.s[cfsVars].addf("static TNimTypeV2* $#[2];$n", [cache])
+    result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
   else:
     # unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
     # have to call it here first:
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:
diff --git a/tests/metatype/ttypedesc3.nim b/tests/metatype/ttypedesc3.nim
index 98a59f613..d3a58853d 100644
--- a/tests/metatype/ttypedesc3.nim
+++ b/tests/metatype/ttypedesc3.nim
@@ -1,5 +1,6 @@
 discard """
-output: '''
+  matrix: "--mm:arc; --mm:refc"
+  output: '''
 proc Base
 proc Child
 method Base
diff --git a/tests/method/tgeneric_methods.nim b/tests/method/tgeneric_methods.nim
index 0e2aeeede..ab92c66d8 100644
--- a/tests/method/tgeneric_methods.nim
+++ b/tests/method/tgeneric_methods.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:arc; --mm:refc"
   output: '''wow2
 X 1
 X 3'''
diff --git a/tests/method/tmethod_issues.nim b/tests/method/tmethod_issues.nim
index df4c3771a..13467f2b3 100644
--- a/tests/method/tmethod_issues.nim
+++ b/tests/method/tmethod_issues.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:arc; --mm:refc"
   output: '''
 wof!
 wof!
diff --git a/tests/method/tmethod_various.nim b/tests/method/tmethod_various.nim
index fd022717b..f9d067a72 100644
--- a/tests/method/tmethod_various.nim
+++ b/tests/method/tmethod_various.nim
@@ -1,4 +1,5 @@
 discard """
+  matrix: "--mm:arc; --mm:refc"
   output: '''
 do nothing
 HELLO WORLD!
diff --git a/tests/method/tsingle_methods.nim b/tests/method/tsingle_methods.nim
index 40269559a..b564e7d87 100644
--- a/tests/method/tsingle_methods.nim
+++ b/tests/method/tsingle_methods.nim
@@ -1,5 +1,5 @@
 discard """
-  cmd: "nim c --multimethods:off $file"
+  matrix: "--mm:arc --multimethods:off; --mm:refc --multimethods:off"
   output: '''base
 base
 base
diff --git a/tests/misc/parsecomb.nim b/tests/misc/parsecomb.nim
index 4ff2f65d2..4f149cbf6 100644
--- a/tests/misc/parsecomb.nim
+++ b/tests/misc/parsecomb.nim
@@ -1,3 +1,7 @@
+discard """
+  matrix: "--mm:arc; --mm:refc"
+"""
+
 type Input[T] = object
   toks: seq[T]
   index: int
diff --git a/tests/pragmas/tlocks.nim b/tests/pragmas/tlocks.nim
index ba66a2dca..6c2a9f9e9 100644
--- a/tests/pragmas/tlocks.nim
+++ b/tests/pragmas/tlocks.nim
@@ -1,3 +1,6 @@
+discard """
+  matrix: "--mm:arc; --mm:refc"
+"""
 
 type SomeBase* = ref object of RootObj
 type SomeDerived* = ref object of SomeBase