diff options
-rw-r--r-- | compiler/ast.nim | 4 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 1 | ||||
-rw-r--r-- | compiler/lowerings.nim | 4 | ||||
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 8 | ||||
-rw-r--r-- | compiler/semparallel.nim | 13 | ||||
-rw-r--r-- | tests/parallel/tdeepcopy.nim | 18 |
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() |