summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2020-01-26 10:50:21 +0100
committerAndreas Rumpf <rumpf_a@web.de>2020-01-26 13:43:02 +0100
commita10cc18247cb576aa409e9056ed99f23539d14f9 (patch)
tree8ad1a8ac55ccb34b9438bbfb57476fcad01d7261 /compiler
parentab35f07e774c3faaee3708479523e66614eb3aa6 (diff)
downloadNim-a10cc18247cb576aa409e9056ed99f23539d14f9.tar.gz
ARC: optimize complete object constructors to use nimNewObjUninit
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/ccgexprs.nim24
-rw-r--r--compiler/injectdestructors.nim6
-rw-r--r--compiler/semobjconstr.nim3
4 files changed, 23 insertions, 12 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 733f60090..3d05fd2ca 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1001,6 +1001,8 @@ const
   resultPos* = 7
   dispatcherPos* = 8
 
+  nfAllFieldsSet* = nfBase2
+
   nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
                   nkCommand, nkCallStrLit, nkHiddenCallConv}
   nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice,
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index c23b64257..84d491cf4 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -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
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index 27171ced6..dc431ef38 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -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
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index 0ddec1706..489bc6684 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -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