Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3299.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3299
Author: eem
Time: 13 January 2023, 2:24:26.105002 pm
UUID: 35ad78ad-0942-4eac-8933-d519dee50a12
Ancestors: VMMaker.oscog-eem.3298
Add a useful comment to benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone to compare it to benchmarkFollowForwardersInStackZone.
Here's the comparison, on a MacBook Pro (16-inch, 2021), Apple M1 Max, Cores: 10 (8 performance and 2 efficiency):
11.176 usecs average for ollowForwardersInStackZone
14.501 usecs average for followForwardingPointersOfReceiverAndTemporariesInStackZone
And here's stats for jitting all of CompiledCode's methods:
min max average
2.417 79.257 9.674 usecs to JIT
2 20 5.938 number of literals
1 106 17.464 number of bytecodes
=============== Diff against VMMaker.oscog-eem.3298 ===============
Item was changed:
----- Method: CoInterpreter class>>benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone (in category 'benchmarks') -----
benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone
"Answer the elapsed time in microseconds for followForwardingPointersOfReceiverAndTemporariesInStackZone."
| ticksPerMicrosecond |
ticksPerMicrosecond := Time highResClockTicksPerMillisecond / 1000.0.
^self primitiveBenchmarkFollowForwardersOfReceiverAndTemporariesInStackZone / ticksPerMicrosecond
+ "self benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone"
+ "| goDeep |
+ goDeep := #defined.
+ goDeep := [:depth| | laurel hardy |
+ depth < 1
+ ifTrue:
+ [laurel := OrderedCollection new.
+ hardy := laurel copy.
+ 10 timesRepeat:
+ [laurel add: self benchmarkFollowForwardersInStackZone.
+ hardy add: self benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone].
+ { laurel. hardy } collect: [:stats| stats average roundTo: 0.001]]
+ ifFalse:
+ [goDeep value: depth - 1]].
+ goDeep value: 1000"!
- "self benchmarkFollowForwardingPointersOfReceiverAndTemporariesInStackZone"!
Branch: refs/heads/virtend
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: f8839669304932afd957b46907f7cb061f6e1e05
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/f8839669304932afd9…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2023-01-13 (Fri, 13 Jan 2023)
Changed paths:
M src/spur32.cog/cogit.h
M src/spur32.cog/cointerp.c
M src/spur32.cog/cointerp.h
M src/spur32.cog/gcc3x-cointerp.c
M src/spur32.sista/cogit.h
M src/spur32.sista/cointerp.c
M src/spur32.sista/cointerp.h
M src/spur32.sista/gcc3x-cointerp.c
M src/spur64.cog/cogit.h
M src/spur64.cog/cointerp.c
M src/spur64.cog/cointerp.h
M src/spur64.cog/gcc3x-cointerp.c
M src/spur64.sista/cogit.h
M src/spur64.sista/cointerp.c
M src/spur64.sista/cointerp.h
M src/spur64.sista/gcc3x-cointerp.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3298
Fix a slip in followForwardingPointersOfReceiverAndTemporariesInStackZone,
which has no business calling markAndTrace: :-)
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 959b8c524746b49fb71029465bfe23c44aa9d6eb
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/959b8c524746b49fb7…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2023-01-13 (Fri, 13 Jan 2023)
Changed paths:
M src/spur32.cog/cogit.h
M src/spur32.cog/cointerp.c
M src/spur32.cog/cointerp.h
M src/spur32.cog/gcc3x-cointerp.c
M src/spur32.sista/cogit.h
M src/spur32.sista/cointerp.c
M src/spur32.sista/cointerp.h
M src/spur32.sista/gcc3x-cointerp.c
M src/spur64.cog/cogit.h
M src/spur64.cog/cointerp.c
M src/spur64.cog/cointerp.h
M src/spur64.cog/gcc3x-cointerp.c
M src/spur64.sista/cogit.h
M src/spur64.sista/cointerp.c
M src/spur64.sista/cointerp.h
M src/spur64.sista/gcc3x-cointerp.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3298
Fix a slip in followForwardingPointersOfReceiverAndTemporariesInStackZone,
which has no business calling markAndTrace: :-)
Branch: refs/heads/virtend
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: f185ad87ad2fe97cc5ba61929b1f0cbac07583e8
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/f185ad87ad2fe97cc5…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2023-01-13 (Fri, 13 Jan 2023)
Changed paths:
M src/plugins/CroquetPlugin/CroquetPlugin.c
M src/plugins/Squeak3D/Squeak3D.c
M src/spur32.cog.lowcode/cogit.h
M src/spur32.cog.lowcode/cogitARMv5.c
M src/spur32.cog.lowcode/cogitIA32.c
M src/spur32.cog.lowcode/cointerp.c
M src/spur32.cog.lowcode/cointerp.h
M src/spur32.cog.lowcode/gcc3x-cointerp.c
M src/spur32.cog/cogit.h
M src/spur32.cog/cogitARMv5.c
M src/spur32.cog/cogitIA32.c
M src/spur32.cog/cointerp.c
M src/spur32.cog/cointerp.h
M src/spur32.cog/cointerpmt.c
M src/spur32.cog/cointerpmt.h
M src/spur32.cog/gcc3x-cointerp.c
M src/spur32.cog/gcc3x-cointerpmt.c
M src/spur32.sista/cogit.h
M src/spur32.sista/cogitARMv5.c
M src/spur32.sista/cogitIA32.c
M src/spur32.sista/cointerp.c
M src/spur32.sista/cointerp.h
M src/spur32.sista/gcc3x-cointerp.c
M src/spur32.stack.lowcode/gcc3x-interp.c
M src/spur32.stack.lowcode/interp.c
M src/spur32.stack/gcc3x-interp.c
M src/spur32.stack/interp.c
M src/spur32.stack/validImage.c
M src/spur64.cog.lowcode/cogit.h
M src/spur64.cog.lowcode/cogitARMv8.c
M src/spur64.cog.lowcode/cogitX64SysV.c
M src/spur64.cog.lowcode/cogitX64WIN64.c
M src/spur64.cog.lowcode/cointerp.c
M src/spur64.cog.lowcode/cointerp.h
M src/spur64.cog.lowcode/gcc3x-cointerp.c
M src/spur64.cog/cogit.h
M src/spur64.cog/cogitARMv8.c
M src/spur64.cog/cogitX64SysV.c
M src/spur64.cog/cogitX64WIN64.c
M src/spur64.cog/cointerp.c
M src/spur64.cog/cointerp.h
M src/spur64.cog/cointerpmt.c
M src/spur64.cog/cointerpmt.h
M src/spur64.cog/gcc3x-cointerp.c
M src/spur64.cog/gcc3x-cointerpmt.c
M src/spur64.sista/cogit.h
M src/spur64.sista/cogitARMv8.c
M src/spur64.sista/cogitX64SysV.c
M src/spur64.sista/cogitX64WIN64.c
M src/spur64.sista/cointerp.c
M src/spur64.sista/cointerp.h
M src/spur64.sista/gcc3x-cointerp.c
M src/spur64.stack.lowcode/gcc3x-interp.c
M src/spur64.stack.lowcode/interp.c
M src/spur64.stack/gcc3x-interp.c
M src/spur64.stack/interp.c
M src/spur64.stack/validImage.c
M src/v3.cog/cogit.h
M src/v3.cog/cogitARMv5.c
M src/v3.cog/cogitIA32.c
M src/v3.cog/cointerp.c
M src/v3.cog/cointerp.h
M src/v3.cog/gcc3x-cointerp.c
M src/v3.stack/gcc3x-interp.c
M src/v3.stack/interp.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3297/Balloon3D-Plugins-eem.20
Include a small suite of VM benchmark primitives to measure the time taken by
operations that are too short-lived to want to time them (because timing can
have significant overhead).
Add an abstraction for identifying full block methods and use it in asserts.
Refactor followForwardingPointersInStackZone: to followForwardingPointersInStackZone
since it makes no use of the becomeEffectFlags argument.
Make sure all uses of cloneObject: in plugins test the result appropriately.
Make sure the head frame pointers are written back when cloning a context in
primitiveClone.
Simplify the TempVectReadBarrier testing in Stack/CoInterpreter, adding one
method and deleting four, and testing TempVectReadBarrier in a single method
only (albeit one that is overridden in CoInterpreter).
Given that better forwarding machinery was written over time, use a slightly
better form for dealing with potential forwarding in the pushFullClosure bytecode,
and neaten StackInterpreter>>pushLiteralVariable:/storeLiteralVariable:withValue:
to use it.
Branch: refs/heads/Cog
Home: https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 143b725584f080a045c7f2cff88a58978f650620
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/143b725584f080a045…
Author: Eliot Miranda <eliot.miranda(a)gmail.com>
Date: 2023-01-13 (Fri, 13 Jan 2023)
Changed paths:
M src/plugins/CroquetPlugin/CroquetPlugin.c
M src/plugins/Squeak3D/Squeak3D.c
M src/spur32.cog.lowcode/cogit.h
M src/spur32.cog.lowcode/cogitARMv5.c
M src/spur32.cog.lowcode/cogitIA32.c
M src/spur32.cog.lowcode/cointerp.c
M src/spur32.cog.lowcode/cointerp.h
M src/spur32.cog.lowcode/gcc3x-cointerp.c
M src/spur32.cog/cogit.h
M src/spur32.cog/cogitARMv5.c
M src/spur32.cog/cogitIA32.c
M src/spur32.cog/cointerp.c
M src/spur32.cog/cointerp.h
M src/spur32.cog/cointerpmt.c
M src/spur32.cog/cointerpmt.h
M src/spur32.cog/gcc3x-cointerp.c
M src/spur32.cog/gcc3x-cointerpmt.c
M src/spur32.sista/cogit.h
M src/spur32.sista/cogitARMv5.c
M src/spur32.sista/cogitIA32.c
M src/spur32.sista/cointerp.c
M src/spur32.sista/cointerp.h
M src/spur32.sista/gcc3x-cointerp.c
M src/spur32.stack.lowcode/gcc3x-interp.c
M src/spur32.stack.lowcode/interp.c
M src/spur32.stack/gcc3x-interp.c
M src/spur32.stack/interp.c
M src/spur32.stack/validImage.c
M src/spur64.cog.lowcode/cogit.h
M src/spur64.cog.lowcode/cogitARMv8.c
M src/spur64.cog.lowcode/cogitX64SysV.c
M src/spur64.cog.lowcode/cogitX64WIN64.c
M src/spur64.cog.lowcode/cointerp.c
M src/spur64.cog.lowcode/cointerp.h
M src/spur64.cog.lowcode/gcc3x-cointerp.c
M src/spur64.cog/cogit.h
M src/spur64.cog/cogitARMv8.c
M src/spur64.cog/cogitX64SysV.c
M src/spur64.cog/cogitX64WIN64.c
M src/spur64.cog/cointerp.c
M src/spur64.cog/cointerp.h
M src/spur64.cog/cointerpmt.c
M src/spur64.cog/cointerpmt.h
M src/spur64.cog/gcc3x-cointerp.c
M src/spur64.cog/gcc3x-cointerpmt.c
M src/spur64.sista/cogit.h
M src/spur64.sista/cogitARMv8.c
M src/spur64.sista/cogitX64SysV.c
M src/spur64.sista/cogitX64WIN64.c
M src/spur64.sista/cointerp.c
M src/spur64.sista/cointerp.h
M src/spur64.sista/gcc3x-cointerp.c
M src/spur64.stack.lowcode/gcc3x-interp.c
M src/spur64.stack.lowcode/interp.c
M src/spur64.stack/gcc3x-interp.c
M src/spur64.stack/interp.c
M src/spur64.stack/validImage.c
M src/v3.cog/cogit.h
M src/v3.cog/cogitARMv5.c
M src/v3.cog/cogitIA32.c
M src/v3.cog/cointerp.c
M src/v3.cog/cointerp.h
M src/v3.cog/gcc3x-cointerp.c
M src/v3.stack/gcc3x-interp.c
M src/v3.stack/interp.c
Log Message:
-----------
CogVM source as per VMMaker.oscog-eem.3297/Balloon3D-Plugins-eem.20
Include a small suite of VM benchmark primitives to measure the time taken by
operations that are too short-lived to want to time them (because timing can
have significant overhead).
Add an abstraction for identifying full block methods and use it in asserts.
Refactor followForwardingPointersInStackZone: to followForwardingPointersInStackZone
since it makes no use of the becomeEffectFlags argument.
Make sure all uses of cloneObject: in plugins test the result appropriately.
Make sure the head frame pointers are written back when cloning a context in
primitiveClone.
Simplify the TempVectReadBarrier testing in Stack/CoInterpreter, adding one
method and deleting four, and testing TempVectReadBarrier in a single method
only (albeit one that is overridden in CoInterpreter).
Given that better forwarding machinery was written over time, use a slightly
better form for dealing with potential forwarding in the pushFullClosure bytecode,
and neaten StackInterpreter>>pushLiteralVariable:/storeLiteralVariable:withValue:
to use it.
Tom Braun uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog.seperateMarking-WoC.3305.mcz
==================== Summary ====================
Name: VMMaker.oscog.seperateMarking-WoC.3305
Author: WoC
Time: 13 January 2023, 12:50:43.423711 am
UUID: 291d0777-24d3-47f4-8046-02acd6de34ad
Ancestors: VMMaker.oscog.seperateMarking-WoC.3304
handle pinned objects during compaction
- try to keep track of them during marking
- abort compaction if we find one in the to be compacted segment
- add assert to forward:to: to forbid forwarding pinned objects
- naive approach to scheduling incremental compacts (needs more work, just an experiment)
- added comment why we replace the pointer in the remembered set
=============== Diff against VMMaker.oscog.seperateMarking-WoC.3304 ===============
Item was changed:
----- Method: SpurCountingIncrementalMarker>>setIsMarkedOf: (in category 'header access') -----
setIsMarkedOf: objOop
| segmentContainingObject |
super setIsMarkedOf: objOop.
self flag: #Todo. "we need a more efficient way to get the segment"
segmentContainingObject := manager segmentManager segmentContainingObj: objOop.
self
setUsedMemory: (self getUsedMemoryOf: segmentContainingObject) + (manager bytesInBody: objOop)
for: segmentContainingObject.
self
setLifeObjectCount: (self getLifeObjectCountOf: segmentContainingObject) + 1
+ for: segmentContainingObject.
+
+ (manager isPinned: objOop)
+ ifTrue: [segmentContainingObject containsPinned: true]!
- for: segmentContainingObject!
Item was changed:
----- Method: SpurIncremental2PhaseGarbageCollector>>doIncrementalCollect (in category 'as yet unclassified') -----
doIncrementalCollect
| startTime |
phase = InMarkingPhase
ifTrue: [ | finishedMarking |
marker isCurrentlyMarking
+ ifFalse: [self assert: manager allObjectsUnmarked.
+ manager segmentManager prepareForGlobalSweep].
- ifFalse: [self assert: manager allObjectsUnmarked].
coInterpreter cr; print: 'start marking '; tab; flush.
finishedMarking := marker incrementalMarkObjects.
"self assert: manager validObjectColors."
finishedMarking
ifTrue: [
"manager allPastSpaceObjectsDo: [:obj | self assert: (manager isWhite: obj)]."
"when sweeping the mutator needs to allocate new objects black as we do not have any information about them.
We only know if they should get swept after the next marking -> keep them alive for this cycle"
self allocatorShouldAllocateBlack: true.
compactor setInitialSweepingEntity.
phase := InSweepingPhase.
"marking is done and thus all forwarding from the last compaction references are resolved
-> we can use the now free segments that were compacted during the last cycle"
compactor freePastSegmentsAndSetSegmentToFill.
compactor assertNoSegmentBeingCompacted.
self assert: manager noObjectGrey.
coInterpreter cr; print: 'finish marking '; tab; flush.
startTime := coInterpreter ioUTCMicrosecondsNow.
manager
setCheckForLeaks: GCCheckFreeSpace + GCModeFull;
runLeakCheckerFor: GCModeFull excludeUnmarkedObjs: true classIndicesShouldBeValid: true;
checkFreeSpace: GCModeFull.
manager clearLeakMapAndMapMarkedOrYoungObjects.
coInterpreter checkStackIntegrity.
coInterpreter cr; print: 'time for internal check: '; printNum: coInterpreter ioUTCMicrosecondsNow - startTime; tab; flush.
0 to: manager numSegments - 1
do: [:i | | segInfo |
segInfo := manager segInfoAt: i.
coInterpreter cr; print: 'occupation from marking: '; printNum: (compactor occupationOf: segInfo) * 100; tab;
print: '('; printNum: (marker getLifeObjectCountOf: segInfo); print: ' objects -> ' ;printNum: (compactor sizeClaimedIn: segInfo) ; print: ' bytes)' ;flush].
manager printSegmentOccupationFromMarkedObjects.
^ self]
ifFalse: [coInterpreter cr; print: 'finish marking pass'; tab; flush. "manager runLeakCheckerFor: GCModeIncremental"]].
phase = InSweepingPhase
ifTrue: [
coInterpreter cr; print: 'start sweeping '; tab; flush.
compactor incrementalSweepAndCompact
ifTrue: [
self allocatorShouldAllocateBlack: false.
self assert: manager allObjectsWhite.
"self assert: manager allObjectsUnmarked."
coInterpreter cr; print: 'finish sweeping '; tab; flush.
startTime := coInterpreter ioUTCMicrosecondsNow.
manager
setCheckForLeaks: GCCheckFreeSpace + GCModeFull;
runLeakCheckerFor: GCModeFull;
checkFreeSpace: GCModeFull.
coInterpreter cr; print: 'time for internal check: '; printNum: coInterpreter ioUTCMicrosecondsNow - startTime; tab; flush.
phase := InMarkingPhase.
+
+ fullGCWanted := false.
^ self]]!
Item was added:
+ ----- Method: SpurIncrementalCompactingSweeper>>abortCompactionAt:in: (in category 'incremental compact') -----
+ abortCompactionAt: entity in: segInfo
+
+ <var: 'segInfo' type: #'SpurSegmentInfo *'>
+ "somebody allocated a new object we did not knew about at the moment of planning :(
+ -> it does not fit anymore and we cannot free the whole segment or the object is pinned. Make sure to
+ unmark the segment as beeing compacted as it would be completetly freed otherwise!!"
+ (manager isPinned: entity)
+ ifTrue: [coInterpreter cr; print: 'segments contains pinned object. ']
+ ifFalse: [coInterpreter cr; print: 'segments if full. '].
+ coInterpreter cr; print: 'Abort compacting of: '; printHex: segInfo segStart ; tab; flush.
+ self
+ unmarkSegment: self currentSegment
+ asBeingCompactedAndSaveEndOfCompactionAddress: entity.
+
+ "we need to sweep the rest of the segment. As the segment is not marked to be compacted
+ anymore sweepOrCompactFromCurrentObject will decide to sweep it. We want to start
+ sweeping from the current entity, therefore setting currentObject to it and we have to protect
+ it from beeing freed (with marking it) as it was marked previously and after us unmarking it here would
+ get collected incorrectly"
+ manager setIsMarkedOf: entity to: true.
+ currentObject := entity.!
Item was changed:
----- Method: SpurIncrementalCompactingSweeper>>compactSegment:freeStart:segIndex: (in category 'incremental compact') -----
compactSegment: segInfo freeStart: initialFreeStart segIndex: segIndex
<var: 'segInfo' type: #'SpurSegmentInfo *'>
| fillStart |
fillStart := initialFreeStart.
self deny: segIndex = 0. "Cannot compact seg 0"
manager segmentManager
allEntitiesInSegment: segInfo
exceptTheLastBridgeDo:
[:entity |
(manager isFreeObject: entity)
ifTrue:
[manager detachFreeObject: entity.
currentsCycleSeenObjectCount := currentsCycleSeenObjectCount + 1.
"To avoid confusing too much Spur (especially the leak/free checks), we mark the free chunk as a word object."
manager set: entity classIndexTo: manager wordSizeClassIndexPun formatTo: manager wordIndexableFormat]
ifFalse:
+ [
+ (manager isPinned: entity)
+ ifTrue: [manager debugger].
+
+ (manager isMarked: entity)
+ ifTrue: [| bytesToCopy |
+ "note: we copy even forwarders if they are marked so they cannot get lost"
+ manager makeWhite: entity.
+
+ "I really hat that this can happen :( . The marker will keep track of which segments contain pinned objects.
+ If the pinned object is created during sweeping and compacting, we cannot know about it while working at
+ our plan we did at the start of sweeping and compacting"
+ (manager isPinned: entity)
+ ifTrue: [self abortCompactionAt: entity in: segInfo].
- [ (manager isMarked: entity)
- ifTrue: [manager makeWhite: entity.
- "During the mutator runs new forwarding references can be created. Ignore them as they get resolved with the other
- forwarders in this segment in the next marking pass"
- (manager isForwarded: entity)
- ifFalse:[| bytesToCopy |
- "Copy the object in segmentToFill and replace it by a forwarder."
- bytesToCopy := manager bytesInBody: entity.
-
- (self would: fillStart + bytesToCopy overflowSegment: segmentToFill)
- ifFalse: [
- self handleWouldBeCompactionOverflow: entity in: segInfo.
+ bytesToCopy := manager bytesInBody: entity.
+
+ (self would: fillStart + bytesToCopy overflowSegment: segmentToFill)
+ ifFalse: [
+ self abortCompactionAt: entity in: segInfo.
- ^ fillStart].
-
- "let's make copying more expensive. Number is just a guess"
- currentsCycleSeenObjectCount := currentsCycleSeenObjectCount + 100.
- self migrate: entity sized: bytesToCopy to: fillStart.
+ ^ fillStart].
+
+ "let's make copying more expensive. Number is just a guess"
+ currentsCycleSeenObjectCount := currentsCycleSeenObjectCount + 100.
+ self migrate: entity sized: bytesToCopy to: fillStart.
+
+ fillStart := fillStart + bytesToCopy.
+ self assert: (self oop: fillStart isLessThan: (segmentToFill segLimit - manager bridgeSize))]
- fillStart := fillStart + bytesToCopy.
- self assert: (self oop: fillStart isLessThan: (segmentToFill segLimit - manager bridgeSize))]]
ifFalse: [self handleUnmarkedEntity: entity]]].
"we want to advance to the next segment from the bridge"
currentObject := currentSegmentsBridge.
^ fillStart!
Item was removed:
- ----- Method: SpurIncrementalCompactingSweeper>>handleWouldBeCompactionOverflow:in: (in category 'compaction planning') -----
- handleWouldBeCompactionOverflow: entity in: segInfo
-
- "somebody allocated a new object we did not knew about at the moment of planning :(
- -> it does not fit anymore and we cannot free the whole segment. Make sure to
- unmark the segment as beeing compacted as it would be completetly freed otherwise!!"
- coInterpreter cr; print: 'segments if full. Abort compacting of: '; printHex: segInfo segStart ; tab; flush.
- self
- unmarkSegment: self currentSegment
- asBeingCompactedAndSaveEndOfCompactionAddress: entity.
-
- "we need to sweep the rest of the segment. As the segment is not marked to be compacted
- anymore sweepOrCompactFromCurrentObject will decide to sweep it. We want to start
- sweeping from the current entity, therefore setting currentObject to it and we have to protect
- it from beeing freed (with marking it) as it was marked previously and after us unmarking it here would
- get collected incorrectly"
- manager setIsMarkedOf: entity to: true.
- currentObject := entity.!
Item was changed:
----- Method: SpurIncrementalCompactingSweeper>>initialize (in category 'initialize-release') -----
initialize
isCurrentlyWorking := false.
currentSegmentsIndex := 0.
currentsCycleSeenObjectCount := 0.
currentSegmentsBridge := nil.
currentObject := nil.
segmentToFill := nil.
shouldCompact := false.
currentCopyToPointer := nil.
+ maxObjectsToFree := InitialMaxObjectsToFree!
- maxObjectsToFree := MaxObjectsToFree!
Item was changed:
----- Method: SpurIncrementalCompactingSweeper>>migrate:sized:to: (in category 'incremental compact') -----
migrate: obj sized: bytesToCopy to: address
| copy |
self assert: (manager isPinned: obj) not.
manager memcpy: address asVoidPointer _: (manager startOfObject: obj) asVoidPointer _: bytesToCopy.
copy := manager objectStartingAt: address.
(manager isRemembered: copy) ifTrue:
+ ["replace the pointer in the remembered set instead of leaving it there. It could get hidden inside the free chunk that will get
+ created after the next marking phase and the sweeper won't be able to find it and make the scavenger forget it."
+ scavenger remember: copy insteadOf: obj].
- [scavenger remember: copy insteadOf: obj].
manager forward: obj to: (manager objectStartingAt: address).
^ copy!
Item was changed:
SpurGarbageCollector subclass: #SpurIncrementalGarbageCollector
+ instanceVariableNames: 'phase allAtOnceMarker checkSetGCFlags stopTheWorldGC fullGCWanted'
- instanceVariableNames: 'phase allAtOnceMarker checkSetGCFlags stopTheWorldGC'
classVariableNames: 'InCompactingPhase InMarkingPhase InSweepingPhase'
poolDictionaries: ''
category: 'VMMaker-SpurGarbageCollector'!
!SpurIncrementalGarbageCollector commentStamp: 'WoC 1/5/2023 21:36' prior: 0!
A SpurIncrementalGarbageCollector is a garbage collection algorithm. The GC is a mark and sweep with an additional compaction if certain conditions are fulfilled.
This class manages SpurIncrementalMarker and SpurIncrementalSweepAndCompact (which in turn manages SpurIncrementalCompactor and SpurIncrementalSweeper). The 3 classes
implementing the GC are therefore SpurIncrementalMarker, SpurIncrementalSweeper and SpurIncrementalCompactor.
Instance Variables
allAtOnceMarker: <SpurAllAtOnceMarker>
checkSetGCFlags: <Bool>
phase: <Number (InMarkingPhase|InSweepingPhase|InCompactingPhase)>
allAtOnceMarker
- an instance of SpurAllAtOnceMarker. We sometimes need parts of the old (stop-the-world) gc algorithm. This is the marking algorithm we can use through static polymorphism
checkSetGCFlags
- should we check if it ok to set gc flags or not
phase
- in which phase is the gc algorithm at the moment. Is either InMarkingPhase, InSweepingPhase or InCompactingPhase
!
Item was changed:
----- Method: SpurIncrementalGarbageCollector>>doIncrementalCollect (in category 'as yet unclassified') -----
doIncrementalCollect
| startTime |
phase = InMarkingPhase
ifTrue: [ | finishedMarking |
marker isCurrentlyMarking
ifFalse: [self assert: manager allObjectsUnmarked].
coInterpreter cr; print: 'start marking '; tab; flush.
finishedMarking := marker incrementalMarkObjects.
"self assert: manager validObjectColors."
finishedMarking
ifTrue: [
manager allPastSpaceObjectsDo: [:obj | self assert: (manager isWhite: obj)].
"when sweeping the mutator needs to allocate new objects black as we do not have any information about them.
We only know if they should get swept after the next marking -> keep them alive for this cycle"
self allocatorShouldAllocateBlack: true.
compactor setInitialSweepingEntity.
phase := InSweepingPhase.
"marking is done and thus all forwarding from the last compaction references are resolved
-> we can use the now free segments that were compacted during the last cycle"
compactor freePastSegmentsAndSetSegmentToFill.
+ manager segmentManager prepareForGlobalSweep.
+
self assert: manager noObjectGrey.
coInterpreter cr; print: 'finish marking '; tab; flush.
startTime := coInterpreter ioUTCMicrosecondsNow.
manager
setCheckForLeaks: GCCheckFreeSpace + GCModeFull;
runLeakCheckerFor: GCModeFull excludeUnmarkedObjs: true classIndicesShouldBeValid: true;
checkFreeSpace: GCModeFull.
coInterpreter cr; print: 'time for internal check: '; printNum: coInterpreter ioUTCMicrosecondsNow - startTime; tab; flush.
^ self]
ifFalse: [coInterpreter cr; print: 'finish marking pass'; tab; flush.manager runLeakCheckerFor: GCModeIncremental]].
phase = InSweepingPhase
ifTrue: [
coInterpreter cr; print: 'start sweeping '; tab; flush.
compactor incrementalSweep
ifTrue: [
self allocatorShouldAllocateBlack: false.
manager allOldSpaceObjectsDo: [:ea | self assert: (manager isWhite: ea) ].
"self assert: manager allObjectsUnmarked."
coInterpreter cr; print: 'finish sweeping '; tab; flush.
startTime := coInterpreter ioUTCMicrosecondsNow.
manager
setCheckForLeaks: GCCheckFreeSpace + GCModeFull;
runLeakCheckerFor: GCModeFull;
checkFreeSpace: GCModeFull.
coInterpreter cr; print: 'time for internal check: '; printNum: coInterpreter ioUTCMicrosecondsNow - startTime; tab; flush.
compactor assertNoSegmentBeingCompacted.
phase := InCompactingPhase.
^ self]].
phase = InCompactingPhase
ifTrue: [
"self cCode: 'raise(SIGINT)'."
coInterpreter cr; print: 'start compacting '; tab; flush.
compactor isCurrentlyCompacting
ifFalse: [manager printFreeSpaceStatistics].
compactor incrementalCompact
ifTrue: [
coInterpreter cr; print: 'finish compacting '; tab; flush.
startTime := coInterpreter ioUTCMicrosecondsNow.
manager
setCheckForLeaks: GCCheckFreeSpace + GCModeFull;
runLeakCheckerFor: GCModeFull;
checkFreeSpace: GCModeFull.
coInterpreter cr; print: 'time for internal check: '; printNum: coInterpreter ioUTCMicrosecondsNow - startTime; tab; flush.
phase := InMarkingPhase.
+ fullGCWanted := false.
+
^ self]]!
Item was changed:
----- Method: SpurIncrementalGarbageCollector>>doScavenge: (in category 'scavenge') -----
doScavenge: tenuringCriterion
"The inner shell for scavenge, abstrascted out so globalGarbageCollect can use it."
<inline: false>
manager doAllocationAccountingForScavenge.
manager gcPhaseInProgress: ScavengeInProgress.
manager pastSpaceStart: (scavenger scavenge: tenuringCriterion).
self assert: (self
oop: manager pastSpaceStart
isGreaterThanOrEqualTo: scavenger pastSpace start
andLessThanOrEqualTo: scavenger pastSpace limit).
manager freeStart: scavenger eden start.
manager gcPhaseInProgress: 0.
manager resetAllocationAccountingAfterGC.
+ (fullGCWanted or: [self numSegmentsAboutToBeFreed > 0])
+ ifTrue: [self incrementalCollect]
+ !
- self incrementalCollect!
Item was changed:
----- Method: SpurIncrementalGarbageCollector>>initialize (in category 'initialize-release') -----
initialize
super initialize.
checkSetGCFlags := true.
phase := InMarkingPhase.
+ fullGCWanted := false.
+
allAtOnceMarker := SpurAllAtOnceMarker new.
stopTheWorldGC := SpurStopTheWorldGarbageCollector new.
stopTheWorldGC marker: allAtOnceMarker.
stopTheWorldGC compactor: SpurPlanningCompactor new!
Item was changed:
----- Method: SpurIncrementalGarbageCollector>>sufficientSpaceAfterGC: (in category 'as yet unclassified') -----
sufficientSpaceAfterGC: numBytes
| heapSizePostGC |
self assert: numBytes = 0.
self scavengingGCTenuringIf: TenureByAge.
heapSizePostGC := manager segmentManager totalOldSpaceCapacity - manager totalFreeOldSpace.
(heapSizePostGC - manager heapSizeAtPreviousGC) asFloat / manager heapSizeAtPreviousGC >= manager heapGrowthToSizeGCRatio
+ ifTrue: [fullGCWanted := true] "fullGC will attempt to shrink"
- ifTrue: ["self fullGC"] "fullGC will attempt to shrink"
ifFalse: "Also attempt to shrink if there is plenty of free space and no need to GC"
[manager totalFreeOldSpace > (manager shrinkThreshold * 2) ifTrue:
[manager attemptToShrink.
^true]].
self flag: #Todo. "we probably want here something more sophisticated, like tak into account how many
objects survived tenuring in the near past and how much work is still to be done until marking is finished
and the segments get freed. Until then just assume the compacted segments get freed soon enough"
[self numSegmentsAboutToBeFreed = 0 "lets wait until we get more space"
and: [manager totalFreeOldSpace < manager growHeadroom
and: [(manager growOldSpaceByAtLeast: 0) notNil]]] whileTrue:
[manager totalFreeOldSpace >= manager growHeadroom ifTrue:
[^true]].
manager lowSpaceThreshold > manager totalFreeOldSpace ifTrue: "space is low"
[manager lowSpaceThreshold: 0. "avoid signalling low space twice"
^false].
^true!
Item was changed:
----- Method: SpurMemoryManager>>forward:to: (in category 'become implementation') -----
forward: obj1 to: obj2
+
+ self assert: (self isPinned: obj1) not.
+
self set: obj1 classIndexTo: self isForwardedObjectClassIndexPun formatTo: self forwardedFormat.
self cppIf: IMMUTABILITY ifTrue: [ self setIsImmutableOf: obj1 to: false ].
self storePointer: 0 ofForwarder: obj1 withValue: obj2.
gc maybeModifyForwarder: obj1.
"For safety make sure the forwarder has a slot count that includes its contents."
(self rawNumSlotsOf: obj1) = 0 ifTrue:
[self rawNumSlotsOf: obj1 put: 1]!