implements display based subtype checking (6.4x faster without threads; 2.8x faster with threads) (#20781)

* WIP: fast 'of' operator based on the literature
* implement  display based subtype checking

Co-authored-by: Araq <rumpf_a@web.de>
This commit is contained in:
ringabout 2022-11-08 20:08:01 +08:00 • committed by GitHub
commit 7d15fdd375
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 52 deletions

View file

@ -1704,11 +1704,8 @@ proc genNewFinalize(p: BProc, e: PNode) =
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Rope) =
if optTinyRtti in p.config.globalOptions:
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])
appcg(p.module, result, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
let token = $genDisplayElem(MD5Digest(hashType(dest)))
appcg(p.module, result, "#isObjDisplayCheck($#.m_type, $#, $#)", [a, getObjDepth(dest), token])
else:
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
# have to call it here first:
@ -1722,10 +1719,6 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Ro
let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope
p.module.s[cfsVars].addf("static TNimType* $#[2];$n", [cache])
appcg(p.module, result, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache])
when false:
# former version:
appcg(p.module, result, "#isObj($1.m_type, $2)",
[a, genTypeInfoV1(p.module, dest, info)])
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
var a: TLoc
@ -2775,16 +2768,23 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
var nilCheck = ""
var r = newRopeAppender()
rdMType(p, a, nilCheck, r)
let checkFor = if optTinyRtti in p.config.globalOptions:
genTypeInfo2Name(p.module, dest)
else:
genTypeInfoV1(p.module, dest, n.info)
if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObj($2, $3)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor])
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(dest)
let token = $genDisplayElem(MD5Digest(hashType(dest)))
if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObjDisplayCheck($2, $3, $4)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor, token])
else:
linefmt(p, cpsStmts, "if (!#isObjDisplayCheck($1, $2, $3)){ #raiseObjectConversionError(); ",
[r, checkFor, token])
else:
linefmt(p, cpsStmts, "if (!#isObj($1, $2)){ #raiseObjectConversionError(); ",
[r, checkFor])
let checkFor = genTypeInfoV1(p.module, dest, n.info)
if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObj($2, $3)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor])
else:
linefmt(p, cpsStmts, "if (!#isObj($1, $2)){ #raiseObjectConversionError(); ",
[r, checkFor])
raiseInstr(p, p.s(cpsStmts))
linefmt p, cpsStmts, "}$n", []