summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim4
-rw-r--r--compiler/ccgtypes.nim1
-rw-r--r--compiler/lowerings.nim4
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semexprs.nim8
-rw-r--r--compiler/semparallel.nim13
-rw-r--r--tests/parallel/tdeepcopy.nim18
7 files changed, 40 insertions, 10 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 51319127c..7ad294695 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1313,6 +1313,10 @@ proc newSons(father: PNode, length: int) =
     setLen(father.sons, length)
 
 proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
+  ## Used throughout the compiler code to test whether a type tree contains or
+  ## doesn't contain a specific type/types - it is often the case that only the
+  ## last child nodes of a type tree need to be searched. This is a really hot
+  ## path within the compiler!
   result = t
   while result.kind in kinds: result = lastSon(result)
 
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 4c71c6ff7..86142995c 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -122,6 +122,7 @@ proc mapSetType(typ: PType): TCTypeKind =
   else: result = ctArray
 
 proc mapType(typ: PType): TCTypeKind = 
+  ## Maps a nimrod type to a C type
   case typ.kind
   of tyNone, tyStmt: result = ctVoid
   of tyBool: result = ctBool
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 4050bb9b4..ddfcb4f01 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -185,14 +185,14 @@ proc callProc(a: PNode): PNode =
 # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter
 # - not in a parallel environment --> requires a flowVar for memory safety
 type
-  TSpawnResult = enum
+  TSpawnResult* = enum
     srVoid, srFlowVar, srByVar
   TFlowVarKind = enum
     fvInvalid # invalid type T for 'FlowVar[T]'
     fvGC      # FlowVar of a GC'ed type
     fvBlob    # FlowVar of a blob type
 
-proc spawnResult(t: PType; inParallel: bool): TSpawnResult =
+proc spawnResult*(t: PType; inParallel: bool): TSpawnResult =
   if t.isEmptyType: srVoid
   elif inParallel and not containsGarbageCollectedRef(t): srByVar
   else: srFlowVar
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 8025ef70d..26a59334c 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -16,7 +16,7 @@ import
   procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
   intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
   evaltempl, patterns, parampatterns, sempass2, pretty, semmacrosanity,
-  semparallel
+  semparallel, lowerings
 
 # implementation
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d040675fa..7e97eb293 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -199,6 +199,8 @@ proc isCastable(dst, src: PType): bool =
     result = (dstSize >= srcSize) or
         (skipTypes(dst, abstractInst).kind in IntegralTypes) or
         (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes)
+  if result and src.kind == tyNil:
+    result = dst.size <= platform.ptrSize
   
 proc isSymChoice(n: PNode): bool {.inline.} =
   result = n.kind in nkSymChoices
@@ -1643,10 +1645,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     result = setMs(n, s)
     result.sons[1] = semExpr(c, n.sons[1])
     if not result[1].typ.isEmptyType:
-      if c.inParallelStmt > 0:
-        result.typ = result[1].typ
-      else:
+      if spawnResult(result[1].typ, c.inParallelStmt > 0) == srFlowVar:
         result.typ = createFlowVar(c, result[1].typ, n.info)
+      else:
+        result.typ = result[1].typ
       result.add instantiateCreateFlowVarCall(c, result[1].typ, n.info).newSymNode
   else: result = semDirectOp(c, n, flags)
 
diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim
index 2ad7ef341..7c489c3b6 100644
--- a/compiler/semparallel.nim
+++ b/compiler/semparallel.nim
@@ -23,7 +23,7 @@
 
 import
   ast, astalgo, idents, lowerings, magicsys, guards, sempass2, msgs,
-  renderer
+  renderer, types
 from trees import getMagic
 from strutils import `%`
 
@@ -406,12 +406,17 @@ proc transformSpawn(owner: PSym; n, barrier: PNode): PNode =
         if result.isNil:
           result = newNodeI(nkStmtList, n.info)
           result.add n
-        result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0])
-        it.sons[it.len-1] = emptyNode
+        let t = b[1][0].typ.sons[0]
+        if spawnResult(t, true) == srByVar:
+          result.add wrapProcForSpawn(owner, m, b.typ, barrier, it[0])
+          it.sons[it.len-1] = emptyNode
+        else:
+          it.sons[it.len-1] = wrapProcForSpawn(owner, m, b.typ, barrier, nil)
     if result.isNil: result = n
   of nkAsgn, nkFastAsgn:
     let b = n[1]
-    if getMagic(b) == mSpawn:
+    if getMagic(b) == mSpawn and (let t = b[1][0].typ.sons[0];
+        spawnResult(t, true) == srByVar):
       let m = transformSlices(b)
       return wrapProcForSpawn(owner, m, b.typ, barrier, n[0])
     result = transformSpawnSons(owner, n, barrier)
diff --git a/tests/parallel/tdeepcopy.nim b/tests/parallel/tdeepcopy.nim
new file mode 100644
index 000000000..84e2edf3f
--- /dev/null
+++ b/tests/parallel/tdeepcopy.nim
@@ -0,0 +1,18 @@
+discard """
+  output: '''13 abc'''
+"""
+
+type
+  PBinaryTree = ref object
+    le, ri: PBinaryTree
+    value: int
+
+
+proc main =
+  var x: PBinaryTree
+  deepCopy(x, PBinaryTree(ri: PBinaryTree(le: PBinaryTree(value: 13))))
+  var y: string
+  deepCopy y, "abc"
+  echo x.ri.le.value, " ", y
+
+main()