precise stack scanning for Nim's GCs; work in progress
This commit is contained in:
parent
55b5401dc6
commit
02bbfa1164
8 changed files with 68 additions and 40 deletions
|
|
@ -739,6 +739,8 @@ type
|
||||||
OnUnknown, # location is unknown (stack, heap or static)
|
OnUnknown, # location is unknown (stack, heap or static)
|
||||||
OnStatic, # in a static section
|
OnStatic, # in a static section
|
||||||
OnStack, # location is on hardware stack
|
OnStack, # location is on hardware stack
|
||||||
|
OnStackShadowDup, # location is on the stack but also replicated
|
||||||
|
# on the shadow stack
|
||||||
OnHeap # location is on heap or global
|
OnHeap # location is on heap or global
|
||||||
# (reference counting needed)
|
# (reference counting needed)
|
||||||
TLocFlags* = set[TLocFlag]
|
TLocFlags* = set[TLocFlag]
|
||||||
|
|
@ -748,6 +750,7 @@ type
|
||||||
flags*: TLocFlags # location's flags
|
flags*: TLocFlags # location's flags
|
||||||
t*: PType # type of location
|
t*: PType # type of location
|
||||||
r*: Rope # rope value of location (code generators)
|
r*: Rope # rope value of location (code generators)
|
||||||
|
dup*: Rope # duplicated location for precise stack scans
|
||||||
|
|
||||||
# ---------------- end of backend information ------------------------------
|
# ---------------- end of backend information ------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,32 +132,12 @@ proc genSetNode(p: BProc, n: PNode): Rope =
|
||||||
else:
|
else:
|
||||||
result = genRawSetData(cs, size)
|
result = genRawSetData(cs, size)
|
||||||
|
|
||||||
proc getStorageLoc(n: PNode): TStorageLoc =
|
|
||||||
case n.kind
|
|
||||||
of nkSym:
|
|
||||||
case n.sym.kind
|
|
||||||
of skParam, skTemp:
|
|
||||||
result = OnStack
|
|
||||||
of skVar, skForVar, skResult, skLet:
|
|
||||||
if sfGlobal in n.sym.flags: result = OnHeap
|
|
||||||
else: result = OnStack
|
|
||||||
of skConst:
|
|
||||||
if sfGlobal in n.sym.flags: result = OnHeap
|
|
||||||
else: result = OnUnknown
|
|
||||||
else: result = OnUnknown
|
|
||||||
of nkDerefExpr, nkHiddenDeref:
|
|
||||||
case n.sons[0].typ.kind
|
|
||||||
of tyVar: result = OnUnknown
|
|
||||||
of tyPtr: result = OnStack
|
|
||||||
of tyRef: result = OnHeap
|
|
||||||
else: internalError(n.info, "getStorageLoc")
|
|
||||||
of nkBracketExpr, nkDotExpr, nkObjDownConv, nkObjUpConv:
|
|
||||||
result = getStorageLoc(n.sons[0])
|
|
||||||
else: result = OnUnknown
|
|
||||||
|
|
||||||
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if dest.s == OnStack or not usesNativeGC():
|
if dest.s == OnStack or not usesNativeGC():
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
|
elif dest.s == OnStackShadowDup:
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", dupLoc(dest), rdLoc(src))
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# location is on heap
|
# location is on heap
|
||||||
# now the writer barrier is inlined for performance:
|
# now the writer barrier is inlined for performance:
|
||||||
|
|
@ -184,6 +164,8 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
|
if preciseStack():
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", dupLoc(dest), rdLoc(src))
|
||||||
|
|
||||||
proc asgnComplexity(n: PNode): int =
|
proc asgnComplexity(n: PNode): int =
|
||||||
if n != nil:
|
if n != nil:
|
||||||
|
|
@ -241,7 +223,7 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
|
||||||
|
|
||||||
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# Consider:
|
# Consider:
|
||||||
# type TMyFastString {.shallow.} = string
|
# type MyFastString {.shallow.} = string
|
||||||
# Due to the implementation of pragmas this would end up to set the
|
# Due to the implementation of pragmas this would end up to set the
|
||||||
# tfShallow flag for the built-in string type too! So we check only
|
# tfShallow flag for the built-in string type too! So we check only
|
||||||
# here for this flag, where it is reasonably safe to do so
|
# here for this flag, where it is reasonably safe to do so
|
||||||
|
|
@ -259,6 +241,9 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
|
||||||
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
addrLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
|
if dest.s == OnStackShadowDup:
|
||||||
|
linefmt(p, cpsStmts, "#genericAssignDup((void*)&$1, (void*)$2, $3);$n",
|
||||||
|
dupLoc(dest), addrLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
|
|
||||||
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# This function replaces all other methods for generating
|
# This function replaces all other methods for generating
|
||||||
|
|
@ -277,12 +262,17 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
|
||||||
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
addrLoc(dest), rdLoc(src), genTypeInfo(p.module, dest.t))
|
||||||
|
if dest.s == OnStackShadowDup:
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
|
||||||
of tyString:
|
of tyString:
|
||||||
if needToCopy notin flags and src.s != OnStatic:
|
if needToCopy notin flags and src.s != OnStatic:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if dest.s == OnStack or not usesNativeGC():
|
if dest.s == OnStack or not usesNativeGC():
|
||||||
linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
|
linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
|
||||||
|
elif dest.s == OnStackShadowDup:
|
||||||
|
linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc)
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# we use a temporary to care for the dreaded self assignment:
|
# we use a temporary to care for the dreaded self assignment:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
|
|
@ -293,6 +283,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
|
if preciseStack():
|
||||||
|
linefmt(p, cpsStmts, "$1 = $2;$n", dest.dupLoc, dest.rdLoc)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if needsComplexAssignment(dest.t):
|
if needsComplexAssignment(dest.t):
|
||||||
# optimize closure assignment:
|
# optimize closure assignment:
|
||||||
|
|
@ -1170,6 +1162,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var t = e.typ.skipTypes(abstractInst)
|
var t = e.typ.skipTypes(abstractInst)
|
||||||
getTemp(p, t, tmp)
|
getTemp(p, t, tmp)
|
||||||
let isRef = t.kind == tyRef
|
let isRef = t.kind == tyRef
|
||||||
|
let stck = stackPlacement(t)
|
||||||
var r = rdLoc(tmp)
|
var r = rdLoc(tmp)
|
||||||
if isRef:
|
if isRef:
|
||||||
rawGenNew(p, tmp, nil)
|
rawGenNew(p, tmp, nil)
|
||||||
|
|
@ -1193,7 +1186,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
add(tmp2.r, field.loc.r)
|
add(tmp2.r, field.loc.r)
|
||||||
tmp2.k = locTemp
|
tmp2.k = locTemp
|
||||||
tmp2.t = field.loc.t
|
tmp2.t = field.loc.t
|
||||||
tmp2.s = if isRef: OnHeap else: OnStack
|
tmp2.s = if isRef: OnHeap else: stck
|
||||||
expr(p, it.sons[1], tmp2)
|
expr(p, it.sons[1], tmp2)
|
||||||
|
|
||||||
if d.k == locNone:
|
if d.k == locNone:
|
||||||
|
|
|
||||||
|
|
@ -803,6 +803,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
|
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
|
||||||
if optStackTrace in p.options:
|
if optStackTrace in p.options:
|
||||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
||||||
|
if p.gcFrameLen > 0:
|
||||||
|
linefmt(p, cpsStmts, "#setGcFrame((#GcFrameBase*)&GCF_);$n")
|
||||||
inc p.inExceptBlock
|
inc p.inExceptBlock
|
||||||
var i = 1
|
var i = 1
|
||||||
var catchAllPresent = false
|
var catchAllPresent = false
|
||||||
|
|
@ -911,6 +913,9 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
||||||
if optStackTrace in p.options:
|
if optStackTrace in p.options:
|
||||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
||||||
|
if p.gcFrameLen > 0:
|
||||||
|
linefmt(p, cpsStmts, "#setGcFrame((#GcFrameBase*)&GCF_);$n")
|
||||||
|
|
||||||
inc p.inExceptBlock
|
inc p.inExceptBlock
|
||||||
var i = 1
|
var i = 1
|
||||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ proc ccgIntroducedPtr(s: PSym): bool =
|
||||||
|
|
||||||
proc fillResult(param: PSym) =
|
proc fillResult(param: PSym) =
|
||||||
fillLoc(param.loc, locParam, param.typ, ~"Result",
|
fillLoc(param.loc, locParam, param.typ, ~"Result",
|
||||||
OnStack)
|
stackPlacement(param.typ))
|
||||||
if mapReturnType(param.typ) != ctArray and isInvalidReturnType(param.typ):
|
if mapReturnType(param.typ) != ctArray and isInvalidReturnType(param.typ):
|
||||||
incl(param.loc.flags, lfIndirect)
|
incl(param.loc.flags, lfIndirect)
|
||||||
param.loc.s = OnUnknown
|
param.loc.s = OnUnknown
|
||||||
|
|
@ -376,9 +376,9 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet): Rope =
|
||||||
result = getTypeDescAux(m, t, check)
|
result = getTypeDescAux(m, t, check)
|
||||||
|
|
||||||
proc paramStorageLoc(param: PSym): TStorageLoc =
|
proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||||
if param.typ.skipTypes({tyVar, tyTypeDesc}).kind notin {
|
let t = param.typ.skipTypes({tyVar, tyTypeDesc})
|
||||||
tyArray, tyOpenArray, tyVarargs}:
|
if t.kind notin {tyArray, tyOpenArray, tyVarargs}:
|
||||||
result = OnStack
|
result = stackPlacement(t)
|
||||||
else:
|
else:
|
||||||
result = OnUnknown
|
result = OnUnknown
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,6 +244,10 @@ proc addrLoc(a: TLoc): Rope =
|
||||||
if lfIndirect notin a.flags and mapType(a.t) != ctArray:
|
if lfIndirect notin a.flags and mapType(a.t) != ctArray:
|
||||||
result = "(&" & result & ")"
|
result = "(&" & result & ")"
|
||||||
|
|
||||||
|
proc dupLoc(a: TLoc): Rope =
|
||||||
|
result = a.dup
|
||||||
|
assert result != nil
|
||||||
|
|
||||||
proc rdCharLoc(a: TLoc): Rope =
|
proc rdCharLoc(a: TLoc): Rope =
|
||||||
# read a location that may need a char-cast:
|
# read a location that may need a char-cast:
|
||||||
result = rdLoc(a)
|
result = rdLoc(a)
|
||||||
|
|
@ -288,12 +292,13 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
if not isComplexValueType(typ):
|
if not isComplexValueType(typ):
|
||||||
if containsGcRef:
|
if containsGcRef:
|
||||||
var nilLoc: TLoc
|
var nilLoc: TLoc
|
||||||
initLoc(nilLoc, locTemp, loc.t, OnStack)
|
initLoc(nilLoc, locTemp, loc.t, stackPlacement(typ))
|
||||||
nilLoc.r = rope("NIM_NIL")
|
nilLoc.r = rope("NIM_NIL")
|
||||||
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
|
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
|
||||||
else:
|
else:
|
||||||
|
XXX use stackPlacement here?
|
||||||
if optNilCheck in p.options:
|
if optNilCheck in p.options:
|
||||||
linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", addrLoc(loc))
|
linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", addrLoc(loc))
|
||||||
if loc.s != OnStack:
|
if loc.s != OnStack:
|
||||||
|
|
@ -343,17 +348,21 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||||
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
||||||
result.k = locTemp
|
result.k = locTemp
|
||||||
result.t = t
|
result.t = t
|
||||||
result.s = OnStack
|
result.s = stackPlacement(t)
|
||||||
result.flags = {}
|
result.flags = {}
|
||||||
constructLoc(p, result, not needsInit)
|
constructLoc(p, result, not needsInit)
|
||||||
|
|
||||||
proc initGCFrame(p: BProc): Rope =
|
proc initGCFrame(p: BProc): Rope =
|
||||||
if p.gcFrameId > 0: result = "struct {$1} GCFRAME_;$n" % [p.gcFrameType]
|
if p.gcFrameLen > 0:
|
||||||
|
result = ropegc(p.module, """
|
||||||
|
struct {#GcFrameBase b_; $1} GCF_;$n
|
||||||
|
GCF_.b_.L=$2;$n
|
||||||
|
#pushGcFrame((GcFrameBase*)&GCF_);$n""" % [
|
||||||
|
p.gcFrameType, rope(p.gcFrameLen)])
|
||||||
|
|
||||||
proc deinitGCFrame(p: BProc): Rope =
|
proc deinitGCFrame(p: BProc): Rope =
|
||||||
if p.gcFrameId > 0:
|
if p.gcFrameLen > 0:
|
||||||
result = ropecg(p.module,
|
result = ropecg(p.module, "#popGcFrame();$n")
|
||||||
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n")
|
|
||||||
|
|
||||||
proc localDebugInfo(p: BProc, s: PSym) =
|
proc localDebugInfo(p: BProc, s: PSym) =
|
||||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||||
|
|
@ -370,7 +379,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
||||||
|
|
||||||
proc localVarDecl(p: BProc; s: PSym): Rope =
|
proc localVarDecl(p: BProc; s: PSym): Rope =
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), OnStack)
|
fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), stackPlacement(s.typ))
|
||||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||||
result = getTypeDesc(p.module, s.typ)
|
result = getTypeDesc(p.module, s.typ)
|
||||||
if s.constraint.isNil:
|
if s.constraint.isNil:
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ type
|
||||||
splitDecls*: int # > 0 if we are in some context for C++ that
|
splitDecls*: int # > 0 if we are in some context for C++ that
|
||||||
# requires 'T x = T()' to become 'T x; x = T()'
|
# requires 'T x = T()' to become 'T x; x = T()'
|
||||||
# (yes, C++ is weird like that)
|
# (yes, C++ is weird like that)
|
||||||
gcFrameId*: Natural # for the GC stack marking
|
gcFrameLen*: int # the number of slots in the GC-Frame
|
||||||
gcFrameType*: Rope # the struct {} we put the GC markers into
|
gcFrameType*: Rope # the struct {} we put the GC markers into
|
||||||
sigConflicts*: CountTable[string]
|
sigConflicts*: CountTable[string]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,12 +140,13 @@ var
|
||||||
gEvalExpr* = "" # expression for idetools --eval
|
gEvalExpr* = "" # expression for idetools --eval
|
||||||
gLastCmdTime*: float # when caas is enabled, we measure each command
|
gLastCmdTime*: float # when caas is enabled, we measure each command
|
||||||
gListFullPaths*: bool
|
gListFullPaths*: bool
|
||||||
isServing*: bool = false
|
gPreciseStack*: bool = false
|
||||||
gNoNimblePath* = false
|
gNoNimblePath* = false
|
||||||
gExperimentalMode*: bool
|
gExperimentalMode*: bool
|
||||||
|
|
||||||
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools}
|
||||||
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc
|
||||||
|
template preciseStack*(): bool = gPreciseStack
|
||||||
|
|
||||||
template compilationCachePresent*: untyped =
|
template compilationCachePresent*: untyped =
|
||||||
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
{optCaasEnabled, optSymbolFiles} * gGlobalOptions != {}
|
||||||
|
|
|
||||||
|
|
@ -38,20 +38,29 @@ proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.}
|
||||||
proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.}
|
proc chckRangeF(x, a, b: float): float {.inline, compilerproc, benign.}
|
||||||
proc chckNil(p: pointer) {.noinline, compilerproc, benign.}
|
proc chckNil(p: pointer) {.noinline, compilerproc, benign.}
|
||||||
|
|
||||||
|
type
|
||||||
|
GcFrame = ptr GcFrameHeader
|
||||||
|
GcFrameHeader {.compilerproc.} = object
|
||||||
|
len: int
|
||||||
|
prev: ptr GcFrameHeader
|
||||||
|
|
||||||
var
|
var
|
||||||
framePtr {.threadvar.}: PFrame
|
framePtr {.threadvar.}: PFrame
|
||||||
excHandler {.threadvar.}: PSafePoint
|
excHandler {.threadvar.}: PSafePoint
|
||||||
# list of exception handlers
|
# list of exception handlers
|
||||||
# a global variable for the root of all try blocks
|
# a global variable for the root of all try blocks
|
||||||
currException {.threadvar.}: ref Exception
|
currException {.threadvar.}: ref Exception
|
||||||
|
gcFramePtr {.threadvar.}: GcFrame
|
||||||
|
|
||||||
type
|
type
|
||||||
FrameState = tuple[framePtr: PFrame, excHandler: PSafePoint, currException: ref Exception]
|
FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame,
|
||||||
|
excHandler: PSafePoint, currException: ref Exception]
|
||||||
|
|
||||||
proc getFrameState*(): FrameState {.compilerRtl, inl.} =
|
proc getFrameState*(): FrameState {.compilerRtl, inl.} =
|
||||||
return (framePtr, excHandler, currException)
|
return (gcFramePtr, framePtr, excHandler, currException)
|
||||||
|
|
||||||
proc setFrameState*(state: FrameState) {.compilerRtl, inl.} =
|
proc setFrameState*(state: FrameState) {.compilerRtl, inl.} =
|
||||||
|
gcFramePtr = state.gcFramePtr
|
||||||
framePtr = state.framePtr
|
framePtr = state.framePtr
|
||||||
excHandler = state.excHandler
|
excHandler = state.excHandler
|
||||||
currException = state.currException
|
currException = state.currException
|
||||||
|
|
@ -64,6 +73,14 @@ proc popFrame {.compilerRtl, inl.} =
|
||||||
proc setFrame*(s: PFrame) {.compilerRtl, inl.} =
|
proc setFrame*(s: PFrame) {.compilerRtl, inl.} =
|
||||||
framePtr = s
|
framePtr = s
|
||||||
|
|
||||||
|
proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr
|
||||||
|
proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev
|
||||||
|
proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s
|
||||||
|
proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} =
|
||||||
|
s.prev = gcFramePtr
|
||||||
|
zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer))
|
||||||
|
gcFramePtr = s
|
||||||
|
|
||||||
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||||
s.hasRaiseAction = false
|
s.hasRaiseAction = false
|
||||||
s.prev = excHandler
|
s.prev = excHandler
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue