3333import com .oracle .svm .core .config .ConfigurationValues ;
3434import com .oracle .svm .core .genscavenge .AlignedHeapChunk ;
3535import com .oracle .svm .core .genscavenge .HeapChunk ;
36+ import com .oracle .svm .core .genscavenge .HeapParameters ;
3637import com .oracle .svm .core .genscavenge .ObjectHeaderImpl ;
3738import com .oracle .svm .core .genscavenge .Space ;
3839import com .oracle .svm .core .genscavenge .remset .BrickTable ;
4748 * or overwrite dead objects.
4849 */
4950public final class PlanningVisitor implements AlignedHeapChunk .Visitor {
51+ private static final ResetNewLocationsForSweepingVisitor RESET_NEW_LOCATIONS_FOR_SWEEPING_VISITOR = new ResetNewLocationsForSweepingVisitor ();
52+
5053 private AlignedHeapChunk .AlignedHeader allocChunk ;
5154 private Pointer allocPointer ;
5255
@@ -62,7 +65,9 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
6265 Pointer objSeq = AlignedHeapChunk .getObjectsStart (chunk );
6366 UnsignedWord gapSize = WordFactory .zero ();
6467 UnsignedWord objSeqSize = WordFactory .zero ();
68+
6569 UnsignedWord brickIndex = WordFactory .zero ();
70+ UnsignedWord totalUnusedBytes = WordFactory .zero ();
6671
6772 /* Initialize the move info structure at the chunk's object start location. */
6873 ObjectMoveInfo .setNewAddress (objSeq , allocPointer );
@@ -107,6 +112,7 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
107112 objSeq = p ;
108113 ObjectMoveInfo .setNextObjectSeqOffset (objSeq , WordFactory .zero ());
109114
115+ totalUnusedBytes = totalUnusedBytes .add (gapSize );
110116 gapSize = WordFactory .zero ();
111117 }
112118
@@ -141,6 +147,12 @@ public boolean visitChunk(AlignedHeapChunk.AlignedHeader chunk) {
141147 ObjectMoveInfo .setObjectSeqSize (objSeq , objSeqSize );
142148 }
143149
150+ totalUnusedBytes = totalUnusedBytes .add (HeapChunk .getEndOffset (chunk ).subtract (HeapChunk .getTopOffset (chunk )));
151+ if (!sweeping && shouldSweepBasedOnFragmentation (totalUnusedBytes )) {
152+ sweeping = true ;
153+ chunk .setShouldSweepInsteadOfCompact (true );
154+ ObjectMoveInfo .visit (chunk , RESET_NEW_LOCATIONS_FOR_SWEEPING_VISITOR );
155+ }
144156 if (sweeping ) {
145157 /*
146158 * Continue allocating for compaction after the swept memory. Note that this forfeits
@@ -173,8 +185,21 @@ private Pointer allocate(UnsignedWord size) {
173185 return p ;
174186 }
175187
188+ private static boolean shouldSweepBasedOnFragmentation (UnsignedWord unusedBytes ) {
189+ UnsignedWord limit = HeapParameters .getAlignedHeapChunkSize ().unsignedDivide (16 );
190+ return unusedBytes .aboveOrEqual (0 ) && unusedBytes .belowThan (limit );
191+ }
192+
176193 public void init (Space space ) {
177194 allocChunk = space .getFirstAlignedHeapChunk ();
178195 allocPointer = AlignedHeapChunk .getObjectsStart (allocChunk );
179196 }
197+
198+ private static class ResetNewLocationsForSweepingVisitor implements ObjectMoveInfo .Visitor {
199+ @ Override
200+ public boolean visit (Pointer objSeq , UnsignedWord size , Pointer newAddress , Pointer nextObjSeq ) {
201+ ObjectMoveInfo .setNewAddress (objSeq , objSeq );
202+ return true ;
203+ }
204+ }
180205}
0 commit comments