closures have an object type field so that we can perform correct deepCopy() for the BoehmGC target

This commit is contained in:
Andreas Rumpf
2017-07-22 11:10:44 +02:00
parent 1f13e94dd0
commit ad608838bf
7 changed files with 40 additions and 19 deletions

View File

@@ -164,11 +164,11 @@ proc genBreakState(p: BProc, n: PNode) =
if n.sons[0].kind == nkClosure:
# XXX this produces quite inefficient code!
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:
initLocExpr(p, n.sons[0], a)
# the environment is guaranteed to contain the 'state' field at offset 0:
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[0]) < 0) break;$n", [rdLoc(a)])
# the environment is guaranteed to contain the 'state' field at offset 1:
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)])
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
proc genVarPrototypeAux(m: BModule, sym: PSym)

View File

@@ -12,6 +12,7 @@
# ------------------------- Name Mangling --------------------------------
import sighashes
from lowerings import createObj
proc isKeyword(w: PIdent): bool =
# Nim and C++ share some keywords
@@ -1092,7 +1093,8 @@ proc fakeClosureType(owner: PSym): PType =
result = newType(tyTuple, owner)
result.rawAddSon(newType(tyPointer, 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)
type

View File

@@ -142,7 +142,7 @@ proc createStateField(iter: PSym): PSym =
proc createEnvObj(owner: PSym; info: TLineInfo): PType =
# 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:
result = createObj(owner, info)
result = createObj(owner, info, final=false)
rawAddField(result, createStateField(owner))
proc getIterResult(iter: PSym): PSym =

View File

@@ -109,17 +109,19 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode =
result.add newFastAsgnStmt(n[1], n[2])
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)
rawAddSon(result, nil)
incl result.flags, tfFinal
if final:
rawAddSon(result, nil)
incl result.flags, tfFinal
else:
rawAddSon(result, getCompilerProc("RootObj").typ)
result.n = newNodeI(nkRecList, info)
when true:
let s = newSym(skType, getIdent("Env_" & info.toFilename),
owner, info)
incl s.flags, sfAnon
s.typ = result
result.sym = s
let s = newSym(skType, getIdent("Env_" & info.toFilename),
owner, info)
incl s.flags, sfAnon
s.typ = result
result.sym = s
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField

View File

@@ -413,7 +413,7 @@ type
## is an int type ranging from one to the maximum value
## 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
## inherit from RootObj or one of its descendants. However,
## 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.} =
## can be used to determine if a first class iterator has finished.
{.emit: """
`result` = *((NI*) `x`.ClE_0) < 0;
`result` = ((NI*) `x`.ClE_0)[1] < 0;
""".}
elif defined(JS):

View File

@@ -148,11 +148,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
let realType = x.typ
sysAssert realType == mt, " types do differ"
# 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 z = newObj(mt, size)
let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
let z = newObj(mt, typ.size)
unsureAsgnRef(cast[PPointer](dest), z)
tab.put(s2, z)
genericDeepCopyAux(z, s2, mt.base, tab)
genericDeepCopyAux(z, s2, typ, tab)
else:
unsureAsgnRef(cast[PPointer](dest), z)
of tyPtr:

View 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()