mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 23:03:36 +00:00
ARC: optimize complete object constructors to use nimNewObjUninit
This commit is contained in:
@@ -1001,6 +1001,8 @@ const
|
||||
resultPos* = 7
|
||||
dispatcherPos* = 8
|
||||
|
||||
nfAllFieldsSet* = nfBase2
|
||||
|
||||
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
||||
nkCommand, nkCallStrLit, nkHiddenCallConv}
|
||||
nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user