optimized method dispatchers
This commit is contained in:
parent
9354b8a9d7
commit
15909c7be2
7 changed files with 49 additions and 5 deletions
|
|
@ -510,6 +510,7 @@ const
|
||||||
tfUncheckedArray* = tfVarargs
|
tfUncheckedArray* = tfVarargs
|
||||||
tfUnion* = tfNoSideEffect
|
tfUnion* = tfNoSideEffect
|
||||||
tfGcSafe* = tfThread
|
tfGcSafe* = tfThread
|
||||||
|
tfObjHasKids* = tfEnumHasHoles
|
||||||
skError* = skUnknown
|
skError* = skUnknown
|
||||||
|
|
||||||
# type flags that are essential for type equality:
|
# type flags that are essential for type equality:
|
||||||
|
|
|
||||||
|
|
@ -1144,6 +1144,24 @@ proc genNewFinalize(p: BProc, e: PNode) =
|
||||||
genObjectInit(p, cpsStmts, bt, a, false)
|
genObjectInit(p, cpsStmts, bt, a, false)
|
||||||
gcUsage(e)
|
gcUsage(e)
|
||||||
|
|
||||||
|
proc genOfHelper(p: BProc; dest: PType; a: PRope): PRope =
|
||||||
|
# unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we
|
||||||
|
# have to call it here first:
|
||||||
|
let ti = genTypeInfo(p.module, dest)
|
||||||
|
if tfFinal in dest.flags or (p.module.objHasKidsValid and
|
||||||
|
tfObjHasKids notin dest.flags):
|
||||||
|
result = ropef("$1.m_type == $2", a, ti)
|
||||||
|
else:
|
||||||
|
discard cgsym(p.module, "TNimType")
|
||||||
|
inc p.module.labels
|
||||||
|
let cache = con("Nim_OfCheck_CACHE", p.module.labels.toRope)
|
||||||
|
appf(p.module.s[cfsVars], "static TNimType* $#[2];$n", cache)
|
||||||
|
result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache)
|
||||||
|
when false:
|
||||||
|
# former version:
|
||||||
|
result = rfmt(p.module, "#isObj($1.m_type, $2)",
|
||||||
|
a, genTypeInfo(p.module, dest))
|
||||||
|
|
||||||
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, x, a)
|
initLocExpr(p, x, a)
|
||||||
|
|
@ -1163,11 +1181,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
|
||||||
globalError(x.info, errGenerated,
|
globalError(x.info, errGenerated,
|
||||||
"no 'of' operator available for pure objects")
|
"no 'of' operator available for pure objects")
|
||||||
if nilCheck != nil:
|
if nilCheck != nil:
|
||||||
r = rfmt(p.module, "(($1) && #isObj($2.m_type, $3))",
|
r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r))
|
||||||
nilCheck, r, genTypeInfo(p.module, dest))
|
|
||||||
else:
|
else:
|
||||||
r = rfmt(p.module, "#isObj($1.m_type, $2)",
|
r = rfmt(p.module, "($1)", genOfHelper(p, dest, r))
|
||||||
r, genTypeInfo(p.module, dest))
|
|
||||||
putIntoDest(p, d, getSysType(tyBool), r)
|
putIntoDest(p, d, getSysType(tyBool), r)
|
||||||
|
|
||||||
proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
proc genOf(p: BProc, n: PNode, d: var TLoc) =
|
||||||
|
|
|
||||||
|
|
@ -796,6 +796,10 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
var tmp = getNimNode(m)
|
var tmp = getNimNode(m)
|
||||||
genObjectFields(m, typ, typ.n, tmp)
|
genObjectFields(m, typ, typ.n, tmp)
|
||||||
appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
|
appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
|
||||||
|
var t = typ.sons[0]
|
||||||
|
while t != nil:
|
||||||
|
t.skipTypes(abstractInst).flags.incl tfObjHasKids
|
||||||
|
t = t.sons[0]
|
||||||
|
|
||||||
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
proc genTupleInfo(m: BModule, typ: PType, name: PRope) =
|
||||||
genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
genTypeInfoAuxBase(m, typ, name, toRope("0"))
|
||||||
|
|
|
||||||
|
|
@ -1383,6 +1383,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
||||||
registerModuleToMain(m.module)
|
registerModuleToMain(m.module)
|
||||||
|
|
||||||
if sfMainModule in m.module.flags:
|
if sfMainModule in m.module.flags:
|
||||||
|
m.objHasKidsValid = true
|
||||||
var disp = generateMethodDispatchers()
|
var disp = generateMethodDispatchers()
|
||||||
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
|
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
|
||||||
genMainProc(m)
|
genMainProc(m)
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ type
|
||||||
# a frame var twice in an init proc
|
# a frame var twice in an init proc
|
||||||
isHeaderFile*: bool # C source file is the header file
|
isHeaderFile*: bool # C source file is the header file
|
||||||
includesStringh*: bool # C source file already includes ``<string.h>``
|
includesStringh*: bool # C source file already includes ``<string.h>``
|
||||||
|
objHasKidsValid*: bool # whether we can rely on tfObjHasKids
|
||||||
cfilename*: string # filename of the module (including path,
|
cfilename*: string # filename of the module (including path,
|
||||||
# without extension)
|
# without extension)
|
||||||
typeCache*: TIdTable # cache the generated types
|
typeCache*: TIdTable # cache the generated types
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,28 @@ proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||||
if a != b:
|
if a != b:
|
||||||
sysFatal(EInvalidObjectAssignment, "invalid object assignment")
|
sysFatal(EInvalidObjectAssignment, "invalid object assignment")
|
||||||
|
|
||||||
|
type ObjCheckCache = array[0..1, PNimType]
|
||||||
|
|
||||||
|
proc isObjSlowPath(obj, subclass: PNimType;
|
||||||
|
cache: var ObjCheckCache): bool {.noinline.} =
|
||||||
|
# checks if obj is of type subclass:
|
||||||
|
var x = obj.base
|
||||||
|
while x != subclass:
|
||||||
|
if x == nil:
|
||||||
|
cache[0] = obj
|
||||||
|
return false
|
||||||
|
x = x.base
|
||||||
|
cache[1] = obj
|
||||||
|
return true
|
||||||
|
|
||||||
|
proc isObjWithCache(obj, subclass: PNimType;
|
||||||
|
cache: var ObjCheckCache): bool {.compilerProc, inline.} =
|
||||||
|
if obj == subclass: return true
|
||||||
|
if obj.base == subclass: return true
|
||||||
|
if cache[0] == obj: return false
|
||||||
|
if cache[1] == obj: return true
|
||||||
|
return isObjSlowPath(obj, subclass, cache)
|
||||||
|
|
||||||
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
|
||||||
# checks if obj is of type subclass:
|
# checks if obj is of type subclass:
|
||||||
var x = obj
|
var x = obj
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -138,7 +138,6 @@ Not essential for 1.0.0
|
||||||
- implement the "snoopResult" pragma; no, make a strutils with string append
|
- implement the "snoopResult" pragma; no, make a strutils with string append
|
||||||
semantics instead ...
|
semantics instead ...
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
- optimize method dispatchers
|
|
||||||
- new feature: ``distinct T with operations``
|
- new feature: ``distinct T with operations``
|
||||||
- arglist as a type (iterator chaining); variable length type lists for generics
|
- arglist as a type (iterator chaining); variable length type lists for generics
|
||||||
- implement marker procs for message passing
|
- implement marker procs for message passing
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue