Replaced ignoreStackAndRegisters with stackSize in GC_step

This commit is contained in:
Ruslan Mustakov 2016-05-11 20:00:22 +06:00
commit 0dc35b7841
3 changed files with 55 additions and 33 deletions

View file

@ -56,7 +56,7 @@ file as well). With this switch the GC supports the following operations:
.. code-block:: nim .. code-block:: nim
proc GC_setMaxPause*(MaxPauseInUs: int) proc GC_setMaxPause*(MaxPauseInUs: int)
proc GC_step*(us: int, strongAdvice, ignoreStackAndRegisters = false) proc GC_step*(us: int, strongAdvice = false, stackSize = -1)
The unit of the parameters ``MaxPauseInUs`` and ``us`` is microseconds. The unit of the parameters ``MaxPauseInUs`` and ``us`` is microseconds.
@ -75,11 +75,13 @@ These two procs are the two modus operandi of the realtime GC:
This allows the GC to perform some work for up to ``us`` time. This is This allows the GC to perform some work for up to ``us`` time. This is
useful to call in a main loop to ensure the GC can do its work. To useful to call in a main loop to ensure the GC can do its work. To
bind all GC activity to a ``GC_step`` call, deactivate the GC with bind all GC activity to a ``GC_step`` call, deactivate the GC with
``GC_disable`` at program startup. Notice that you may ask GC to not ``GC_disable`` at program startup. If ``strongAdvice`` is set to ``true``,
scan stack and registers for references via ``ignoreStackAndRegisters`` GC will be forced to perform collection cycle. Otherwise, GC may decide not
parameter. This may reduce the step time depending on the stack depth, to do anything, if there is not much garbage to collect.
but use it only when you are sure that neither the stack nor the registers You may also specify the current stack size via ``stackSize`` parameter.
contain unique references to objects that must be preserved. It can improve performance, when you know that there are no unique Nim
references below certain point on the stack. Make sure the size you specify
is greater than the potential worst case size.
These procs provide a "best effort" realtime guarantee; in particular the These procs provide a "best effort" realtime guarantee; in particular the
cycle collector is not aware of deadlines yet. Deactivate it to get more cycle collector is not aware of deadlines yet. Deactivate it to get more

View file

@ -905,19 +905,19 @@ proc unmarkStackAndRegisters(gch: var GcHeap) =
#sysAssert c.typ != nil, "unmarkStackAndRegisters 2" #sysAssert c.typ != nil, "unmarkStackAndRegisters 2"
gch.decStack.len = 0 gch.decStack.len = 0
proc collectCTBody(gch: var GcHeap, ignoreStackAndRegisters = false) = proc collectCTBody(gch: var GcHeap) =
when withRealTime: when withRealTime:
let t0 = getticks() let t0 = getticks()
sysAssert(allocInv(gch.region), "collectCT: begin") sysAssert(allocInv(gch.region), "collectCT: begin")
when not defined(nimCoroutines):
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
sysAssert(gch.decStack.len == 0, "collectCT") sysAssert(gch.decStack.len == 0, "collectCT")
prepareForInteriorPointerChecking(gch.region) prepareForInteriorPointerChecking(gch.region)
if not ignoreStackAndRegisters: markStackAndRegisters(gch)
when not defined(nimCoroutines): markThreadStacks(gch)
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize()) gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
markStackAndRegisters(gch) inc(gch.stat.stackScans)
markThreadStacks(gch)
gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
inc(gch.stat.stackScans)
if collectZCT(gch): if collectZCT(gch):
when cycleGC: when cycleGC:
if getOccupiedMem(gch.region) >= gch.cycleThreshold or alwaysCycleGC: if getOccupiedMem(gch.region) >= gch.cycleThreshold or alwaysCycleGC:
@ -927,8 +927,7 @@ proc collectCTBody(gch: var GcHeap, ignoreStackAndRegisters = false) =
gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() * gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
CycleIncrease) CycleIncrease)
gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold) gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
if not ignoreStackAndRegisters: unmarkStackAndRegisters(gch)
unmarkStackAndRegisters(gch)
sysAssert(allocInv(gch.region), "collectCT: end") sysAssert(allocInv(gch.region), "collectCT: end")
when withRealTime: when withRealTime:
@ -972,17 +971,28 @@ when withRealTime:
proc GC_setMaxPause*(MaxPauseInUs: int) = proc GC_setMaxPause*(MaxPauseInUs: int) =
gch.maxPause = MaxPauseInUs.toNano gch.maxPause = MaxPauseInUs.toNano
proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool, ignoreStackAndRegisters: bool) = proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) =
acquire(gch) acquire(gch)
gch.maxPause = us.toNano gch.maxPause = us.toNano
if (gch.zct.len >= ZctThreshold or (cycleGC and if (gch.zct.len >= ZctThreshold or (cycleGC and
getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or
strongAdvice: strongAdvice:
collectCTBody(gch, ignoreStackAndRegisters) collectCTBody(gch)
release(gch) release(gch)
proc GC_step*(us: int, strongAdvice, ignoreStackAndRegisters = false) = proc GC_step*(us: int, strongAdvice = false, stackSize = -1) {.noinline.} =
GC_step(gch, us, strongAdvice, ignoreStackAndRegisters) var stackTop {.volatile.}: pointer
let prevStackBottom = gch.stackBottom
if stackSize >= 0:
stackTop = addr(stackTop)
when stackIncreases:
gch.stackBottom = cast[pointer](
cast[ByteAddress](stackTop) - sizeof(pointer) * 6 - stackSize)
else:
gch.stackBottom = cast[pointer](
cast[ByteAddress](stackTop) + sizeof(pointer) * 6 + stackSize)
GC_step(gch, us, strongAdvice)
gch.stackBottom = prevStackBottom
when not defined(useNimRtl): when not defined(useNimRtl):
proc GC_disable() = proc GC_disable() =

View file

@ -894,18 +894,18 @@ proc unmarkStackAndRegisters(gch: var GcHeap) =
decRef(d[i]) decRef(d[i])
gch.decStack.len = 0 gch.decStack.len = 0
proc collectCTBody(gch: var GcHeap, ignoreStackAndRegisters = false) = proc collectCTBody(gch: var GcHeap) =
when withRealTime: when withRealTime:
let t0 = getticks() let t0 = getticks()
sysAssert(allocInv(gch.region), "collectCT: begin") sysAssert(allocInv(gch.region), "collectCT: begin")
when not defined(nimCoroutines):
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
sysAssert(gch.decStack.len == 0, "collectCT") sysAssert(gch.decStack.len == 0, "collectCT")
prepareForInteriorPointerChecking(gch.region) prepareForInteriorPointerChecking(gch.region)
if not ignoreStackAndRegisters: markStackAndRegisters(gch)
when not defined(nimCoroutines): gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize()) inc(gch.stat.stackScans)
markStackAndRegisters(gch)
gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
inc(gch.stat.stackScans)
if collectZCT(gch): if collectZCT(gch):
when cycleGC: when cycleGC:
if getOccupiedMem(gch.region) >= gch.cycleThreshold or alwaysCycleGC: if getOccupiedMem(gch.region) >= gch.cycleThreshold or alwaysCycleGC:
@ -914,8 +914,7 @@ proc collectCTBody(gch: var GcHeap, ignoreStackAndRegisters = false) =
gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() * gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
CycleIncrease) CycleIncrease)
gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold) gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
if not ignoreStackAndRegisters: unmarkStackAndRegisters(gch)
unmarkStackAndRegisters(gch)
sysAssert(allocInv(gch.region), "collectCT: end") sysAssert(allocInv(gch.region), "collectCT: end")
when withRealTime: when withRealTime:
@ -950,15 +949,26 @@ when withRealTime:
proc GC_setMaxPause*(MaxPauseInUs: int) = proc GC_setMaxPause*(MaxPauseInUs: int) =
gch.maxPause = MaxPauseInUs.toNano gch.maxPause = MaxPauseInUs.toNano
proc GC_step(gch: var GcHeap, us: int, strongAdvice, ignoreStackAndRegisters: bool) = proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) =
gch.maxPause = us.toNano gch.maxPause = us.toNano
if (gch.zct.len >= ZctThreshold or (cycleGC and if (gch.zct.len >= ZctThreshold or (cycleGC and
getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or
strongAdvice: strongAdvice:
collectCTBody(gch, ignoreStackAndRegisters) collectCTBody(gch)
proc GC_step*(us: int, strongAdvice, ignoreStackAndRegisters = false) = proc GC_step*(us: int, strongAdvice = false, stackSize = -1) {.noinline.} =
GC_step(gch, us, strongAdvice, ignoreStackAndRegisters) var stackTop {.volatile.}: pointer
let prevStackBottom = gch.stackBottom
if stackSize >= 0:
stackTop = addr(stackTop)
when stackIncreases:
gch.stackBottom = cast[pointer](
cast[ByteAddress](stackTop) - sizeof(pointer) * 6 - stackSize)
else:
gch.stackBottom = cast[pointer](
cast[ByteAddress](stackTop) + sizeof(pointer) * 6 + stackSize)
GC_step(gch, us, strongAdvice)
gch.stackBottom = prevStackBottom
when not defined(useNimRtl): when not defined(useNimRtl):
proc GC_disable() = proc GC_disable() =