From 5a2e87ba588b8ff1993cc11e039944da9faecd45 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 21 Feb 2022 13:40:44 +0100 Subject: [PATCH 1/2] Add debug helper methods. --- .../oracle/svm/core/genscavenge/HeapImpl.java | 4 +- .../core/genscavenge/ObjectHeaderImpl.java | 10 +- .../src/com/oracle/svm/core/DebugHelper.java | 329 ++++++++++++++++++ .../oracle/svm/core/SubstrateDiagnostics.java | 13 + .../com/oracle/svm/core/SubstrateOptions.java | 3 + .../oracle/svm/core/heap/ObjectHeader.java | 7 + .../com/oracle/svm/core/hub/DynamicHub.java | 3 + .../src/com/oracle/svm/core/hub/HubType.java | 6 + .../oracle/svm/core/hub/LayoutEncoding.java | 1 + 9 files changed, 366 insertions(+), 10 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java 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 f7cde39d4416..986d0ec92a70 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 @@ -68,7 +68,6 @@ import com.oracle.svm.core.heap.ReferenceHandlerThread; import com.oracle.svm.core.heap.ReferenceInternals; 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; @@ -643,9 +642,8 @@ public boolean printLocationInfo(Log log, UnsignedWord value, boolean allowJavaH Pointer ptr = (Pointer) value; if (printLocationInfo(log, ptr, allowJavaHeapAccess, allowUnsafeOperations)) { if (allowJavaHeapAccess && objectHeaderImpl.pointsToObjectHeader(ptr)) { - DynamicHub hub = objectHeaderImpl.readDynamicHubFromPointer(ptr); log.indent(true); - log.string("hub=").string(hub.getName()); + SubstrateDiagnostics.printObjectInfo(log, ptr); log.redent(false); } 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 d4cbfcd2774f..2926cb06235f 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 @@ -142,13 +142,14 @@ public DynamicHub dynamicHubFromObjectHeader(UnsignedWord header) { return (DynamicHub) objectValue; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) @Override public Pointer readPotentialDynamicHubFromPointer(Pointer ptr) { UnsignedWord potentialHeader = ObjectHeaderImpl.readHeaderFromPointer(ptr); UnsignedWord pointerBits = clearBits(potentialHeader); if (ReferenceAccess.singleton().haveCompressedReferences()) { - UnsignedWord compressedBits = pointerBits.unsignedShiftRight(getCompressionShift()); - return KnownIntrinsics.heapBase().add(compressedBits.shiftLeft(getCompressionShift())); + UnsignedWord compressedBits = pointerBits.unsignedShiftRight(ObjectHeader.getCompressionShift()); + return KnownIntrinsics.heapBase().add(compressedBits.shiftLeft(ObjectHeader.getCompressionShift())); } else { return (Pointer) pointerBits; } @@ -378,9 +379,4 @@ static int getReferenceSize() { static boolean hasBase() { return ImageSingletons.lookup(CompressEncoding.class).hasBase(); } - - @Fold - static int getCompressionShift() { - return ReferenceAccess.singleton().getCompressEncoding().getShift(); - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java new file mode 100644 index 000000000000..4bae4b20e5a6 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2022, 2022, 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; + +import java.util.function.BooleanSupplier; + +import org.graalvm.compiler.word.Word; +import org.graalvm.nativeimage.IsolateThread; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.nativeimage.c.function.CodePointer; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; + +import com.oracle.svm.core.annotate.Uninterruptible; +import com.oracle.svm.core.c.function.CEntryPointOptions; +import com.oracle.svm.core.c.function.CEntryPointOptions.NoEpilogue; +import com.oracle.svm.core.c.function.CEntryPointOptions.Publish; +import com.oracle.svm.core.graal.nodes.WriteCurrentVMThreadNode; +import com.oracle.svm.core.graal.snippets.CEntryPointSnippets; +import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.heap.ObjectHeader; +import com.oracle.svm.core.heap.ReferenceAccess; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.LayoutEncoding; +import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.snippets.KnownIntrinsics; +import com.oracle.svm.core.thread.VMThreads; + +public class DebugHelper { + static class PointerDebugHelper { + @Uninterruptible(reason = "Called with a raw pointer.") + @CEntryPoint(name = "dbg_ptr_isInImageHeap", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isInImageHeap(@SuppressWarnings("unused") IsolateThread thread, Pointer ptr) { + return Heap.getHeap().isInImageHeap(ptr); + } + + @Uninterruptible(reason = "Called with a raw pointer.") + @CEntryPoint(name = "dbg_ptr_isObject", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isObject(@SuppressWarnings("unused") IsolateThread thread, Pointer ptr) { + ObjectHeader header = Heap.getHeap().getObjectHeader(); + return header.pointsToObjectHeader(ptr); + } + } + + static class HubDebugHelper { + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_getLayoutEncoding", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static int getLayoutEncoding(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return hub.getLayoutEncoding(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_getArrayElementSize", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.getArrayElementSize(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static int getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.getArrayBaseOffset(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_isArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.isArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_isPrimitiveArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.isPrimitiveArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_isObjectArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.isObjectArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_isInstance", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isInstance(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.isInstance(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_hub_isReference", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isReference(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + return DebugHelper.isReference(hub); + } + } + + static class ObjectDebugHelper { + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_getHub", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static long getHub(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + return Word.objectToUntrackedPointer(KnownIntrinsics.readHub(obj)).rawValue(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_getObjectSize", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static long getObjectSize(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + return LayoutEncoding.getSizeFromObject(obj).rawValue(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_getArrayElementSize", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.getArrayElementSize(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static long getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.getArrayBaseOffset(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_isArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.isArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_isPrimitiveArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.isPrimitiveArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_isObjectArray", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.isObjectArray(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_isInstance", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isInstance(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.isInstance(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_isReference", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static boolean isReference(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + DynamicHub hub = KnownIntrinsics.readHub(obj); + return DebugHelper.isReference(hub); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_uncompress", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static long uncompressObjectPointer(@SuppressWarnings("unused") IsolateThread thread, Pointer compressedPtr) { + return Word.objectToUntrackedPointer(ReferenceAccess.singleton().uncompressReference(compressedPtr)).rawValue(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "dbg_obj_compress", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static long compressObjectPointer(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + Object obj = objPtr.toObject(); + return ReferenceAccess.singleton().getCompressedRepresentation(obj).rawValue(); + } + } + + static class StringDebugHelper { + @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) + @CEntryPoint(name = "dbg_string_print", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static void printString(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { + String str = (String) strPtr.toObject(); + Log.log().string(str).newline(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) + @CEntryPoint(name = "dbg_string_length", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static int getStringLength(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { + String str = (String) strPtr.toObject(); + return str.length(); + } + } + + static class DiagnosticDebugHelper { + @Uninterruptible(reason = "Just to keep the verification happy.", calleeMustBe = false) + @CEntryPoint(name = "dbg_printFatalError", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static void printFatalError(@SuppressWarnings("unused") IsolateThread thread, Pointer sp, CodePointer ip) { + SubstrateDiagnostics.printFatalError(Log.log(), sp, ip, WordFactory.nullPointer(), false); + } + + @Uninterruptible(reason = "Just to keep the verification happy.", calleeMustBe = false) + @CEntryPoint(name = "dbg_printLocationInfo", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static void printLocationInfo(@SuppressWarnings("unused") IsolateThread thread, Pointer mem) { + SubstrateDiagnostics.printLocationInfo(Log.log(), mem, true, true); + } + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static int getArrayElementSize(DynamicHub hub) { + if (hub.isArray()) { + return LayoutEncoding.getArrayIndexScale(hub.getLayoutEncoding()); + } + return -1; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static int getArrayBaseOffset(DynamicHub hub) { + if (hub.isArray()) { + return LayoutEncoding.getArrayIndexScale(hub.getLayoutEncoding()); + } + return -1; + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static boolean isArray(DynamicHub hub) { + return LayoutEncoding.isArray(hub.getLayoutEncoding()); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static boolean isPrimitiveArray(DynamicHub hub) { + return LayoutEncoding.isPrimitiveArray(hub.getLayoutEncoding()); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static boolean isObjectArray(DynamicHub hub) { + return LayoutEncoding.isObjectArray(hub.getLayoutEncoding()); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static boolean isInstance(DynamicHub hub) { + return LayoutEncoding.isInstance(hub.getLayoutEncoding()); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static boolean isReference(DynamicHub hub) { + return hub.isReferenceInstanceClass(); + } + + private static class SetThreadAndHeapBasePrologue implements CEntryPointOptions.Prologue { + @Uninterruptible(reason = "prologue") + @SuppressWarnings("unused") + public static void enter(IsolateThread thread) { + WriteCurrentVMThreadNode.writeCurrentVMThread(thread); + if (SubstrateOptions.SpawnIsolates.getValue()) { + CEntryPointSnippets.setHeapBase(VMThreads.IsolateTL.get()); + } + } + } + + private static class IncludeDebugHelperMethods implements BooleanSupplier { + @Platforms(Platform.HOSTED_ONLY.class) + IncludeDebugHelperMethods() { + } + + @Override + public boolean getAsBoolean() { + return SubstrateOptions.IncludeDebugHelperMethods.getValue() || SubstrateOptions.optimizationLevel() == 0; + } + } +} 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 269d1fb83a18..d2e9eec60b77 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 @@ -67,6 +67,7 @@ import com.oracle.svm.core.deopt.DeoptimizedFrame; import com.oracle.svm.core.deopt.Deoptimizer; import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicWord; import com.oracle.svm.core.locks.VMLockSupport; import com.oracle.svm.core.log.Log; @@ -133,6 +134,18 @@ public static void printLocationInfo(Log log, UnsignedWord value, boolean allowJ } } + public static void printObjectInfo(Log log, Pointer ptr) { + DynamicHub objHub = Heap.getHeap().getObjectHeader().readDynamicHubFromPointer(ptr); + if (objHub == SubstrateUtil.cast(DynamicHub.class, DynamicHub.class)) { + // The pointer is already a hub, so print some information about the hub. + DynamicHub hub = (DynamicHub) ptr.toObject(); + log.string("is the hub of ").string(hub.getName()); + } else { + // The pointer is an object, so print some information about the object's hub. + log.string("is an object with hub=").string(objHub.getName()); + } + } + /** * See {@link #printInformation(Log, Pointer, CodePointer, RegisterDumper.Context, boolean)}. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 1ee936f59eb9..44927d62c847 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -528,6 +528,9 @@ public static int codeAlignment() { @Option(help = "Determines if VM internal threads (e.g., a dedicated VM operation or reference handling thread) are allowed in this image.", type = OptionType.Expert) // public static final HostedOptionKey AllowVMInternalThreads = new HostedOptionKey<>(true); + @Option(help = "Determines if debugging-specific helper methods are embedded into the image. Those methods can be called directly from the debugger to obtain or print additional information.", type = OptionType.Debug) // + public static final HostedOptionKey IncludeDebugHelperMethods = new HostedOptionKey<>(false); + @APIOption(name = "-g", fixedValue = "2", customHelp = "generate debugging information")// @Option(help = "Insert debug info into the generated native image or library")// public static final HostedOptionKey GenerateDebugInfo = new HostedOptionKey<>(0) { 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 56c5aaf511d8..5b9553b4e68e 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 @@ -24,6 +24,7 @@ */ package com.oracle.svm.core.heap; +import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -70,11 +71,13 @@ public static DynamicHub readDynamicHubFromObject(Object o) { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public abstract DynamicHub readDynamicHubFromPointer(Pointer ptr); + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public abstract Pointer readPotentialDynamicHubFromPointer(Pointer ptr); @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public abstract void initializeHeaderOfNewObject(Pointer objectPointer, Word objectHeader); + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean pointsToObjectHeader(Pointer ptr) { Pointer potentialDynamicHub = readPotentialDynamicHubFromPointer(ptr); if (Heap.getHeap().isInImageHeap(potentialDynamicHub)) { @@ -84,4 +87,8 @@ public boolean pointsToObjectHeader(Pointer ptr) { return false; } + @Fold + protected static int getCompressionShift() { + return ReferenceAccess.singleton().getCompressEncoding().getShift(); + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index cfb56b00a692..a0d10a71879e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -580,14 +580,17 @@ public String getName() { return name; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean isInstanceClass() { return HubType.isInstance(hubType); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean isStoredContinuationClass() { return HubType.isStoredContinuation(hubType); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public boolean isReferenceInstanceClass() { return HubType.isReferenceInstance(hubType); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/HubType.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/HubType.java index 94a780ee4d40..6a31527e46e2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/HubType.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/HubType.java @@ -25,6 +25,7 @@ package com.oracle.svm.core.hub; import com.oracle.svm.core.annotate.DuplicatedInNativeCode; +import com.oracle.svm.core.annotate.Uninterruptible; @DuplicatedInNativeCode public enum HubType { @@ -44,22 +45,27 @@ public enum HubType { this.value = value; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public int getValue() { return value; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isInstance(int hubType) { return hubType <= StoredContinuation.getValue(); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isReferenceInstance(int hubType) { return hubType == InstanceReference.getValue(); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isStoredContinuation(int hubType) { return hubType == StoredContinuation.getValue(); } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isArray(int hubType) { return hubType >= TypeArray.getValue(); } 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 bc2b40aa8ddb..0339cee88387 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 @@ -150,6 +150,7 @@ public static boolean isAbstract(int encoding) { return encoding == ABSTRACT_VALUE; } + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static boolean isInstance(int encoding) { return encoding > LAST_SPECIAL_VALUE; } From 02d80a187ab9fce74fb2c41f1fb2ec02f5af476b Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 23 Feb 2022 10:13:15 +0100 Subject: [PATCH 2/2] Review feedback and two more methods for printing hubs and objects. --- .../native-image/DebugInfo.md | 18 ++++ .../src/com/oracle/svm/core/DebugHelper.java | 90 +++++++++++-------- .../oracle/svm/core/SubstrateDiagnostics.java | 5 +- 3 files changed, 73 insertions(+), 40 deletions(-) diff --git a/docs/reference-manual/native-image/DebugInfo.md b/docs/reference-manual/native-image/DebugInfo.md index 302abb10d4d7..5a69cc0268d4 100644 --- a/docs/reference-manual/native-image/DebugInfo.md +++ b/docs/reference-manual/native-image/DebugInfo.md @@ -648,3 +648,21 @@ end (gdb) hubname_indirect 0x1dc860 0x7ffff78a52f0: "java.lang.Class" ``` + +## Debug Helper Methods + +On platforms where the debugging information is not fully supported, or when debugging complex issues, it can be helpful to print or query high-level information about the Native Image execution state. +For those scenarios, Native Image provides debug helper methods that can be embedded into a native image by specifying the build-time option `-H:+IncludeDebugHelperMethods`. +While debugging, it is then possible to invoke those debug helper methods like any normal C method. +This functionality is compatible with pretty much any debugger. + +While debugging with gdb, the following command can be used to list all debug helper methods that are embedded into the native image: +``` +(gdb) info functions svm_dbg_ +``` + +Before invoking a method, it is best to directly look at the source code of the Java class `DebugHelper` to determine which arguments each method expects. +For example, calling the method below prints high-level information about the Native Image execution state similar to what is printed for a fatal error: +``` +(gdb) call svm_dbg_print_fatalErrorDiagnostics($r15, $rsp, $rip) +``` \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java index 4bae4b20e5a6..e1f7143a51e5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/DebugHelper.java @@ -50,17 +50,20 @@ import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.thread.VMThreads; +/** + * All {@link CEntryPoint} methods in here can be directly called from a debugger. + */ public class DebugHelper { static class PointerDebugHelper { @Uninterruptible(reason = "Called with a raw pointer.") - @CEntryPoint(name = "dbg_ptr_isInImageHeap", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_ptr_isInImageHeap", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isInImageHeap(@SuppressWarnings("unused") IsolateThread thread, Pointer ptr) { return Heap.getHeap().isInImageHeap(ptr); } @Uninterruptible(reason = "Called with a raw pointer.") - @CEntryPoint(name = "dbg_ptr_isObject", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_ptr_isObject", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isObject(@SuppressWarnings("unused") IsolateThread thread, Pointer ptr) { ObjectHeader header = Heap.getHeap().getObjectHeader(); @@ -70,7 +73,7 @@ public static boolean isObject(@SuppressWarnings("unused") IsolateThread thread, static class HubDebugHelper { @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_getLayoutEncoding", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_getLayoutEncoding", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static int getLayoutEncoding(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -78,7 +81,7 @@ public static int getLayoutEncoding(@SuppressWarnings("unused") IsolateThread th } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_getArrayElementSize", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_getArrayElementSize", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -86,7 +89,7 @@ public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static int getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -94,7 +97,7 @@ public static int getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread t } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_isArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_isArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -102,7 +105,7 @@ public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_isPrimitiveArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_isPrimitiveArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -110,7 +113,7 @@ public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_isObjectArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_isObjectArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -118,7 +121,7 @@ public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread th } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_isInstance", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_isInstance", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isInstance(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -126,7 +129,7 @@ public static boolean isInstance(@SuppressWarnings("unused") IsolateThread threa } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_hub_isReference", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_hub_isReference", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isReference(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { DynamicHub hub = (DynamicHub) hubPtr.toObject(); @@ -136,7 +139,7 @@ public static boolean isReference(@SuppressWarnings("unused") IsolateThread thre static class ObjectDebugHelper { @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_getHub", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_getHub", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static long getHub(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -144,7 +147,7 @@ public static long getHub(@SuppressWarnings("unused") IsolateThread thread, Poin } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_getObjectSize", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_getObjectSize", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static long getObjectSize(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -152,7 +155,7 @@ public static long getObjectSize(@SuppressWarnings("unused") IsolateThread threa } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_getArrayElementSize", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_getArrayElementSize", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -161,7 +164,7 @@ public static int getArrayElementSize(@SuppressWarnings("unused") IsolateThread } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_getArrayBaseOffset", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static long getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -170,7 +173,7 @@ public static long getArrayBaseOffset(@SuppressWarnings("unused") IsolateThread } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_isArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_isArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -179,7 +182,7 @@ public static boolean isArray(@SuppressWarnings("unused") IsolateThread thread, } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_isPrimitiveArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_isPrimitiveArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -188,7 +191,7 @@ public static boolean isPrimitiveArray(@SuppressWarnings("unused") IsolateThread } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_isObjectArray", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_isObjectArray", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -197,7 +200,7 @@ public static boolean isObjectArray(@SuppressWarnings("unused") IsolateThread th } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_isInstance", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_isInstance", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isInstance(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -206,7 +209,7 @@ public static boolean isInstance(@SuppressWarnings("unused") IsolateThread threa } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_isReference", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_isReference", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static boolean isReference(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -215,14 +218,14 @@ public static boolean isReference(@SuppressWarnings("unused") IsolateThread thre } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_uncompress", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_uncompress", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static long uncompressObjectPointer(@SuppressWarnings("unused") IsolateThread thread, Pointer compressedPtr) { return Word.objectToUntrackedPointer(ReferenceAccess.singleton().uncompressReference(compressedPtr)).rawValue(); } @Uninterruptible(reason = "Called with a raw object pointer.") - @CEntryPoint(name = "dbg_obj_compress", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_obj_compress", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static long compressObjectPointer(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { Object obj = objPtr.toObject(); @@ -232,32 +235,47 @@ public static long compressObjectPointer(@SuppressWarnings("unused") IsolateThre static class StringDebugHelper { @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) - @CEntryPoint(name = "dbg_string_print", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_string_length", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) - public static void printString(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { + public static int getStringLength(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { String str = (String) strPtr.toObject(); - Log.log().string(str).newline(); + return str.length(); } + } + static class DiagnosticDebugHelper { @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) - @CEntryPoint(name = "dbg_string_length", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_print_hub", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) - public static int getStringLength(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { + public static void printHub(@SuppressWarnings("unused") IsolateThread thread, Pointer hubPtr) { + DynamicHub hub = (DynamicHub) hubPtr.toObject(); + Log.log().string(hub.getName()).newline(); + } + + @Uninterruptible(reason = "Called with a raw object pointer.") + @CEntryPoint(name = "svm_dbg_print_obj", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static void printObject(@SuppressWarnings("unused") IsolateThread thread, Pointer objPtr) { + SubstrateDiagnostics.printObjectInfo(Log.log(), objPtr); + } + + @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) + @CEntryPoint(name = "svm_dbg_print_string", include = IncludeDebugHelperMethods.class) + @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) + public static void printString(@SuppressWarnings("unused") IsolateThread thread, Pointer strPtr) { String str = (String) strPtr.toObject(); - return str.length(); + Log.log().string(str).newline(); } - } - static class DiagnosticDebugHelper { @Uninterruptible(reason = "Just to keep the verification happy.", calleeMustBe = false) - @CEntryPoint(name = "dbg_printFatalError", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_print_fatalErrorDiagnostics", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) - public static void printFatalError(@SuppressWarnings("unused") IsolateThread thread, Pointer sp, CodePointer ip) { + public static void printFatalErrorDiagnostics(@SuppressWarnings("unused") IsolateThread thread, Pointer sp, CodePointer ip) { SubstrateDiagnostics.printFatalError(Log.log(), sp, ip, WordFactory.nullPointer(), false); } @Uninterruptible(reason = "Just to keep the verification happy.", calleeMustBe = false) - @CEntryPoint(name = "dbg_printLocationInfo", include = IncludeDebugHelperMethods.class) + @CEntryPoint(name = "svm_dbg_print_locationInfo", include = IncludeDebugHelperMethods.class) @CEntryPointOptions(prologue = SetThreadAndHeapBasePrologue.class, epilogue = NoEpilogue.class, publishAs = Publish.SymbolOnly) public static void printLocationInfo(@SuppressWarnings("unused") IsolateThread thread, Pointer mem) { SubstrateDiagnostics.printLocationInfo(Log.log(), mem, true, true); @@ -307,7 +325,6 @@ private static boolean isReference(DynamicHub hub) { private static class SetThreadAndHeapBasePrologue implements CEntryPointOptions.Prologue { @Uninterruptible(reason = "prologue") - @SuppressWarnings("unused") public static void enter(IsolateThread thread) { WriteCurrentVMThreadNode.writeCurrentVMThread(thread); if (SubstrateOptions.SpawnIsolates.getValue()) { @@ -316,14 +333,11 @@ public static void enter(IsolateThread thread) { } } + @Platforms(Platform.HOSTED_ONLY.class) private static class IncludeDebugHelperMethods implements BooleanSupplier { - @Platforms(Platform.HOSTED_ONLY.class) - IncludeDebugHelperMethods() { - } - @Override public boolean getAsBoolean() { - return SubstrateOptions.IncludeDebugHelperMethods.getValue() || SubstrateOptions.optimizationLevel() == 0; + return SubstrateOptions.IncludeDebugHelperMethods.getValue(); } } } 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 d2e9eec60b77..bd0cf2a0537e 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 @@ -134,15 +134,16 @@ public static void printLocationInfo(Log log, UnsignedWord value, boolean allowJ } } + @Uninterruptible(reason = "Called with a raw object pointer.", calleeMustBe = false) public static void printObjectInfo(Log log, Pointer ptr) { DynamicHub objHub = Heap.getHeap().getObjectHeader().readDynamicHubFromPointer(ptr); - if (objHub == SubstrateUtil.cast(DynamicHub.class, DynamicHub.class)) { + if (objHub == DynamicHub.fromClass(DynamicHub.class)) { // The pointer is already a hub, so print some information about the hub. DynamicHub hub = (DynamicHub) ptr.toObject(); log.string("is the hub of ").string(hub.getName()); } else { // The pointer is an object, so print some information about the object's hub. - log.string("is an object with hub=").string(objHub.getName()); + log.string("is an object of type ").string(objHub.getName()); } }