fixes a serious codegen bug that caused to emit wrong barriers in rare cases

This commit is contained in:
Araq 2015-04-19 13:36:22 +02:00
commit 89cbf092b2
3 changed files with 71 additions and 13 deletions

View file

@ -685,19 +685,23 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
else: else:
var a: TLoc var a: TLoc
initLocExprSingleUse(p, e.sons[0], a) initLocExprSingleUse(p, e.sons[0], a)
let typ = skipTypes(a.t, abstractInst) if d.k == locNone:
case typ.kind let typ = skipTypes(a.t, abstractInst)
of tyRef: # dest = *a; <-- We do not know that 'dest' is on the heap!
d.s = OnHeap # It is completely wrong to set 'd.s' here, unless it's not yet
of tyVar: # been assigned to.
d.s = OnUnknown case typ.kind
if tfVarIsPtr notin typ.flags and p.module.compileToCpp and of tyRef:
e.kind == nkHiddenDeref: d.s = OnHeap
putIntoDest(p, d, e.typ, rdLoc(a)) of tyVar:
return d.s = OnUnknown
of tyPtr: if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
d.s = OnUnknown # BUGFIX! e.kind == nkHiddenDeref:
else: internalError(e.info, "genDeref " & $a.t.kind) putIntoDest(p, d, e.typ, rdLoc(a))
return
of tyPtr:
d.s = OnUnknown # BUGFIX!
else: internalError(e.info, "genDeref " & $a.t.kind)
if enforceDeref and mt == ctPtrToArray: if enforceDeref and mt == ctPtrToArray:
# we lie about the type for better C interop: 'ptr array[3,T]' is # we lie about the type for better C interop: 'ptr array[3,T]' is
# translated to 'ptr T', but for deref'ing this produces wrong code. # translated to 'ptr T', but for deref'ing this produces wrong code.

View file

@ -0,0 +1,53 @@
discard """
output: "Success"
"""
import math, threadPool
# ---
type
Person = object
age: int
friend: ref Person
var
people: seq[ref Person] = @[]
proc newPerson(age:int): ref Person =
result.new()
result.age = age
proc greet(p:Person) =
#echo p.age, ", ", p.friend.age
p.friend.age += 1
# ---
proc setup =
for i in 0 .. <20:
people.add newPerson(i + 1)
for i in 0 .. <20:
people[i].friend = people[random(20)]
proc update =
var countA: array[20, int]
var countB: array[20, int]
for i, p in people:
countA[i] = getRefCount(p)
parallel:
for i in 0 .. people.high:
spawn greet(people[i][])
for i, p in people:
countB[i] = getRefCount(p)
for i in 0 .. <20:
doAssert countA[i] == countB[i]
echo "Success"
# ---
when isMainModule:
setup()
update()

View file

@ -2,6 +2,7 @@ version 0.10.4
============== ==============
- make 'nil' work for 'add' and 'len' - make 'nil' work for 'add' and 'len'
- enable parameter info for nimsuggest
version 1.0 version 1.0
=========== ===========