fixes #18612; apply cache and memcmp for methods in arc/orc (#19749)

* try using endsWith

* use memcmp

* add cache

* cleanup

* better

* minor

* fix

* improve test coverage for methods with ARC

(cherry picked from commit 8bfc396a4d)
This commit is contained in:
flywind
2022-04-27 02:14:39 +08:00
committed by narimiran
parent 0e5bf5953e
commit 1788b8b991
9 changed files with 45 additions and 7 deletions

View File

@@ -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:

View File

@@ -227,10 +227,34 @@ template tearDownForeignThreadGc* =
## With `--gc:arc` a nop.
discard
proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
type ObjCheckCache = array[0..1, PNimTypeV2]
result = strstr(obj.name, subclass) != nil
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.} =
result = endsWith(obj.name, subclass)
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:

View File

@@ -1,5 +1,6 @@
discard """
output: '''
matrix: "--mm:arc; --mm:refc"
output: '''
proc Base
proc Child
method Base

View File

@@ -1,4 +1,5 @@
discard """
matrix: "--mm:arc; --mm:refc"
output: '''wow2
X 1
X 3'''

View File

@@ -1,4 +1,5 @@
discard """
matrix: "--mm:arc; --mm:refc"
output: '''
wof!
wof!

View File

@@ -1,4 +1,5 @@
discard """
matrix: "--mm:arc; --mm:refc"
output: '''
do nothing
HELLO WORLD!

View File

@@ -1,5 +1,5 @@
discard """
cmd: "nim c --multimethods:off $file"
matrix: "--mm:arc --multimethods:off; --mm:refc --multimethods:off"
output: '''base
base
base

View File

@@ -1,3 +1,7 @@
discard """
matrix: "--mm:arc; --mm:refc"
"""
type Input[T] = object
toks: seq[T]
index: int

View File

@@ -1,3 +1,6 @@
discard """
matrix: "--mm:arc; --mm:refc"
"""
type SomeBase* = ref object of RootObj
type SomeDerived* = ref object of SomeBase