ARC: optimize complete object constructors to use nimNewObjUninit

This commit is contained in:
Araq
2020-01-26 10:50:21 +01:00
committed by Andreas Rumpf
parent ab35f07e77
commit a10cc18247
5 changed files with 40 additions and 12 deletions

View File

@@ -1001,6 +1001,8 @@ const
resultPos* = 7
dispatcherPos* = 8
nfAllFieldsSet* = nfBase2
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit, nkHiddenCallConv}
nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice,

View File

@@ -1197,7 +1197,7 @@ proc genDefault(p: BProc; n: PNode; d: var TLoc) =
if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
else: resetLoc(p, d)
proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope) =
proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
var sizeExpr = sizeExpr
let typ = a.t
var b: TLoc
@@ -1209,8 +1209,12 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope) =
sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
if optTinyRtti in p.config.globalOptions:
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
[getTypeDesc(p.module, typ), sizeExpr])
if needsInit:
b.r = ropecg(p.module, "($1) #nimNewObj($2)",
[getTypeDesc(p.module, typ), sizeExpr])
else:
b.r = ropecg(p.module, "($1) #nimNewObjUninit($2)",
[getTypeDesc(p.module, typ), sizeExpr])
genAssignment(p, a, b, {})
else:
let ti = genTypeInfo(p.module, typ, a.lode.info)
@@ -1254,9 +1258,9 @@ proc genNew(p: BProc, e: PNode) =
if e.len == 3:
var se: TLoc
initLocExpr(p, e[2], se)
rawGenNew(p, a, se.rdLoc)
rawGenNew(p, a, se.rdLoc, needsInit = true)
else:
rawGenNew(p, a, nil)
rawGenNew(p, a, nil, needsInit = true)
gcUsage(p.config, e)
proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
@@ -1356,7 +1360,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
getTemp(p, t, tmp)
r = rdLoc(tmp)
if isRef:
rawGenNew(p, tmp, nil)
rawGenNew(p, tmp, nil, needsInit = nfAllFieldsSet notin e.flags)
t = t.lastSon.skipTypes(abstractInstOwned)
r = "(*$1)" % [r]
gcUsage(p.config, e)
@@ -2180,7 +2184,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
if optTinyRtti in p.config.globalOptions:
var a: TLoc
initLocExpr(p, e[1], a)
rawGenNew(p, a, nil)
rawGenNew(p, a, nil, needsInit = true)
gcUsage(p.config, e)
else:
genNewFinalize(p, e)
@@ -2811,7 +2815,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
# else branch
selectedBranch = i
assert(selectedBranch >= 1)
result.add "{"
var countB = 0
let b = lastSon(obj[selectedBranch])
@@ -2822,10 +2826,10 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
result.add "}"
elif b.kind == nkSym:
result.add "." & mangleRecFieldName(p.module, b.sym) & " = "
result.add "." & mangleRecFieldName(p.module, b.sym) & " = "
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
result.add "}"
of nkSym:
if count > 0: result.add ", "
inc count

View File

@@ -485,7 +485,8 @@ proc cycleCheck(n: PNode; c: var Con) =
break
proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt, nkIfExpr, nkCaseStmt, nkWhen}:
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen}:
handleNested(n): p(node, c, mode)
elif mode == sinkArg:
if n.containsConstSeq:
@@ -493,7 +494,8 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
# sink parameter (bug #11524). Note that the string implementation is
# different and can deal with 'const string sunk into var'.
result = passCopyToSink(n, c)
elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure} + nkCallKinds + nkLiterals:
elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
nkCallKinds + nkLiterals:
result = p(n, c, consumed)
elif n.kind == nkSym and isSinkParam(n.sym):
# Sinked params can be consumed only once. We need to reset the memory

View File

@@ -388,3 +388,6 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
# 2) No such field exists in the constructed type
localError(c.config, field.info, errUndeclaredFieldX % id.s)
return
if initResult == initFull:
incl result.flags, nfAllFieldsSet

View File

@@ -72,6 +72,23 @@ proc nimNewObj(size: int): pointer {.compilerRtl.} =
when traceCollector:
cprintf("[Allocated] %p\n", result -! sizeof(RefHeader))
proc nimNewObjUninit(size: int): pointer {.compilerRtl.} =
# Same as 'newNewObj' but do not initialize the memory to zero.
# The codegen proved for us that this is not necessary.
let s = size + sizeof(RefHeader)
when defined(nimscript):
discard
elif defined(useMalloc):
var orig = cast[ptr RefHeader](c_malloc(cuint s))
elif compileOption("threads"):
var orig = cast[ptr RefHeader](allocShared(s))
else:
var orig = cast[ptr RefHeader](alloc(s))
orig.rc = 0
result = orig +! sizeof(RefHeader)
when traceCollector:
cprintf("[Allocated] %p\n", result -! sizeof(RefHeader))
proc nimDecWeakRef(p: pointer) {.compilerRtl, inl.} =
dec head(p).rc, rcIncrement