diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyDebugUsage.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyDebugUsage.java index 340d1da1f6e4..64b7b52a4747 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyDebugUsage.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/VerifyDebugUsage.java @@ -203,7 +203,9 @@ protected int verifyDumpLevelParameter(MethodCallTargetNode debugCallTarget, Res protected void verifyDumpObjectParameter(MethodCallTargetNode debugCallTarget, ValueNode arg, ResolvedJavaMethod verifiedCallee, Integer dumpLevel) throws VerifyPhase.VerificationError { ResolvedJavaType argType = ((ObjectStamp) arg.stamp(NodeView.DEFAULT)).type(); - if (metaAccess.lookupJavaType(Graph.class).isAssignableFrom(argType)) { + // GR-64309: Calls returning interface type are built with an unrestricted stamp. ArgType is + // null for SubstrateInstalledCode. + if (argType != null && metaAccess.lookupJavaType(Graph.class).isAssignableFrom(argType)) { verifyStructuredGraphDumping(debugCallTarget, verifiedCallee, dumpLevel); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java index e5b1ee7f03fc..75aa5268f0e1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalVMEventListener.java @@ -24,7 +24,6 @@ */ package jdk.graal.compiler.hotspot; -import jdk.graal.compiler.code.CompilationResult; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugOptions; import jdk.vm.ci.code.CompiledCode; @@ -56,8 +55,6 @@ public void notifyShutdown() { public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { DebugContext debug = DebugContext.forCurrentThread(); if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { - CompilationResult compResult = debug.contextLookup(CompilationResult.class); - assert compResult != null : "can't dump installed code properly without CompilationResult"; debug.dump(DebugContext.BASIC_LEVEL, installedCode, "After code installation"); } if (debug.isLogEnabled()) { diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index 636fe20fabfc..1d86b58566b8 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -395,6 +395,29 @@ def truffle_unittest_task(extra_build_args=None): # GR-44492 native_unittest(['jdk.graal.compiler.truffle.test.ContextLookupCompilationTest'] + truffle_args(extra_build_args + svm_experimental_options(['-H:-SupportCompileInIsolates']))) + logfile = tempfile.NamedTemporaryFile(mode='w', delete=False) + logfile.close() + success = False + try: + native_unittest(['com.oracle.truffle.sl.test.SLFactorialTest'] + truffle_args(extra_build_args) +[ + '-Dpolyglot.engine.CompileImmediately=true', + '-Dpolyglot.engine.BackgroundCompilation=false', + f'-Dpolyglot.log.file={logfile.name}', + '-Djdk.graal.PrintCompilation=true' + ]) + compilation_pattern = re.compile(r"^SubstrateCompilation-.*root_eval.*allocated start=0x([0-9a-f]*)$") + with open(logfile.name) as f: + for line in f: + match = compilation_pattern.match(line) + if match and int(match.group(1), 16) != 0: + success = True + break + if not success: + mx.abort(f"Failed to find expected PrintCompilation output in log file: {logfile.name}.") + finally: + if success: + os.unlink(logfile.name) + def truffle_context_pre_init_unittest_task(extra_build_args): native_unittest(['com.oracle.truffle.api.test.polyglot.ContextPreInitializationNativeImageTest'] + truffle_args(extra_build_args)) diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java index 4e7d3bace565..2c3322530f6d 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java @@ -34,6 +34,7 @@ import com.oracle.svm.graal.meta.SubstrateCodeCacheProvider; import com.oracle.svm.graal.meta.SubstrateMethod; +import jdk.graal.compiler.debug.DebugContext; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.RegisterConfig; @@ -68,8 +69,11 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile ImageHeapRef methodRef = ImageHeapObjects.ref((SubstrateMethod) method); installedCode = IsolatedRuntimeCodeInstaller.installInClientIsolate(methodRef, result, installedCodeFactoryHandle); } - installBridge.setSubstrateInstalledCodeHandle(installedCode); + DebugContext debug = DebugContext.forCurrentThread(); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { + debug.dump(DebugContext.BASIC_LEVEL, installBridge, "After code installation"); + } return installBridge; } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCodeInstallBridge.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCodeInstallBridge.java index 5bea3b0063b1..80bb5e09e886 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCodeInstallBridge.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolatedCodeInstallBridge.java @@ -24,12 +24,21 @@ */ package com.oracle.svm.graal.isolated; +import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.code.CodeInfo; +import com.oracle.svm.core.code.CodeInfoAccess; +import com.oracle.svm.core.code.CodeInfoTable; +import com.oracle.svm.core.code.UntetheredCodeInfo; import com.oracle.svm.core.deopt.SubstrateInstalledCode; import com.oracle.svm.core.util.VMError; import com.oracle.truffle.compiler.OptimizedAssumptionDependency; import com.oracle.truffle.compiler.TruffleCompilable; +import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.InstalledCode; +import org.graalvm.nativeimage.c.function.CEntryPoint; +import org.graalvm.nativeimage.c.function.CodePointer; +import org.graalvm.nativeimage.c.type.CTypeConversion; /** * A helper to pass information for installing code in the compilation client through a Truffle @@ -66,14 +75,32 @@ public String getName() { throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); } + /** + * This method is used by the compiler debugging feature + * {@code jdk.graal.PrintCompilation=true}. + */ @Override public long getStart() { - throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); + ClientHandle handle = installedCodeHandle; + if (handle.notEqual(IsolatedHandles.nullHandle())) { + return getStart0(IsolatedCompileContext.get().getClient(), handle); + } else { + return 0L; + } } + /** + * This method is used by the compiler debugging feature {@code jdk.graal.Dump=CodeInstall} to + * dump a code at the point of code installation. + */ @Override public boolean isValid() { - throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); + ClientHandle handle = installedCodeHandle; + if (handle.notEqual(IsolatedHandles.nullHandle())) { + return isValid0(IsolatedCompileContext.get().getClient(), handle); + } else { + return false; + } } @Override @@ -81,9 +108,19 @@ public boolean isAlive() { throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); } + /** + * This method is used by the compiler debugging feature {@code jdk.graal.Dump=CodeInstall} to + * dump a code at the point of code installation. + */ @Override public byte[] getCode() { - throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); + ClientHandle handle = installedCodeHandle; + if (handle.notEqual(IsolatedHandles.nullHandle())) { + CompilerHandle codeHandle = getCode0(IsolatedCompileContext.get().getClient(), handle); + return codeHandle == IsolatedHandles.nullHandle() ? null : IsolatedCompileContext.get().unhand(codeHandle); + } else { + return null; + } } @Override @@ -101,4 +138,46 @@ public TruffleCompilable getCompilable() { throw VMError.shouldNotReachHere(DO_NOT_CALL_REASON); } + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = CEntryPoint.Publish.NotPublished) + private static long getStart0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle installedCodeHandle) { + return IsolatedCompileClient.get().unhand(installedCodeHandle).getAddress(); + } + + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = CEntryPoint.Publish.NotPublished) + private static boolean isValid0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle installedCodeHandle) { + return IsolatedCompileClient.get().unhand(installedCodeHandle).isValid(); + } + + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = CEntryPoint.Publish.NotPublished) + private static CompilerHandle getCode0(@SuppressWarnings("unused") ClientIsolateThread client, ClientHandle installedCodeHandle) { + SubstrateInstalledCode installedCode = IsolatedCompileClient.get().unhand(installedCodeHandle); + return getCodeUninterruptible(Word.pointer(installedCode.getEntryPoint())); + } + + @Uninterruptible(reason = "Accesses code info.") + private static CompilerHandle getCodeUninterruptible(CodePointer entryPointAddress) { + UntetheredCodeInfo untetheredCodeInfo = CodeInfoTable.lookupCodeInfo(entryPointAddress); + if (untetheredCodeInfo.isNull()) { + return IsolatedHandles.nullHandle(); + } + Object tether = CodeInfoAccess.acquireTether(untetheredCodeInfo); + try { + CodeInfo codeInfo = CodeInfoAccess.convert(untetheredCodeInfo, tether); + return copyCode0(codeInfo); + } finally { + CodeInfoAccess.releaseTether(untetheredCodeInfo, tether); + } + } + + @Uninterruptible(reason = "Wrap the now safe call to code info.", calleeMustBe = false) + private static CompilerHandle copyCode0(CodeInfo codeInfo) { + return copyCodeInCompilerIsolate0(IsolatedCompileClient.get().getCompiler(), CodeInfoAccess.getCodeStart(codeInfo), (int) CodeInfoAccess.getCodeSize(codeInfo).rawValue()); + } + + @CEntryPoint(include = CEntryPoint.NotIncludedAutomatically.class, publishAs = CEntryPoint.Publish.NotPublished) + private static CompilerHandle copyCodeInCompilerIsolate0(@SuppressWarnings("unused") @CEntryPoint.IsolateThreadContext CompilerIsolateThread context, CodePointer codeStart, int codeSize) { + byte[] code = new byte[codeSize]; + CTypeConversion.asByteBuffer(codeStart, codeSize).get(code); + return IsolatedCompileContext.get().hand(code); + } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java index 3dd818d25f27..a29e8da48cd0 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java @@ -33,6 +33,7 @@ import com.oracle.svm.core.graal.meta.SharedRuntimeMethod; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.debug.DebugContext; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.RegisterConfig; @@ -60,6 +61,10 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile CompilationResult compResult = ((SubstrateCompiledCode) compiledCode).getCompilationResult(); substrateInstalledCode.setCompilationId(compResult.getCompilationId()); RuntimeCodeInstaller.install((SharedRuntimeMethod) method, compResult, substrateInstalledCode); + DebugContext debug = DebugContext.forCurrentThread(); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { + debug.dump(DebugContext.BASIC_LEVEL, substrateInstalledCode, "After code installation"); + } return predefinedInstalledCode; } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateInstalledCodeImpl.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateInstalledCodeImpl.java index 1531fb92a064..116e8e9ae8f5 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateInstalledCodeImpl.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateInstalledCodeImpl.java @@ -26,6 +26,8 @@ import static com.oracle.svm.core.util.VMError.shouldNotReachHere; +import com.oracle.svm.core.code.CodeInfoAccess; +import com.oracle.svm.core.code.UntetheredCodeInfo; import jdk.graal.compiler.core.common.CompilationIdentifier; import com.oracle.svm.core.Uninterruptible; @@ -37,8 +39,11 @@ import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.nativeimage.c.function.CodePointer; +import org.graalvm.nativeimage.c.type.CTypeConversion; /** * Represents the installed code of a runtime compiled method. Note that Truffle uses its own @@ -119,14 +124,48 @@ public SubstrateSpeculationLog getSpeculationLog() { public void setCompilationId(CompilationIdentifier id) { } + /** + * This method is used by the compiler debugging feature + * {@code jdk.graal.PrintCompilation=true}. + */ @Override public long getStart() { - throw shouldNotReachHere("No implementation in Substrate VM"); + return getAddress(); } + /** + * This method is used by the compiler debugging feature {@code jdk.graal.Dump=CodeInstall} to + * dump a code at the point of code installation. + */ @Override public byte[] getCode() { - throw shouldNotReachHere("No implementation in Substrate VM"); + return getCode(Word.pointer(entryPoint)); + } + + @Uninterruptible(reason = "Accesses code info.") + public static byte[] getCode(CodePointer entryPointAddress) { + UntetheredCodeInfo untetheredCodeInfo = CodeInfoTable.lookupCodeInfo(entryPointAddress); + if (untetheredCodeInfo.isNull()) { + return null; + } + Object tether = CodeInfoAccess.acquireTether(untetheredCodeInfo); + try { + CodeInfo codeInfo = CodeInfoAccess.convert(untetheredCodeInfo, tether); + return copyCode0(codeInfo); + } finally { + CodeInfoAccess.releaseTether(untetheredCodeInfo, tether); + } + } + + @Uninterruptible(reason = "Wrap the now safe call to code info.", calleeMustBe = false) + private static byte[] copyCode0(CodeInfo codeInfo) { + return copyCode(CodeInfoAccess.getCodeStart(codeInfo), (int) CodeInfoAccess.getCodeSize(codeInfo).rawValue()); + } + + private static byte[] copyCode(CodePointer codeStart, int codeSize) { + byte[] code = new byte[codeSize]; + CTypeConversion.asByteBuffer(codeStart, codeSize).get(code); + return code; } @Override diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateOptimizedCallTargetInstalledCode.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateOptimizedCallTargetInstalledCode.java index f07b3b92341a..917cf84885bd 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateOptimizedCallTargetInstalledCode.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateOptimizedCallTargetInstalledCode.java @@ -26,6 +26,7 @@ import java.lang.ref.WeakReference; +import com.oracle.svm.graal.meta.SubstrateInstalledCodeImpl; import jdk.graal.compiler.word.Word; import com.oracle.svm.core.Uninterruptible; @@ -250,14 +251,22 @@ boolean isValidLastTier() { private static final String NOT_CALLED_IN_SUBSTRATE_VM = "No implementation in Substrate VM"; + /** + * This method is used by the compiler debugging feature + * {@code jdk.graal.PrintCompilation=true}. + */ @Override public long getStart() { - throw VMError.shouldNotReachHere(NOT_CALLED_IN_SUBSTRATE_VM); + return getAddress(); } + /** + * This method is used by the compiler debugging feature {@code jdk.graal.Dump=CodeInstall} to + * dump a code at the point of code installation. + */ @Override public byte[] getCode() { - throw VMError.shouldNotReachHere(NOT_CALLED_IN_SUBSTRATE_VM); + return SubstrateInstalledCodeImpl.getCode(Word.pointer(entryPoint)); } @Override