mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
closures have an object type field so that we can perform correct deepCopy() for the BoehmGC target
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
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()
|
||||
Reference in New Issue
Block a user