diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index de97ce2bc8ef..6dd5aff78aa9 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -313,7 +313,7 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co } private void verifyBeforeGC() { - if (SubstrateGCOptions.VerifyHeap.getValue()) { + if (SubstrateGCOptions.VerifyHeap.getValue() && SerialGCOptions.VerifyBeforeGC.getValue()) { Timer verifyBeforeTimer = timers.verifyBefore.open(); try { boolean success = true; @@ -332,7 +332,7 @@ private void verifyBeforeGC() { } private void verifyAfterGC() { - if (SubstrateGCOptions.VerifyHeap.getValue()) { + if (SubstrateGCOptions.VerifyHeap.getValue() && SerialGCOptions.VerifyAfterGC.getValue()) { Timer verifyAfterTime = timers.verifyAfter.open(); try { boolean success = true; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GreyToBlackObjRefVisitor.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GreyToBlackObjRefVisitor.java index 03105a9b19fd..ac1be2f4d2f8 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GreyToBlackObjRefVisitor.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GreyToBlackObjRefVisitor.java @@ -31,6 +31,7 @@ import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.genscavenge.remset.RememberedSet; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectReferenceVisitor; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.hub.LayoutEncoding; @@ -86,7 +87,7 @@ public boolean visitObjectReferenceInline(Pointer objRef, int innerOffset, boole // This is the most expensive check as it accesses the heap fairly randomly, which results // in a lot of cache misses. ObjectHeaderImpl ohi = ObjectHeaderImpl.getObjectHeaderImpl(); - Word header = ohi.readHeaderFromPointer(p); + Word header = ObjectHeader.readHeaderFromPointer(p); if (GCImpl.getGCImpl().isCompleteCollection() || !RememberedSet.get().hasRememberedSet(header)) { if (ObjectHeaderImpl.isForwardedHeader(header)) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java index 69104f59be47..6014037a1098 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunk.java @@ -41,8 +41,8 @@ import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; -import com.oracle.svm.core.MemoryWalker; import com.oracle.svm.core.AlwaysInline; +import com.oracle.svm.core.MemoryWalker; import com.oracle.svm.core.NeverInline; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.c.struct.PinnedObjectField; @@ -332,7 +332,7 @@ public static Pointer asPointer(Header that) { public static HeapChunk.Header getEnclosingHeapChunk(Object obj) { if (!GraalDirectives.inIntrinsic()) { assert !HeapImpl.getHeapImpl().isInImageHeap(obj) || HeapImpl.usesImageHeapChunks() : "Must be checked before calling this method"; - assert !ObjectHeaderImpl.getObjectHeaderImpl().isPointerToForwardedObject(Word.objectToUntrackedPointer(obj)) : "Forwarded objects must be a pointer and not an object"; + assert !ObjectHeaderImpl.isPointerToForwardedObject(Word.objectToUntrackedPointer(obj)) : "Forwarded objects must be a pointer and not an object"; } if (ObjectHeaderImpl.isAlignedObject(obj)) { return AlignedHeapChunk.getEnclosingChunk(obj); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index f41076dd6ed1..b5f84cedaaad 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -42,17 +42,16 @@ import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.MemoryWalker; +import com.oracle.svm.core.NeverInline; import com.oracle.svm.core.SubstrateDiagnostics; import com.oracle.svm.core.SubstrateDiagnostics.DiagnosticThunk; import com.oracle.svm.core.SubstrateDiagnostics.DiagnosticThunkRegistry; import com.oracle.svm.core.SubstrateDiagnostics.ErrorContext; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.heap.RestrictHeapAccess; +import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.genscavenge.AlignedHeapChunk.AlignedHeader; import com.oracle.svm.core.genscavenge.ThreadLocalAllocation.Descriptor; @@ -69,7 +68,9 @@ import com.oracle.svm.core.heap.ReferenceHandler; import com.oracle.svm.core.heap.ReferenceHandlerThread; import com.oracle.svm.core.heap.ReferenceInternals; +import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.heap.RuntimeCodeInfoGCSupport; +import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference; import com.oracle.svm.core.locks.VMCondition; import com.oracle.svm.core.locks.VMMutex; @@ -641,6 +642,13 @@ public boolean printLocationInfo(Log log, UnsignedWord value, boolean allowJavaH } } + if (objectHeaderImpl.isEncodedObjectHeader((Word) value)) { + log.string("is the encoded object header for an object of type "); + DynamicHub hub = objectHeaderImpl.dynamicHubFromObjectHeader((Word) value); + log.string(hub.getName()); + return true; + } + Pointer ptr = (Pointer) value; if (printLocationInfo(log, ptr, allowJavaHeapAccess, allowUnsafeOperations)) { if (allowJavaHeapAccess && objectHeaderImpl.pointsToObjectHeader(ptr)) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java index 38af545a2aad..40226d733f94 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapVerifier.java @@ -38,6 +38,7 @@ import com.oracle.svm.core.genscavenge.AlignedHeapChunk.AlignedHeader; import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader; import com.oracle.svm.core.genscavenge.remset.RememberedSet; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectReferenceVisitor; import com.oracle.svm.core.heap.ObjectVisitor; import com.oracle.svm.core.heap.ReferenceAccess; @@ -257,7 +258,7 @@ private static boolean verifyObject(Object obj, AlignedHeader aChunk, UnalignedH return false; } - Word header = ObjectHeaderImpl.getObjectHeaderImpl().readHeaderFromPointer(ptr); + Word header = ObjectHeader.readHeaderFromPointer(ptr); if (ObjectHeaderImpl.isProducedHeapChunkZapped(header) || ObjectHeaderImpl.isConsumedHeapChunkZapped(header)) { Log.log().string("Object ").zhex(ptr).string(" has a zapped header: ").zhex(header).newline(); return false; @@ -325,11 +326,11 @@ private static boolean verifyObject(Object obj, AlignedHeader aChunk, UnalignedH // This method is executed exactly once per object in the heap. private static boolean verifyReferences(Object obj) { - if (!SerialGCOptions.VerifyReferences.getValue()) { + if (!SerialGCOptions.VerifyReferences.getValue() && !SerialGCOptions.VerifyReferencesPointIntoValidChunk.getValue()) { return true; } - REFERENCE_VERIFIER.initialize(obj); + REFERENCE_VERIFIER.initialize(); InteriorObjRefWalker.walkObject(obj, REFERENCE_VERIFIER); boolean success = REFERENCE_VERIFIER.result; @@ -358,27 +359,27 @@ private static boolean verifyReference(Object parentObject, Pointer reference, P return true; } - if (!HeapImpl.getHeapImpl().isInHeap(referencedObject)) { + if (SerialGCOptions.VerifyReferencesPointIntoValidChunk.getValue() && !HeapImpl.getHeapImpl().isInHeap(referencedObject)) { Log.log().string("Object reference at ").zhex(reference).string(" points outside the Java heap: ").zhex(referencedObject).string(". "); - printParentObject(parentObject); + printParent(parentObject); return false; } if (!ObjectHeaderImpl.getObjectHeaderImpl().pointsToObjectHeader(referencedObject)) { Log.log().string("Object reference at ").zhex(reference).string(" does not point to a Java object or the object header of the Java object is invalid: ").zhex(referencedObject) .string(". "); - printParentObject(parentObject); + printParent(parentObject); return false; } return true; } - private static void printParentObject(Object parentObject) { + private static void printParent(Object parentObject) { if (parentObject != null) { Log.log().string("The object that contains the invalid reference is of type ").string(parentObject.getClass().getName()).newline(); } else { - Log.log().string("The invalid reference is on the stack.").newline(); + Log.log().string("The invalid reference is on the stack").newline(); } } @@ -446,7 +447,6 @@ public boolean visitObject(Object object) { } private static class ObjectReferenceVerifier implements ObjectReferenceVisitor { - private Object parentObject; private boolean result; @Platforms(Platform.HOSTED_ONLY.class) @@ -454,14 +454,13 @@ private static class ObjectReferenceVerifier implements ObjectReferenceVisitor { } @SuppressWarnings("hiding") - public void initialize(Object parentObject) { - this.parentObject = parentObject; + public void initialize() { this.result = true; } @Override public boolean visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) { - result &= verifyReference(parentObject, objRef, compressed); + result &= verifyReference(holderObject, objRef, compressed); return true; } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java index 1ffadd77743a..85a64165988b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java @@ -79,8 +79,8 @@ public final class ObjectHeaderImpl extends ObjectHeader { private static final UnsignedWord IDHASH_STATE_FROM_ADDRESS = WordFactory.unsigned(0b01); private static final UnsignedWord IDHASH_STATE_IN_FIELD = WordFactory.unsigned(0b10); - private final int numReservedBits; private final int numAlignmentBits; + private final int numReservedBits; private final int numReservedExtraBits; private final int reservedBitsMask; @@ -114,52 +114,9 @@ public int getReservedBitsMask() { return reservedBitsMask; } - /** - * Read the header of the object at the specified address. When compressed references are - * enabled, the specified address must be the uncompressed absolute address of the object in - * memory. - */ - @Override - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public Word readHeaderFromPointer(Pointer objectPointer) { - if (getReferenceSize() == Integer.BYTES) { - return WordFactory.unsigned(objectPointer.readInt(getHubOffset())); - } else { - return objectPointer.readWord(getHubOffset()); - } - } - - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public static Word readHeaderFromObject(Object o) { - if (getReferenceSize() == Integer.BYTES) { - return WordFactory.unsigned(ObjectAccess.readInt(o, getHubOffset())); - } else { - return ObjectAccess.readWord(o, getHubOffset()); - } - } - - @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public DynamicHub readDynamicHubFromPointer(Pointer ptr) { - Word header = readHeaderFromPointer(ptr); - return dynamicHubFromObjectHeader(header); - } - @Override - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public DynamicHub dynamicHubFromObjectHeader(Word header) { - return (DynamicHub) extractPotentialDynamicHubFromHeader(header).toObject(); - } - - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - @Override - public Pointer readPotentialDynamicHubFromPointer(Pointer ptr) { - Word potentialHeader = readHeaderFromPointer(ptr); - return extractPotentialDynamicHubFromHeader(potentialHeader); - } - - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - private Pointer extractPotentialDynamicHubFromHeader(UnsignedWord header) { + public Pointer extractPotentialDynamicHubFromHeader(Word header) { if (ReferenceAccess.singleton().haveCompressedReferences()) { UnsignedWord hubBits = header.unsignedShiftRight(numReservedBits); UnsignedWord baseRelativeBits = hubBits.shiftLeft(numAlignmentBits); @@ -369,7 +326,7 @@ public static boolean isAlignedHeader(UnsignedWord header) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isUnalignedObject(Object obj) { - UnsignedWord header = ObjectHeaderImpl.readHeaderFromObject(obj); + UnsignedWord header = readHeaderFromObject(obj); return isUnalignedHeader(header); } @@ -389,7 +346,7 @@ public static boolean hasRememberedSet(UnsignedWord header) { } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - boolean isPointerToForwardedObject(Pointer p) { + static boolean isPointerToForwardedObject(Pointer p) { Word header = readHeaderFromPointer(p); return isForwardedHeader(header); } @@ -450,16 +407,6 @@ private UnsignedWord getHeaderBitsFromHeader(UnsignedWord header) { return header.and(reservedBitsMask); } - @Fold - static int getHubOffset() { - return ConfigurationValues.getObjectLayout().getHubOffset(); - } - - @Fold - static int getReferenceSize() { - return ConfigurationValues.getObjectLayout().getReferenceSize(); - } - @Fold static boolean hasFixedIdentityHashField() { return ConfigurationValues.getObjectLayout().hasFixedIdentityHashField(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ReferenceObjectProcessing.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ReferenceObjectProcessing.java index 429afe8fa0b9..e3a4ee9b894b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ReferenceObjectProcessing.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ReferenceObjectProcessing.java @@ -38,6 +38,7 @@ import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.genscavenge.remset.RememberedSet; import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectReferenceVisitor; import com.oracle.svm.core.heap.ReferenceInternals; import com.oracle.svm.core.hub.DynamicHub; @@ -219,7 +220,7 @@ private static boolean processRememberedRef(Reference dr) { private static boolean maybeUpdateForwardedReference(Reference dr, Pointer referentAddr) { ObjectHeaderImpl ohi = ObjectHeaderImpl.getObjectHeaderImpl(); - UnsignedWord header = ohi.readHeaderFromPointer(referentAddr); + UnsignedWord header = ObjectHeader.readHeaderFromPointer(referentAddr); if (ObjectHeaderImpl.isForwardedHeader(header)) { Object forwardedObj = ohi.getForwardedObject(referentAddr); ReferenceInternals.setReferent(dr, forwardedObj); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheReachabilityAnalyzer.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheReachabilityAnalyzer.java index e53e54a5334b..5f2384068b57 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheReachabilityAnalyzer.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/RuntimeCodeCacheReachabilityAnalyzer.java @@ -29,11 +29,12 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.word.Pointer; -import com.oracle.svm.core.util.DuplicatedInNativeCode; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectReferenceVisitor; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.RuntimeCodeCacheCleaner; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.util.DuplicatedInNativeCode; @DuplicatedInNativeCode final class RuntimeCodeCacheReachabilityAnalyzer implements ObjectReferenceVisitor { @@ -69,7 +70,7 @@ public static boolean isReachable(Pointer ptrToObj) { } ObjectHeaderImpl ohi = ObjectHeaderImpl.getObjectHeaderImpl(); - Word header = ohi.readHeaderFromPointer(ptrToObj); + Word header = ObjectHeader.readHeaderFromPointer(ptrToObj); if (ObjectHeaderImpl.isForwardedHeader(header)) { return true; } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/SerialGCOptions.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/SerialGCOptions.java index bc23ae04dc97..edac8966b176 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/SerialGCOptions.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/SerialGCOptions.java @@ -88,12 +88,21 @@ public Integer getValue(OptionValues values) { @Option(help = "Instrument write barriers with counters. Serial GC only.", type = OptionType.Debug)// public static final HostedOptionKey CountWriteBarriers = new HostedOptionKey<>(false, SerialGCOptions::serialGCOnly); + @Option(help = "Verify the heap before doing a garbage collection if VerifyHeap is enabled. Serial GC only.", type = OptionType.Debug)// + public static final HostedOptionKey VerifyBeforeGC = new HostedOptionKey<>(true, SerialGCOptions::serialGCOnly); + + @Option(help = "Verify the heap after doing a garbage collection if VerifyHeap is enabled. Serial GC only.", type = OptionType.Debug)// + public static final HostedOptionKey VerifyAfterGC = new HostedOptionKey<>(true, SerialGCOptions::serialGCOnly); + @Option(help = "Verify the remembered set if VerifyHeap is enabled. Serial GC only.", type = OptionType.Debug)// public static final HostedOptionKey VerifyRememberedSet = new HostedOptionKey<>(true, SerialGCOptions::serialGCOnly); @Option(help = "Verify all object references if VerifyHeap is enabled. Serial GC only.", type = OptionType.Debug)// public static final HostedOptionKey VerifyReferences = new HostedOptionKey<>(true, SerialGCOptions::serialGCOnly); + @Option(help = "Verify that object references point into valid heap chunks if VerifyHeap is enabled. Serial GC only.", type = OptionType.Debug)// + public static final HostedOptionKey VerifyReferencesPointIntoValidChunk = new HostedOptionKey<>(false, SerialGCOptions::serialGCOnly); + @Option(help = "Verify write barriers. Serial GC only.", type = OptionType.Debug)// public static final HostedOptionKey VerifyWriteBarriers = new HostedOptionKey<>(false, SerialGCOptions::serialGCOnly); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java index 06a6e8f0da16..1aff988d39a2 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/Space.java @@ -44,6 +44,7 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.genscavenge.GCImpl.ChunkReleaser; import com.oracle.svm.core.genscavenge.remset.RememberedSet; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectVisitor; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.identityhashcode.IdentityHashCodeSupport; @@ -369,7 +370,7 @@ private Object copyAlignedObject(Object originalObj) { UnsignedWord copySize = originalSize; boolean addIdentityHashField = false; if (!ConfigurationValues.getObjectLayout().hasFixedIdentityHashField()) { - Word header = ObjectHeaderImpl.readHeaderFromObject(originalObj); + Word header = ObjectHeader.readHeaderFromObject(originalObj); if (probability(SLOW_PATH_PROBABILITY, ObjectHeaderImpl.hasIdentityHashFromAddressInline(header))) { addIdentityHashField = true; copySize = LayoutEncoding.getSizeFromObjectInlineInGC(originalObj, true); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/StackVerifier.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/StackVerifier.java index abc53e03442b..ac6d3458c96d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/StackVerifier.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/StackVerifier.java @@ -31,13 +31,13 @@ import org.graalvm.nativeimage.c.function.CodePointer; import org.graalvm.word.Pointer; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.heap.RestrictHeapAccess; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.deopt.DeoptimizedFrame; import com.oracle.svm.core.heap.ObjectReferenceVisitor; +import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.stack.JavaStackWalker; import com.oracle.svm.core.stack.StackFrameVisitor; @@ -53,40 +53,46 @@ private StackVerifier() { @NeverInline("Starts a stack walk in the caller frame") public static boolean verifyAllThreads() { - STACK_FRAME_VISITOR.reset(); + boolean result = true; + STACK_FRAME_VISITOR.initialize(); JavaStackWalker.walkCurrentThread(KnownIntrinsics.readCallerStackPointer(), STACK_FRAME_VISITOR); + result &= STACK_FRAME_VISITOR.result; + if (SubstrateOptions.MultiThreaded.getValue()) { - for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (vmThread == CurrentIsolate.getCurrentThread()) { + for (IsolateThread thread = VMThreads.firstThread(); thread.isNonNull(); thread = VMThreads.nextThread(thread)) { + if (thread == CurrentIsolate.getCurrentThread()) { continue; } - JavaStackWalker.walkThread(vmThread, STACK_FRAME_VISITOR); + + STACK_FRAME_VISITOR.initialize(); + JavaStackWalker.walkThread(thread, STACK_FRAME_VISITOR); + result &= STACK_FRAME_VISITOR.result; } } - return STACK_FRAME_VISITOR.getResult(); + return result; } private static class StackFrameVerificationVisitor extends StackFrameVisitor { private final VerifyFrameReferencesVisitor verifyFrameReferencesVisitor; + private boolean result; + @Platforms(Platform.HOSTED_ONLY.class) StackFrameVerificationVisitor() { verifyFrameReferencesVisitor = new VerifyFrameReferencesVisitor(); } - public void reset() { - verifyFrameReferencesVisitor.reset(); - } - - public boolean getResult() { - return verifyFrameReferencesVisitor.result; + public void initialize() { + this.result = true; } @Override @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate while verifying the stack.") public boolean visitFrame(Pointer currentSP, CodePointer currentIP, CodeInfo codeInfo, DeoptimizedFrame deoptimizedFrame) { + verifyFrameReferencesVisitor.initialize(); CodeInfoTable.visitObjectReferences(currentSP, currentIP, codeInfo, deoptimizedFrame, verifyFrameReferencesVisitor); + result &= verifyFrameReferencesVisitor.result; return true; } } @@ -98,8 +104,8 @@ private static class VerifyFrameReferencesVisitor implements ObjectReferenceVisi VerifyFrameReferencesVisitor() { } - public void reset() { - result = true; + public void initialize() { + this.result = true; } @Override diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java index f25fbcf3fcd6..1c997255d9af 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGeneration.java @@ -29,10 +29,11 @@ import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; -import com.oracle.svm.core.MemoryWalker; import com.oracle.svm.core.AlwaysInline; +import com.oracle.svm.core.MemoryWalker; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.genscavenge.GCImpl.ChunkReleaser; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.ObjectVisitor; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.thread.VMOperation; @@ -243,7 +244,7 @@ public boolean contains(Object object) { return HeapChunk.getSpace(HeapChunk.getEnclosingHeapChunk(object)).isYoungSpace(); } // Only objects in the young generation have no remembered set - UnsignedWord header = ObjectHeaderImpl.readHeaderFromObject(object); + UnsignedWord header = ObjectHeader.readHeaderFromObject(object); boolean young = !ObjectHeaderImpl.hasRememberedSet(header); assert young == HeapChunk.getSpace(HeapChunk.getEnclosingHeapChunk(object)).isYoungSpace(); return young; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/BarrierSnippets.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/BarrierSnippets.java index 247da5e8440e..dae405b49556 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/BarrierSnippets.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/BarrierSnippets.java @@ -61,6 +61,7 @@ import com.oracle.svm.core.genscavenge.remset.RememberedSet; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; import com.oracle.svm.core.graal.snippets.SubstrateTemplates; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.heap.StoredContinuation; import com.oracle.svm.core.util.Counter; import com.oracle.svm.core.util.CounterFeature; @@ -97,7 +98,7 @@ public static void postWriteBarrierSnippet(Object object, @ConstantParameter boo counters().postWriteBarrier.inc(); Object fixedObject = FixedValueAnchorNode.getObject(object); - UnsignedWord objectHeader = ObjectHeaderImpl.readHeaderFromObject(fixedObject); + UnsignedWord objectHeader = ObjectHeader.readHeaderFromObject(fixedObject); if (SerialGCOptions.VerifyWriteBarriers.getValue() && alwaysAlignedChunk) { /* diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java index 40ec1153d282..57d0cf1f6148 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/remset/CardTableBasedRememberedSet.java @@ -42,6 +42,7 @@ import com.oracle.svm.core.genscavenge.Space; import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader; import com.oracle.svm.core.genscavenge.graal.SubstrateCardTableBarrierSet; +import com.oracle.svm.core.heap.ObjectHeader; import com.oracle.svm.core.image.ImageHeapObject; import com.oracle.svm.core.util.HostedByteBufferPointer; @@ -151,7 +152,7 @@ public void dirtyCardIfNecessary(Object holderObject, Object object) { return; } - UnsignedWord objectHeader = ObjectHeaderImpl.readHeaderFromObject(holderObject); + UnsignedWord objectHeader = ObjectHeader.readHeaderFromObject(holderObject); if (hasRememberedSet(objectHeader)) { if (ObjectHeaderImpl.isAlignedObject(holderObject)) { AlignedChunkRememberedSet.dirtyCardForObject(holderObject, false); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index 67affa122d3c..c6a4372a42d8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -245,10 +245,12 @@ private static void printFatalErrorForCurrentState() { FatalErrorState fatalErrorState = fatalErrorState(); Log log = fatalErrorState.log; - if (fatalErrorState.diagnosticThunkIndex > 0) { + if (fatalErrorState.diagnosticThunkIndex >= 0) { // An error must have happened earlier as the code for printing diagnostics was invoked // recursively. log.resetIndentation().newline(); + } else { + fatalErrorState.diagnosticThunkIndex = 0; } // Print the various sections of the diagnostics and skip all sections that were already @@ -463,7 +465,7 @@ public static class FatalErrorState { @Platforms(Platform.HOSTED_ONLY.class) public FatalErrorState() { diagnosticThread = new AtomicWord<>(); - diagnosticThunkIndex = 0; + diagnosticThunkIndex = -1; invocationCount = 0; log = null; @@ -478,7 +480,7 @@ public ErrorContext getErrorContext() { @SuppressWarnings("hiding") public boolean trySet(Log log, Pointer sp, CodePointer ip, RegisterDumper.Context registerContext, boolean frameHasCalleeSavedRegisters) { if (diagnosticThread.compareAndSet(WordFactory.nullPointer(), CurrentIsolate.getCurrentThread())) { - assert diagnosticThunkIndex == 0; + assert diagnosticThunkIndex == -1; assert invocationCount == 0; this.log = log; @@ -501,7 +503,7 @@ public void clear() { errorContext.setRegisterContext(WordFactory.nullPointer()); errorContext.setFrameHasCalleeSavedRegisters(false); - diagnosticThunkIndex = 0; + diagnosticThunkIndex = -1; invocationCount = 0; diagnosticThread.set(WordFactory.nullPointer()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java index 28f51e24eafc..980cd605c997 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java @@ -192,7 +192,7 @@ protected static void printSegfaultAddressInfo(Log log, long addr) { if (addr != 0) { long delta = addr - CurrentIsolate.getIsolate().rawValue(); String sign = (delta >= 0 ? "+" : "-"); - log.string("(heapBase ").string(sign).signed(delta).string(")"); + log.string("(heapBase ").string(sign).string(" ").signed(Math.abs(delta)).string(")"); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java index c203d92c0fe2..0c8034d51148 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/InstanceReferenceMapDecoder.java @@ -29,11 +29,11 @@ import org.graalvm.word.WordFactory; import com.oracle.svm.core.AlwaysInline; -import com.oracle.svm.core.util.DuplicatedInNativeCode; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.util.DuplicatedInNativeCode; import com.oracle.svm.core.util.NonmovableByteArrayReader; -import com.oracle.svm.core.util.TypedMemoryReader; +import com.oracle.svm.core.util.coder.NativeCoder; @DuplicatedInNativeCode public class InstanceReferenceMapDecoder { @@ -43,7 +43,7 @@ public static boolean walkOffsetsFromPointer(Pointer baseAddress, NonmovableArra assert referenceMapEncoding.isNonNull(); Pointer position = NonmovableByteArrayReader.pointerTo(referenceMapEncoding, referenceMapIndex); - int entryCount = TypedMemoryReader.getS4(position); + int entryCount = position.readInt(0); position = position.add(4); int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize(); @@ -53,10 +53,10 @@ public static boolean walkOffsetsFromPointer(Pointer baseAddress, NonmovableArra UnsignedWord sizeOfEntries = WordFactory.unsigned(InstanceReferenceMapEncoder.MAP_ENTRY_SIZE).multiply(entryCount); Pointer end = position.add(sizeOfEntries); while (position.belowThan(end)) { - int offset = TypedMemoryReader.getS4(position); + int offset = position.readInt(0); position = position.add(4); - long count = TypedMemoryReader.getU4(position); + long count = NativeCoder.readU4(position); position = position.add(4); Pointer objRef = baseAddress.add(offset); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ObjectHeader.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ObjectHeader.java index 5e83ff7a0932..25df0155520a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ObjectHeader.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ObjectHeader.java @@ -25,12 +25,15 @@ package com.oracle.svm.core.heap; import org.graalvm.compiler.api.replacements.Fold; +import org.graalvm.compiler.word.ObjectAccess; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.image.ImageHeapObject; import com.oracle.svm.core.snippets.KnownIntrinsics; @@ -61,20 +64,46 @@ protected ObjectHeader() { public abstract Word encodeAsUnmanagedObjectHeader(DynamicHub hub); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public abstract DynamicHub dynamicHubFromObjectHeader(Word header); + public DynamicHub dynamicHubFromObjectHeader(Word header) { + return (DynamicHub) extractPotentialDynamicHubFromHeader(header).toObject(); + } public static DynamicHub readDynamicHubFromObject(Object o) { return KnownIntrinsics.readHub(o); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public abstract Word readHeaderFromPointer(Pointer ptr); + public static Word readHeaderFromPointer(Pointer objectPointer) { + if (getReferenceSize() == Integer.BYTES) { + return WordFactory.unsigned(objectPointer.readInt(getHubOffset())); + } else { + return objectPointer.readWord(getHubOffset()); + } + } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public abstract DynamicHub readDynamicHubFromPointer(Pointer ptr); + public static Word readHeaderFromObject(Object o) { + if (getReferenceSize() == Integer.BYTES) { + return WordFactory.unsigned(ObjectAccess.readInt(o, getHubOffset())); + } else { + return ObjectAccess.readWord(o, getHubOffset()); + } + } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - public abstract Pointer readPotentialDynamicHubFromPointer(Pointer ptr); + public DynamicHub readDynamicHubFromPointer(Pointer ptr) { + Word header = readHeaderFromPointer(ptr); + return dynamicHubFromObjectHeader(header); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public Pointer readPotentialDynamicHubFromPointer(Pointer ptr) { + Word potentialHeader = readHeaderFromPointer(ptr); + return extractPotentialDynamicHubFromHeader(potentialHeader); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public abstract Pointer extractPotentialDynamicHubFromHeader(Word header); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public abstract void initializeHeaderOfNewObject(Pointer ptr, Word header); @@ -82,11 +111,13 @@ public static DynamicHub readDynamicHubFromObject(Object o) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean pointsToObjectHeader(Pointer ptr) { Pointer potentialDynamicHub = readPotentialDynamicHubFromPointer(ptr); - if (Heap.getHeap().isInImageHeap(potentialDynamicHub)) { - Pointer potentialHubOfDynamicHub = readPotentialDynamicHubFromPointer(potentialDynamicHub); - return potentialHubOfDynamicHub.equal(Word.objectToUntrackedPointer(DynamicHub.class)); - } - return false; + return isDynamicHub(potentialDynamicHub); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public boolean isEncodedObjectHeader(Word potentialHeader) { + Pointer potentialDynamicHub = extractPotentialDynamicHubFromHeader(potentialHeader); + return isDynamicHub(potentialDynamicHub); } @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @@ -98,8 +129,27 @@ public boolean pointsToObjectHeader(Pointer ptr) { @Uninterruptible(reason = "Prevent a GC interfering with the object's identity hash state.", callerMustBe = true) public abstract void setIdentityHashFromAddress(Pointer ptr, Word currentHeader); + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private boolean isDynamicHub(Pointer potentialDynamicHub) { + if (Heap.getHeap().isInImageHeap(potentialDynamicHub)) { + Pointer potentialHubOfDynamicHub = readPotentialDynamicHubFromPointer(potentialDynamicHub); + return potentialHubOfDynamicHub.equal(Word.objectToUntrackedPointer(DynamicHub.class)); + } + return false; + } + + @Fold + protected static int getReferenceSize() { + return ConfigurationValues.getObjectLayout().getReferenceSize(); + } + @Fold protected static int getCompressionShift() { return ReferenceAccess.singleton().getCompressEncoding().getShift(); } + + @Fold + protected static int getHubOffset() { + return ConfigurationValues.getObjectLayout().getHubOffset(); + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java index 1e63276c3a3c..e13f5e27379a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/LayoutEncoding.java @@ -361,7 +361,7 @@ private static UnsignedWord getSizeFromObjectInline(Object obj, boolean withOpti @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static boolean checkOptionalIdentityHashField(Object obj) { ObjectHeader oh = Heap.getHeap().getObjectHeader(); - Word header = oh.readHeaderFromPointer(Word.objectToUntrackedPointer(obj)); + Word header = ObjectHeader.readHeaderFromPointer(Word.objectToUntrackedPointer(obj)); return oh.hasOptionalIdentityHashField(header); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/SubstrateIdentityHashCodeSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/SubstrateIdentityHashCodeSnippets.java index d384d0c4faab..a990d5539289 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/SubstrateIdentityHashCodeSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/identityhashcode/SubstrateIdentityHashCodeSnippets.java @@ -70,7 +70,7 @@ protected int computeIdentityHashCode(Object obj) { } ObjectHeader oh = Heap.getHeap().getObjectHeader(); Word objPtr = Word.objectToUntrackedPointer(obj); - Word header = oh.readHeaderFromPointer(objPtr); + Word header = ObjectHeader.readHeaderFromPointer(objPtr); if (probability(LIKELY_PROBABILITY, oh.hasOptionalIdentityHashField(header))) { int offset = LayoutEncoding.getOptionalIdentityHashOffset(obj); identityHashCode = ObjectAccess.readInt(obj, offset, IdentityHashCodeSupport.IDENTITY_HASHCODE_LOCATION); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/TypedMemoryReader.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/TypedMemoryReader.java deleted file mode 100644 index 22f004c74e27..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/TypedMemoryReader.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.util; - -import org.graalvm.word.Pointer; - -public class TypedMemoryReader { - public static int getS1(Pointer ptr) { - return ptr.readByte(0); - } - - public static int getS2(Pointer ptr) { - return ptr.readShort(0); - } - - public static int getS4(Pointer ptr) { - return ptr.readInt(0); - } - - public static long getS8(Pointer ptr) { - return ptr.readLong(0); - } - - public static int getU1(Pointer ptr) { - return getS1(ptr) & 0xFF; - } - - public static int getU2(Pointer ptr) { - return getS2(ptr) & 0xFFFF; - } - - public static long getU4(Pointer ptr) { - return getS4(ptr) & 0xFFFFFFFFL; - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/coder/NativeCoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/coder/NativeCoder.java index b11eeff2a0aa..bc00b091f324 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/coder/NativeCoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/coder/NativeCoder.java @@ -25,11 +25,32 @@ package com.oracle.svm.core.util.coder; import org.graalvm.word.Pointer; +import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.Uninterruptible; /** Uses the native, architecture-specific byte order to access {@link ByteStream} data. */ public class NativeCoder { + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static int readU1(Pointer ptr) { + return ptr.readInt(0) & 0xFF; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static int readU2(Pointer ptr) { + return ptr.readShort(0) & 0xFFFF; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static long readU4(Pointer ptr) { + return ptr.readInt(0) & 0xFFFFFFFFL; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static UnsignedWord readU8(Pointer ptr) { + return ptr.readWord(0); + } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static byte readByte(ByteStream data) { Pointer position = data.getPosition();