summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/ccgexprs.nim161
-rwxr-xr-xlib/system/gc.nim1
-rwxr-xr-xtodo.txt4
3 files changed, 89 insertions, 77 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index dc2b5857a..eb4c9a271 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -899,25 +899,96 @@ proc genNew(p: BProc, e: PNode) =
   refType = skipTypes(e.sons[1].typ, abstractVarRange)
   InitLocExpr(p, e.sons[1], a)
   initLoc(b, locExpr, a.t, OnHeap)
-  b.r = ropecg(p.module,
-      "($1) #newObj($2, sizeof($3))", [getTypeDesc(p.module, reftype),
-      genTypeInfo(p.module, refType),
-      getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
-  genAssignment(p, a, b, {needToKeepAlive})  # set the object type:
+  let args = [getTypeDesc(p.module, reftype),
+              genTypeInfo(p.module, refType),
+              getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]
+  if a.s == OnHeap and optRefcGc in gGlobalOptions:
+    # use newObjRC1 as an optimization; and we don't need 'keepAlive' either
+    appcg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc)
+    b.r = ropecg(p.module, "($1) #newObjRC1($2, sizeof($3))", args)
+    appcg(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc)
+  else:
+    b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", args)
+    genAssignment(p, a, b, {needToKeepAlive})  # set the object type:
   bt = skipTypes(refType.sons[0], abstractRange)
   genObjectInit(p, cpsStmts, bt, a, false)
 
+proc genNewSeqAux(p: BProc, dest: TLoc, length: PRope) =
+  let seqtype = skipTypes(dest.t, abstractVarRange)
+  let args = [getTypeDesc(p.module, seqtype),
+              genTypeInfo(p.module, seqType), length]
+  var call: TLoc
+  initLoc(call, locExpr, dest.t, OnHeap)
+  if dest.s == OnHeap and optRefcGc in gGlobalOptions:
+    appcg(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc)
+    call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args)
+    appcg(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc)
+  else:
+    call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args)
+    genAssignment(p, dest, call, {needToKeepAlive})
+  
 proc genNewSeq(p: BProc, e: PNode) =
-  var
-    a, b, c: TLoc
-  var seqType = skipTypes(e.sons[1].typ, abstractVarRange)
+  var a, b: TLoc
   InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  initLoc(c, locExpr, a.t, OnHeap)
-  c.r = ropecg(p.module, "($1) #newSeq($2, $3)", [
-               getTypeDesc(p.module, seqtype),
-               genTypeInfo(p.module, seqType), rdLoc(b)])
-  genAssignment(p, a, c, {needToKeepAlive})
+  genNewSeqAux(p, a, b.rdLoc)
+  
+proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
+  var arr: TLoc
+  if d.k == locNone:
+    getTemp(p, t.typ, d)
+  # generate call to newSeq before adding the elements per hand:
+  genNewSeqAux(p, d, intLiteral(sonsLen(t)))
+  for i in countup(0, sonsLen(t) - 1):
+    initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
+    arr.r = ropef("$1->data[$2]", [rdLoc(d), intLiteral(i)])
+    arr.s = OnHeap            # we know that sequences are on the heap
+    expr(p, t.sons[i], arr)
+
+proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
+  var elem, a, arr: TLoc
+  if t.kind == nkBracket:
+    t.sons[1].typ = t.typ
+    genSeqConstr(p, t.sons[1], d)
+    return
+  if d.k == locNone:
+    getTemp(p, t.typ, d)
+  # generate call to newSeq before adding the elements per hand:
+  var L = int(lengthOrd(t.sons[1].typ))
+  
+  genNewSeqAux(p, d, intLiteral(L))
+  initLocExpr(p, t.sons[1], a)
+  for i in countup(0, L - 1):
+    initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
+    elem.r = ropef("$1->data[$2]", [rdLoc(d), intLiteral(i)])
+    elem.s = OnHeap # we know that sequences are on the heap
+    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s)
+    arr.r = ropef("$1[$2]", [rdLoc(a), intLiteral(i)])
+    genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
+  
+proc genNewFinalize(p: BProc, e: PNode) =
+  var
+    a, b, f: TLoc
+    refType, bt: PType
+    ti: PRope
+    oldModule: BModule
+  refType = skipTypes(e.sons[1].typ, abstractVarRange)
+  InitLocExpr(p, e.sons[1], a)
+  # This is a little hack:
+  # XXX this is also a bug, if the finalizer expression produces side-effects
+  oldModule = p.module
+  p.module = gNimDat
+  InitLocExpr(p, e.sons[2], f)
+  p.module = oldModule
+  initLoc(b, locExpr, a.t, OnHeap)
+  ti = genTypeInfo(p.module, refType)
+  appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
+  b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
+      getTypeDesc(p.module, refType),
+      ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
+  genAssignment(p, a, b, {needToKeepAlive})  # set the object type:
+  bt = skipTypes(refType.sons[0], abstractRange)
+  genObjectInit(p, cpsStmts, bt, a, false)
 
 proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   var a: TLoc
@@ -945,30 +1016,6 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
 proc genOf(p: BProc, n: PNode, d: var TLoc) =
   genOf(p, n.sons[1], n.sons[2].typ, d)
 
-proc genNewFinalize(p: BProc, e: PNode) =
-  var
-    a, b, f: TLoc
-    refType, bt: PType
-    ti: PRope
-    oldModule: BModule
-  refType = skipTypes(e.sons[1].typ, abstractVarRange)
-  InitLocExpr(p, e.sons[1], a)
-  # This is a little hack:
-  # XXX this is also a bug, if the finalizer expression produces side-effects
-  oldModule = p.module
-  p.module = gNimDat
-  InitLocExpr(p, e.sons[2], f)
-  p.module = oldModule
-  initLoc(b, locExpr, a.t, OnHeap)
-  ti = genTypeInfo(p.module, refType)
-  appf(gNimDat.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
-  b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
-      getTypeDesc(p.module, refType),
-      ti, getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))])
-  genAssignment(p, a, b, {needToKeepAlive})  # set the object type:
-  bt = skipTypes(refType.sons[0], abstractRange)
-  genObjectInit(p, cpsStmts, bt, a, false)
-
 proc genRepr(p: BProc, e: PNode, d: var TLoc) =
   # XXX we don't generate keep alive info for now here
   var a: TLoc
@@ -1277,46 +1324,6 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
   else:
     binaryExpr(p, e, d, "#eqStrings($1, $2)")
 
-proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
-  var newSeq, arr: TLoc
-  if d.k == locNone:
-    getTemp(p, t.typ, d)
-  # generate call to newSeq before adding the elements per hand:
-  initLoc(newSeq, locExpr, t.typ, OnHeap)
-  newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)", 
-      [getTypeDesc(p.module, t.typ),
-      genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))])
-  genAssignment(p, d, newSeq, {afSrcIsNotNil, needToKeepAlive})
-  for i in countup(0, sonsLen(t) - 1):
-    initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
-    arr.r = ropef("$1->data[$2]", [rdLoc(d), intLiteral(i)])
-    arr.s = OnHeap            # we know that sequences are on the heap
-    expr(p, t.sons[i], arr)
-
-proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
-  var newSeq, elem, a, arr: TLoc
-  if t.kind == nkBracket:
-    t.sons[1].typ = t.typ
-    genSeqConstr(p, t.sons[1], d)
-    return
-  if d.k == locNone:
-    getTemp(p, t.typ, d)
-  # generate call to newSeq before adding the elements per hand:
-  var L = int(lengthOrd(t.sons[1].typ))
-  initLoc(newSeq, locExpr, t.typ, OnHeap)
-  newSeq.r = ropecg(p.module, "($1) #newSeq($2, $3)", 
-      [getTypeDesc(p.module, t.typ),
-      genTypeInfo(p.module, t.typ), intLiteral(L)])
-  genAssignment(p, d, newSeq, {afSrcIsNotNil, needToKeepAlive})
-  initLocExpr(p, t.sons[1], a)
-  for i in countup(0, L - 1):
-    initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap)
-    elem.r = ropef("$1->data[$2]", [rdLoc(d), intLiteral(i)])
-    elem.s = OnHeap # we know that sequences are on the heap
-    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s)
-    arr.r = ropef("$1[$2]", [rdLoc(a), intLiteral(i)])
-    genAssignment(p, elem, arr, {afDestIsNil, needToCopy})
-
 proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   if {optNanCheck, optInfCheck} * p.options != {}:
     const opr: array[mAddF64..mDivF64, string] = ["+", "-", "*", "/"]
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 66b84a8c5..02782cdd0 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -230,6 +230,7 @@ proc decRef(c: PCell) {.inline.} =
   if --c.refcount:
     rtlAddZCT(c)
   elif canBeCycleRoot(c):
+    # XXX if 'incRef' does this check, it should be unnecessary in 'decRef'
     rtlAddCycleRoot(c) 
 
 proc incRef(c: PCell) {.inline.} = 
diff --git a/todo.txt b/todo.txt
index 9f77fcf2e..eb87a3cb1 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,6 +1,10 @@
 version 0.8.14
 ==============
 
+- compiler should generate better code wrt GC
+  - compiler should optimize string creation
+  - marker procs for the GC
+  - need to generate code to prevent tail call optimization
 - warning for implicit openArray -> varargs convention
 - implement explicit varargs; **but** ``len(varargs)`` problem remains! 
   --> solve by implicit conversion from varargs to openarray