Skip to content

Commit fdd3df0

Browse files
authored
Merge pull request OpenSmalltalk#561 from pharo-project/fix/ephemeron-compaction
Fix ephemeron compaction
2 parents 809b6e0 + 7ef0b66 commit fdd3df0

File tree

4 files changed

+109
-38
lines changed

4 files changed

+109
-38
lines changed

smalltalksrc/VMMaker/Spur64BitMMLESimulator.class.st

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,6 @@ Spur64BitMMLESimulator >> freeLists [
127127
^freeLists
128128
]
129129

130-
{ #category : #'gc - global' }
131-
Spur64BitMMLESimulator >> globalGarbageCollect [
132-
"If we're /not/ a clone, clone the VM and push it over the cliff.
133-
If it survives, destroy the clone and continue. We should be OK until next time."
134-
parent ifNil:
135-
[coInterpreter cr; print: 'GC number '; print: statFullGCs; tab; flush.
136-
CloneOnGC ifTrue:
137-
[coInterpreter cloneSimulation objectMemory globalGarbageCollect.
138-
Smalltalk garbageCollect]].
139-
^super globalGarbageCollect
140-
]
141-
142130
{ #category : #'growing/shrinking memory' }
143131
Spur64BitMMLESimulator >> growOldSpaceByAtLeast: minAmmount [
144132
"Attempt to grow memory by at least minAmmount.

smalltalksrc/VMMaker/SpurMemoryManager.class.st

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10642,7 +10642,6 @@ SpurMemoryManager >> relocateObjStackForPlanningCompactor: objStack [
1064210642
to: ObjStackNextx + (self rawHashBitsOf: stackOrNil).
1064310643
stackOrNil = objStack ifTrue:
1064410644
[result := relocated].
10645-
self setHashBitsOf: stackOrNil to: 0.
1064610645
next ~= 0]
1064710646
whileTrue:
1064810647
[stackOrNil := next].

smalltalksrc/VMMaker/SpurPlanningCompactor.class.st

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ Class {
6060
'mobileStart',
6161
'objectAfterLastMobileObject',
6262
'savedFirstFieldsSpace',
63-
'savedFirstFieldsSpaceNotInOldSpace'
63+
'savedFirstFieldsSpaceNotInOldSpace',
64+
'savedFirstFieldSpaceMaxSlots'
6465
],
6566
#pools : [
6667
'VMBytecodeConstants'
@@ -162,6 +163,23 @@ SpurPlanningCompactor >> compact [
162163
self endCompaction
163164
]
164165

166+
{ #category : #'space management' }
167+
SpurPlanningCompactor >> configureSavedFirstFieldsSpaceStart: theStart limit: theLimit isOldSpace: isOldSpace [
168+
"Use teden to hold the savedFirstFieldsSpace."
169+
170+
<inline: true>
171+
| limit |
172+
limit := theLimit.
173+
savedFirstFieldSpaceMaxSlots ifNotNil: [
174+
limit := limit min:
175+
(theStart + (savedFirstFieldSpaceMaxSlots * manager bytesPerOop)) ].
176+
177+
savedFirstFieldsSpace
178+
start: theStart;
179+
limit: limit.
180+
savedFirstFieldsSpaceNotInOldSpace := isOldSpace not
181+
]
182+
165183
{ #category : #compaction }
166184
SpurPlanningCompactor >> copyAndUnmark: firstPass [
167185
"Sweep the heap, unmarking all objects and moving mobile objects to their correct positions,
@@ -351,11 +369,12 @@ SpurPlanningCompactor >> freeFrom: initialToFinger upTo: limit nextObject: nextO
351369
[manager addFreeChunkWithBytes: limit - toFinger at: toFinger]
352370
]
353371

354-
{ #category : #'instance initialization' }
372+
{ #category : #initialization }
355373
SpurPlanningCompactor >> initialize [
356374
biasForGC := true.
357375
savedFirstFieldsSpace := SpurContiguousObjStack new.
358-
savedFirstFieldsSpaceNotInOldSpace := true
376+
savedFirstFieldsSpaceNotInOldSpace := true.
377+
savedFirstFieldSpaceMaxSlots := nil.
359378
]
360379

361380
{ #category : #compaction }
@@ -463,6 +482,7 @@ SpurPlanningCompactor >> planCompactSavingForwarders [
463482
toFinger := manager startOfObject: firstFreeObject.
464483
top := savedFirstFieldsSpace start.
465484
startOfPreviousPin := 0.
485+
lastMobileObject := nil.
466486
manager allOldSpaceEntitiesFrom: firstFreeObject do:
467487
[:o|
468488
self check: o.
@@ -508,6 +528,7 @@ SpurPlanningCompactor >> planCompactSavingForwarders [
508528
[savedFirstFieldsSpace top: top - manager bytesPerOop.
509529
objectAfterLastMobileObject := manager oldSpaceObjectAfter: lastMobileObject.
510530
^false]]]].
531+
511532
"If the heap is already fully compacted there will be no lastMobileObject..."
512533
lastMobileObject ifNotNil:
513534
[savedFirstFieldsSpace top: top - manager bytesPerOop.
@@ -595,6 +616,12 @@ SpurPlanningCompactor >> repinRememberedSet [
595616
scavenger relocateRememberedSet
596617
]
597618

619+
{ #category : #'space management' }
620+
SpurPlanningCompactor >> savedFirstFieldSpaceMaxSlots: aNumber [
621+
622+
savedFirstFieldSpaceMaxSlots := aNumber
623+
]
624+
598625
{ #category : #'space management' }
599626
SpurPlanningCompactor >> savedFirstFieldsSpaceInFreeChunk [
600627
<inline: true>
@@ -947,11 +974,12 @@ SpurPlanningCompactor >> updateSavedFirstFieldsSpaceIfNecessary [
947974
{ #category : #'space management' }
948975
SpurPlanningCompactor >> useEdenForSavedFirstFieldsSpace [
949976
"Use teden to hold the savedFirstFieldsSpace."
977+
950978
<inline: true>
951-
savedFirstFieldsSpace
952-
start: scavenger eden start;
953-
limit: scavenger eden limit.
954-
savedFirstFieldsSpaceNotInOldSpace := true.
979+
self
980+
configureSavedFirstFieldsSpaceStart: scavenger eden start
981+
limit: scavenger eden limit
982+
isOldSpace: false.
955983
self deny: self savedFirstFieldsSpaceWasAllocated
956984
]
957985

@@ -960,35 +988,39 @@ SpurPlanningCompactor >> useFreeChunkForSavedFirstFieldsSpace: highestSuitableFr
960988
"Use the supplied free chunk to hold the savedFirstFieldsSpace. Invoked when
961989
eden is found not to be big enough for the job. Avoid the first few fields so as
962990
not to destroy the free chunk and there by confuse object enumeration."
991+
963992
<inline: true>
964993
self assert: (manager validFreeTreeChunk: highestSuitableFreeBlock).
965-
savedFirstFieldsSpace
966-
start: highestSuitableFreeBlock + (manager freeChunkLargerIndex * manager bytesPerOop);
967-
limit: (manager addressAfter: highestSuitableFreeBlock).
968-
savedFirstFieldsSpaceNotInOldSpace := false.
994+
self
995+
configureSavedFirstFieldsSpaceStart: highestSuitableFreeBlock
996+
+ (manager freeChunkLargerIndex * manager bytesPerOop)
997+
limit: (manager addressAfter: highestSuitableFreeBlock)
998+
isOldSpace: false.
969999
self deny: self savedFirstFieldsSpaceWasAllocated
9701000
]
9711001

9721002
{ #category : #'space management' }
9731003
SpurPlanningCompactor >> useSegmentForSavedFirstFieldsSpace: spaceEstimate [
9741004
"Attempt to allocate a memory segment large enough to hold the savedFirstFieldsSpace.
9751005
Invoked when neither eden nor a large free chunk are found to be big enough for the job."
976-
| roundedSize allocatedSize |
1006+
9771007
<var: #segAddress type: #'void *'>
1008+
| roundedSize allocatedSize |
9781009
roundedSize := spaceEstimate + 1023 // 1024 * 1024.
979-
(manager "sent to the manager so that the simulator can increase memory to simulate a new segment"
980-
sqAllocateMemorySegmentOfSize: roundedSize
981-
Above: (manager segmentManager firstGapOfSizeAtLeast: roundedSize)
982-
AllocatedSizeInto: (self cCode: [self addressOf: allocatedSize]
983-
inSmalltalk: [[:sz| allocatedSize := sz]])) ifNotNil:
984-
[:segAddress|
985-
savedFirstFieldsSpace
986-
start: segAddress asUnsignedIntegerPtr;
987-
limit: segAddress asUnsignedIntegerPtr + allocatedSize.
988-
savedFirstFieldsSpaceNotInOldSpace := true.
989-
self assert: self savedFirstFieldsSpaceWasAllocated.
990-
^true].
991-
^false
1010+
(manager
1011+
sqAllocateMemorySegmentOfSize: roundedSize
1012+
Above: (manager segmentManager firstGapOfSizeAtLeast: roundedSize)
1013+
AllocatedSizeInto: (self
1014+
cCode: [ self addressOf: allocatedSize ]
1015+
inSmalltalk: [ [ :sz | allocatedSize := sz ] ])) ifNotNil: [ :segAddress |
1016+
self
1017+
configureSavedFirstFieldsSpaceStart:
1018+
segAddress asUnsignedIntegerPtr
1019+
limit: segAddress asUnsignedIntegerPtr + allocatedSize
1020+
isOldSpace: true.
1021+
self assert: self savedFirstFieldsSpaceWasAllocated.
1022+
^ true ]. "sent to the manager so that the simulator can increase memory to simulate a new segment"
1023+
^ false
9921024
]
9931025

9941026
{ #category : #private }

smalltalksrc/VMMakerTests/VMSpurOldSpaceGarbageCollectorTest.class.st

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,58 @@ VMSpurOldSpaceGarbageCollectorTest >> testAnOldObjectReferencedFromVMVariableSho
220220
self assertHashOf: self keptObjectInVMVariable1 equals: hash
221221
]
222222

223+
{ #category : #ephemerons }
224+
VMSpurOldSpaceGarbageCollectorTest >> testCompactEphemeronQueuePass1 [
225+
226+
| ephemeron |
227+
228+
"Hole, then mourn queue"
229+
self newOldSpaceObjectWithSlots: 0.
230+
memory initializeMournQueue.
231+
232+
"Hole, then ephemeron. Does not really need to be an ephemeron for this tests, any object does it"
233+
self newOldSpaceObjectWithSlots: 0.
234+
ephemeron := self newOldSpaceObjectWithSlots: 0.
235+
self keepObjectInVMVariable1: ephemeron.
236+
memory push: ephemeron onObjStack: memory mournQueue.
237+
238+
"Compact in one pass"
239+
memory garbageCollectForSnapshot.
240+
241+
self assert: (memory sizeOfObjStack: memory mournQueue) equals: 1.
242+
self assert: memory dequeueMourner equals: self keptObjectInVMVariable1.
243+
]
244+
245+
{ #category : #ephemerons }
246+
VMSpurOldSpaceGarbageCollectorTest >> testCompactEphemeronQueuePass2 [
247+
248+
| ephemeron |
249+
250+
"For first compaction pass"
251+
"Hole, then mourn queue"
252+
self newOldSpaceObjectWithSlots: 0.
253+
memory initializeMournQueue.
254+
255+
"For second compaction pass"
256+
"Hole, then ephemeron. Does not really need to be an ephemeron for this tests, any object does it"
257+
self newOldSpaceObjectWithSlots: 0.
258+
ephemeron := self newOldSpaceObjectWithSlots: 0.
259+
self keepObjectInVMVariable1: ephemeron.
260+
memory push: ephemeron onObjStack: memory mournQueue.
261+
262+
"Set the number of objects to compact per compact Phase.
263+
We set N=1 to make two compaction phases.
264+
The first phase will compact the mourn queue.
265+
The second phase will compact the ephemeron."
266+
memory compactor savedFirstFieldSpaceMaxSlots: 1.
267+
268+
"Compact"
269+
memory garbageCollectForSnapshot.
270+
271+
self assert: (memory sizeOfObjStack: memory mournQueue) equals: 1.
272+
self assert: memory dequeueMourner equals: self keptObjectInVMVariable1.
273+
]
274+
223275
{ #category : #'tests-OldSpaceSize' }
224276
VMSpurOldSpaceGarbageCollectorTest >> testDoNotCollectRoots [
225277

0 commit comments

Comments
 (0)