diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java index 890774f41c0e..cac2fa902fb2 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/AlignedChunkRememberedSet.java @@ -54,6 +54,11 @@ final class AlignedChunkRememberedSet { private AlignedChunkRememberedSet() { } + @Fold + public static int wordSize() { + return ConfigurationValues.getTarget().wordSize; + } + @Fold public static UnsignedWord getHeaderSize() { UnsignedWord headerSize = getFirstObjectTableLimitOffset(); @@ -133,19 +138,23 @@ public static void walkDirtyObjects(AlignedHeader chunk, GreyToBlackObjectVisito UnsignedWord memorySize = objectsLimit.subtract(objectsStart); UnsignedWord indexLimit = CardTable.indexLimitForMemorySize(memorySize); - for (UnsignedWord index = WordFactory.zero(); index.belowThan(indexLimit); index = index.add(1)) { - if (CardTable.isDirty(cardTableStart, index)) { + for (UnsignedWord index = WordFactory.zero(); index.belowThan(indexLimit); index = index.add(wordSize())) { + UnsignedWord value = CardTable.readWord(cardTableStart, index); + if (value.notEqual(CardTable.CLEAN_WORD)) { if (clean) { - CardTable.setClean(cardTableStart, index); + CardTable.cleanWord(cardTableStart, index); } - - Pointer ptr = FirstObjectTable.getFirstObjectImprecise(fotStart, objectsStart, objectsLimit, index); - Pointer cardLimit = CardTable.indexToMemoryPointer(objectsStart, index.add(1)); - Pointer walkLimit = PointerUtils.min(cardLimit, objectsLimit); - while (ptr.belowThan(walkLimit)) { - Object obj = ptr.toObject(); - visitor.visitObjectInline(obj); - ptr = LayoutEncoding.getObjectEndInline(obj); + for (int i = 0; i < wordSize(); i++) { + if (value.unsignedShiftRight(i * 8).and(0xFF).equal(CardTable.DIRTY_ENTRY)) { + Pointer ptr = FirstObjectTable.getFirstObjectImprecise(fotStart, objectsStart, objectsLimit, index.add(i)); + Pointer cardLimit = CardTable.indexToMemoryPointer(objectsStart, index.add(i + 1)); + Pointer walkLimit = PointerUtils.min(cardLimit, objectsLimit); + while (ptr.belowThan(walkLimit)) { + Object obj = ptr.toObject(); + visitor.visitObjectInline(obj); + ptr = LayoutEncoding.getObjectEndInline(obj); + } + } } } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTable.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTable.java index 5bf1c95dd4be..4ef957458c4c 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTable.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTable.java @@ -74,10 +74,11 @@ final class CardTable { public static final int BYTES_COVERED_BY_ENTRY = 512; - private static final int ENTRY_SIZE_BYTES = 1; + static final int DIRTY_ENTRY = 0; + static final int CLEAN_ENTRY = 1; + static final UnsignedWord CLEAN_WORD = WordFactory.unsigned(0x0101010101010101L); - private static final int DIRTY_ENTRY = 0; - private static final int CLEAN_ENTRY = 1; + private static final int ENTRY_SIZE_BYTES = 1; private static final CardTableVerificationVisitor CARD_TABLE_VERIFICATION_VISITOR = new CardTableVerificationVisitor(); @@ -112,6 +113,14 @@ private static boolean isClean(Pointer table, UnsignedWord index) { return entry == CLEAN_ENTRY; } + public static UnsignedWord readWord(Pointer table, UnsignedWord index) { + return table.readWord(indexToTableOffset(index)); + } + + public static void cleanWord(Pointer table, UnsignedWord index) { + table.writeWord(indexToTableOffset(index), CLEAN_WORD, BarrierSnippets.CARD_REMEMBERED_SET_LOCATION); + } + private static int readEntry(Pointer table, UnsignedWord index) { return table.readByte(indexToTableOffset(index)); }