closures have an object type field so that we can perform correct deepCopy() for the BoehmGC target
This commit is contained in:
parent
1f13e94dd0
commit
ad608838bf
7 changed files with 40 additions and 19 deletions
|
|
@ -164,11 +164,11 @@ proc genBreakState(p: BProc, n: PNode) =
|
||||||
if n.sons[0].kind == nkClosure:
|
if n.sons[0].kind == nkClosure:
|
||||||
# XXX this produces quite inefficient code!
|
# XXX this produces quite inefficient code!
|
||||||
initLocExpr(p, n.sons[0].sons[1], a)
|
initLocExpr(p, n.sons[0].sons[1], a)
|
||||||
lineF(p, cpsStmts, "if (((NI*) $1)[0] < 0) break;$n", [rdLoc(a)])
|
lineF(p, cpsStmts, "if (((NI*) $1)[1] < 0) break;$n", [rdLoc(a)])
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
# the environment is guaranteed to contain the 'state' field at offset 0:
|
# the environment is guaranteed to contain the 'state' field at offset 1:
|
||||||
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[0]) < 0) break;$n", [rdLoc(a)])
|
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)])
|
||||||
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
|
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
|
||||||
|
|
||||||
proc genVarPrototypeAux(m: BModule, sym: PSym)
|
proc genVarPrototypeAux(m: BModule, sym: PSym)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
# ------------------------- Name Mangling --------------------------------
|
# ------------------------- Name Mangling --------------------------------
|
||||||
|
|
||||||
import sighashes
|
import sighashes
|
||||||
|
from lowerings import createObj
|
||||||
|
|
||||||
proc isKeyword(w: PIdent): bool =
|
proc isKeyword(w: PIdent): bool =
|
||||||
# Nim and C++ share some keywords
|
# Nim and C++ share some keywords
|
||||||
|
|
@ -1092,7 +1093,8 @@ proc fakeClosureType(owner: PSym): PType =
|
||||||
result = newType(tyTuple, owner)
|
result = newType(tyTuple, owner)
|
||||||
result.rawAddSon(newType(tyPointer, owner))
|
result.rawAddSon(newType(tyPointer, owner))
|
||||||
var r = newType(tyRef, owner)
|
var r = newType(tyRef, owner)
|
||||||
r.rawAddSon(newType(tyTuple, owner))
|
let obj = createObj(owner, owner.info, final=false)
|
||||||
|
r.rawAddSon(obj)
|
||||||
result.rawAddSon(r)
|
result.rawAddSon(r)
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ proc createStateField(iter: PSym): PSym =
|
||||||
proc createEnvObj(owner: PSym; info: TLineInfo): PType =
|
proc createEnvObj(owner: PSym; info: TLineInfo): PType =
|
||||||
# YYY meh, just add the state field for every closure for now, it's too
|
# YYY meh, just add the state field for every closure for now, it's too
|
||||||
# hard to figure out if it comes from a closure iterator:
|
# hard to figure out if it comes from a closure iterator:
|
||||||
result = createObj(owner, info)
|
result = createObj(owner, info, final=false)
|
||||||
rawAddField(result, createStateField(owner))
|
rawAddField(result, createStateField(owner))
|
||||||
|
|
||||||
proc getIterResult(iter: PSym): PSym =
|
proc getIterResult(iter: PSym): PSym =
|
||||||
|
|
|
||||||
|
|
@ -109,17 +109,19 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode =
|
||||||
result.add newFastAsgnStmt(n[1], n[2])
|
result.add newFastAsgnStmt(n[1], n[2])
|
||||||
result.add newFastAsgnStmt(n[2], tempAsNode)
|
result.add newFastAsgnStmt(n[2], tempAsNode)
|
||||||
|
|
||||||
proc createObj*(owner: PSym, info: TLineInfo): PType =
|
proc createObj*(owner: PSym, info: TLineInfo; final=true): PType =
|
||||||
result = newType(tyObject, owner)
|
result = newType(tyObject, owner)
|
||||||
rawAddSon(result, nil)
|
if final:
|
||||||
incl result.flags, tfFinal
|
rawAddSon(result, nil)
|
||||||
|
incl result.flags, tfFinal
|
||||||
|
else:
|
||||||
|
rawAddSon(result, getCompilerProc("RootObj").typ)
|
||||||
result.n = newNodeI(nkRecList, info)
|
result.n = newNodeI(nkRecList, info)
|
||||||
when true:
|
let s = newSym(skType, getIdent("Env_" & info.toFilename),
|
||||||
let s = newSym(skType, getIdent("Env_" & info.toFilename),
|
owner, info)
|
||||||
owner, info)
|
incl s.flags, sfAnon
|
||||||
incl s.flags, sfAnon
|
s.typ = result
|
||||||
s.typ = result
|
result.sym = s
|
||||||
result.sym = s
|
|
||||||
|
|
||||||
proc rawAddField*(obj: PType; field: PSym) =
|
proc rawAddField*(obj: PType; field: PSym) =
|
||||||
assert field.kind == skField
|
assert field.kind == skField
|
||||||
|
|
|
||||||
|
|
@ -413,7 +413,7 @@ type
|
||||||
## is an int type ranging from one to the maximum value
|
## is an int type ranging from one to the maximum value
|
||||||
## of an int. This type is often useful for documentation and debugging.
|
## of an int. This type is often useful for documentation and debugging.
|
||||||
|
|
||||||
RootObj* {.exportc: "TNimObject", inheritable.} =
|
RootObj* {.compilerProc, inheritable.} =
|
||||||
object ## the root of Nim's object hierarchy. Objects should
|
object ## the root of Nim's object hierarchy. Objects should
|
||||||
## inherit from RootObj or one of its descendants. However,
|
## inherit from RootObj or one of its descendants. However,
|
||||||
## objects that have no ancestor are allowed.
|
## objects that have no ancestor are allowed.
|
||||||
|
|
@ -3269,7 +3269,7 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} =
|
proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} =
|
||||||
## can be used to determine if a first class iterator has finished.
|
## can be used to determine if a first class iterator has finished.
|
||||||
{.emit: """
|
{.emit: """
|
||||||
`result` = *((NI*) `x`.ClE_0) < 0;
|
`result` = ((NI*) `x`.ClE_0)[1] < 0;
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
elif defined(JS):
|
elif defined(JS):
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
|
||||||
let realType = x.typ
|
let realType = x.typ
|
||||||
sysAssert realType == mt, " types do differ"
|
sysAssert realType == mt, " types do differ"
|
||||||
# this version should work for any possible GC:
|
# this version should work for any possible GC:
|
||||||
let size = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[].size else: mt.base.size
|
let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
|
||||||
let z = newObj(mt, size)
|
let z = newObj(mt, typ.size)
|
||||||
unsureAsgnRef(cast[PPointer](dest), z)
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
tab.put(s2, z)
|
tab.put(s2, z)
|
||||||
genericDeepCopyAux(z, s2, mt.base, tab)
|
genericDeepCopyAux(z, s2, typ, tab)
|
||||||
else:
|
else:
|
||||||
unsureAsgnRef(cast[PPointer](dest), z)
|
unsureAsgnRef(cast[PPointer](dest), z)
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
|
|
|
||||||
17
tests/closure/tboehmdeepcopy.nim
Normal file
17
tests/closure/tboehmdeepcopy.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
cmd: "nim c --gc:boehm $options $file"
|
||||||
|
output: '''meep'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc callit(it: proc ()) =
|
||||||
|
it()
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
var outer = "meep"
|
||||||
|
proc x =
|
||||||
|
echo outer
|
||||||
|
var y: proc()
|
||||||
|
deepCopy(y, x)
|
||||||
|
callit(y)
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue