Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GR-54697] Implement debuginfo generation at image-runtime. #10522

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6428e75
Implementation for GDB JIT compilation interface
dominikmascherbauer Jun 26, 2024
8853448
Add a LocalVariableTable to SubstrateMethod
dominikmascherbauer Jun 26, 2024
8ff2d55
Create a test to manually trigger runtime compilation
dominikmascherbauer Jun 26, 2024
f2ee654
Create Initial Runtime Debug Info Implementation
dominikmascherbauer Jul 29, 2024
f9b8aef
Rework Runtime Debug Info Generation
dominikmascherbauer Sep 17, 2024
ce9464e
Implement the GDB JIT interface in System Java
dominikmascherbauer Oct 28, 2024
5938cc2
Refactor and rework gdb-debughelpers
dominikmascherbauer Oct 29, 2024
2207fea
Rework Debug Info Generation to create a Shared base for AOT and Runt…
dominikmascherbauer Nov 20, 2024
75e3ca0
Fix concurrency problems and some cleanup
dominikmascherbauer Dec 2, 2024
929f78a
Add some logging, Create more local info based on frame values, Bugfi…
dominikmascherbauer Dec 5, 2024
3dae547
Remove some constraints from logging in dwarf sections, Split up Debu…
dominikmascherbauer Dec 9, 2024
f111560
Cleanup, Refactoring and some Bugfixes
dominikmascherbauer Dec 10, 2024
68dee18
More Code Cleanup, Remove unused code, merge BFD Name providers
dominikmascherbauer Dec 12, 2024
d08b8e5
Code Cleanup and fix some issues with concurrency
dominikmascherbauer Dec 16, 2024
3b3f664
Add, update and fix copyright headers, fix style issues
dominikmascherbauer Dec 17, 2024
35a6d0f
Code cleanup and fix style issues
dominikmascherbauer Dec 19, 2024
93fc01a
Bugfix in handle release for GDB JIT compilation interface
dominikmascherbauer Jan 7, 2025
b4546fe
Updates and fixes of gdb-debughelpers for shared library supports
dominikmascherbauer Jan 10, 2025
a77914f
Add testing for runtime compilations
dominikmascherbauer Jan 10, 2025
2d16637
Update debug info provider to keep multi method info
dominikmascherbauer Jan 10, 2025
a0bb620
Fix style issue
dominikmascherbauer Jan 13, 2025
05969df
Bugfixes, fix style issue and add copyright headers
dominikmascherbauer Jan 14, 2025
7b88a7f
Bugfixes, Code Cleanup and fix style issue
dominikmascherbauer Jan 15, 2025
ce26fe1
Code cleanup, Add comments
dominikmascherbauer Jan 17, 2025
06ef6ab
Fix style issues
dominikmascherbauer Jan 17, 2025
c4c5130
Fix style issues, Add native image config for runtimedebuginfotest
dominikmascherbauer Jan 21, 2025
a6101eb
Add changelog entry
dominikmascherbauer Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Create a test to manually trigger runtime compilation
  • Loading branch information
dominikmascherbauer committed Jan 21, 2025
commit 8ff2d55b5cf777da5953037376e16c80efcf7079
35 changes: 35 additions & 0 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,32 @@ def _cinterfacetutorial(native_image, args=None):
mx.run([join(build_dir, 'cinterfacetutorial')])


def _runtimedebuginfotest(native_image, args=None):
"""Build and run the runtimedebuginfotest"""

args = [] if args is None else args
build_dir = join(svmbuild_dir(), 'runtimedebuginfotest')

# clean / create output directory
if exists(build_dir):
mx.rmtree(build_dir)
mx_util.ensure_dir_exists(build_dir)

# Build the native image from Java code
native_image([
'-g', '-O0', '--no-fallback',
'-o', join(build_dir, 'runtimedebuginfotest'),
'-cp', classpath('com.oracle.svm.test'),
'--features=com.oracle.svm.test.debug.RuntimeCompileDebugInfoTest$RegisterMethodsFeature',
'com.oracle.svm.test.debug.RuntimeCompileDebugInfoTest',
] + svm_experimental_options([
'-H:DebugInfoSourceSearchPath=' + mx.project('com.oracle.svm.test').source_dirs()[0],
]) + args)

# Start the native image
mx.run([join(build_dir, 'runtimedebuginfotest')])


_helloworld_variants = {
'traditional': '''
public class HelloWorld {
Expand Down Expand Up @@ -1821,6 +1847,14 @@ def cinterfacetutorial(args):
native_image_context_run(_cinterfacetutorial, args)


@mx.command(suite.name, 'runtimedebuginfotest', 'Runs the runtime debuginfo generation test')
def runtimedebuginfotest(args):
"""
runs a native image that compiles code and creates debug info at runtime.
"""
native_image_context_run(_runtimedebuginfotest, args)


@mx.command(suite.name, 'javaagenttest', 'Runs tests for java agent with native image')
def java_agent_test(args):
def build_and_run(args, binary_path, native_image, agents, agents_arg):
Expand Down Expand Up @@ -1859,6 +1893,7 @@ def build_and_test_java_agent_image(native_image, args):

native_image_context_run(build_and_test_java_agent_image, args)


@mx.command(suite.name, 'clinittest', 'Runs the ')
def clinittest(args):
def build_and_test_clinittest_image(native_image, args):
Expand Down
4 changes: 4 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,10 @@
"jdk.internal.misc",
"sun.security.jca",
],
"jdk.internal.vm.ci" : [
"jdk.vm.ci.code",
"jdk.vm.ci.meta",
],
},
"checkstyle": "com.oracle.svm.test",
"checkstyleVersion" : "10.21.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
package com.oracle.svm.test.debug;

import com.oracle.svm.core.NeverInline;
import com.oracle.svm.core.c.InvokeJavaFunctionPointer;
import com.oracle.svm.graal.SubstrateGraalUtils;
import com.oracle.svm.graal.hosted.runtimecompilation.RuntimeCompilationFeature;
import com.oracle.svm.graal.meta.SubstrateMethod;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.util.ModuleSupport;
import jdk.vm.ci.code.InstalledCode;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.VMRuntime;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeClassInitialization;
import org.graalvm.word.WordFactory;

import java.util.ArrayList;
import java.util.List;

import static com.oracle.svm.core.util.VMError.shouldNotReachHere;

class RuntimeCompilations {

Integer a;
int b;
String c;
Object d;

static Integer sa = 42;
static String sb;
static Object sc;

RuntimeCompilations(int a) {
this.a = a;
}

@NeverInline("For testing")
private void breakHere() {}

@NeverInline("For testing")
public Integer paramMethod(int param1, String param2, Object param3) {
breakHere();
b = param1;
breakHere();
c = param2;
breakHere();
d = param3;
breakHere();
return a;
}

@NeverInline("For testing")
public Integer noParamMethod() {
return a;
}

@NeverInline("For testing")
public void voidMethod() {
a *= 2;
}

@NeverInline("For testing")
public int primitiveReturnMethod(int param1) {
a = param1;
return param1;
}

@NeverInline("For testing")
public Integer[] arrayMethod(int[] param1, String[] param2) {
a = param1[0];
return new Integer[] { a };
}

@NeverInline("For testing")
public float localsMethod(String param1) {
float f = 1.5f;
String x = param1;
byte[] bytes = x.getBytes();
return f;
}

@NeverInline("For testing")
public static Integer staticMethod(int param1, String param2, Object param3) {
sa = param1;
sb = param2;
sc = param3;
return sa;
}
}

public class RuntimeCompileDebugInfoTest {
static class RuntimeHolder {
SubstrateMethod testMethod1;
SubstrateMethod testMethod2;
SubstrateMethod testMethod3;
SubstrateMethod testMethod4;
SubstrateMethod testMethod5;
SubstrateMethod testMethod6;
SubstrateMethod testMethod7;
}

public static class RegisterMethodsFeature implements Feature {
RegisterMethodsFeature() {
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, RegisterMethodsFeature.class, false,
"org.graalvm.nativeimage.builder",
"com.oracle.svm.graal", "com.oracle.svm.graal.hosted.runtimecompilation", "com.oracle.svm.hosted");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, RegisterMethodsFeature.class, false,
"jdk.internal.vm.ci",
"jdk.vm.ci.code");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, RegisterMethodsFeature.class, false,
"jdk.graal.compiler",
"jdk.graal.compiler.api.directives");
}

@Override
public List<Class<? extends Feature>> getRequiredFeatures() {
return List.of(RuntimeCompilationFeature.class);
}

@Override
public void beforeAnalysis(BeforeAnalysisAccess a) {
BeforeAnalysisAccessImpl config = (BeforeAnalysisAccessImpl) a;

RuntimeHolder holder = new RuntimeHolder();
RuntimeClassInitialization.initializeAtBuildTime(RuntimeHolder.class);
ImageSingletons.add(RuntimeHolder.class, holder);

RuntimeCompilationFeature runtimeCompilationFeature = RuntimeCompilationFeature.singleton();
runtimeCompilationFeature.initializeRuntimeCompilationForTesting(config);

holder.testMethod1 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "paramMethod", int.class, String.class, Object.class);
holder.testMethod2 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "noParamMethod");
holder.testMethod3 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "voidMethod");
holder.testMethod4 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "primitiveReturnMethod", int.class);
holder.testMethod5 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "arrayMethod", int[].class, String[].class);
holder.testMethod6 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "localsMethod", String.class);
holder.testMethod7 = prepareMethodForRuntimeCompilation(config, runtimeCompilationFeature, RuntimeCompilations.class, "staticMethod", int.class, String.class, Object.class);
}

private SubstrateMethod prepareMethodForRuntimeCompilation(BeforeAnalysisAccessImpl config, RuntimeCompilationFeature runtimeCompilationFeature, Class<?> holder, String methodName, Class<?>... signature) {
RuntimeClassInitialization.initializeAtBuildTime(holder);
try {
return runtimeCompilationFeature.prepareMethodForRuntimeCompilation(holder.getMethod(methodName, signature), config);
} catch (NoSuchMethodException ex) {
throw shouldNotReachHere(ex);
}
}
}


interface TestFunctionPointer extends CFunctionPointer {
@InvokeJavaFunctionPointer
Integer invoke(Object receiver, int arg1, String arg2, Object arg3);
@InvokeJavaFunctionPointer
Object invoke(Object receiver);
@InvokeJavaFunctionPointer
int invoke(Object receiver, int arg1);
@InvokeJavaFunctionPointer
Integer[] invoke(Object receiver, int[] arg1, String[] arg2);
@InvokeJavaFunctionPointer
float invoke(Object receiver, String arg1);
@InvokeJavaFunctionPointer
Integer invoke(int arg1, String arg2, Object arg3);
}

private static RuntimeHolder getHolder() {
return ImageSingletons.lookup(RuntimeHolder.class);
}

private static Integer invoke(TestFunctionPointer functionPointer, Object receiver, int arg1, String arg2, Object arg3) {
return functionPointer.invoke(receiver, arg1, arg2, arg3);
}

private static Object invoke(TestFunctionPointer functionPointer, Object receiver) {
return functionPointer.invoke(receiver);
}

private static int invoke(TestFunctionPointer functionPointer, Object receiver, int arg1) {
return functionPointer.invoke(receiver, arg1);
}

private static Integer[] invoke(TestFunctionPointer functionPointer, Object receiver, int[] arg1, String[] arg2) {
return functionPointer.invoke(receiver, arg1, arg2);
}

private static float invoke(TestFunctionPointer functionPointer, Object receiver, String arg1) {
return functionPointer.invoke(receiver, arg1);
}

private static Integer invoke(TestFunctionPointer functionPointer, Integer arg1, String arg2, Object arg3) {
return functionPointer.invoke(arg1, arg2, arg3);
}

private static TestFunctionPointer getFunctionPointer(InstalledCode installedCode) {
return WordFactory.pointer(installedCode.getEntryPoint());
}

public static void testParams() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod1);
InstalledCode installedCodeStatic = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod7);

RuntimeCompilations x = new RuntimeCompilations(11);
int param1 = 27;
String param2 = "test";
Object param3 = new ArrayList<>();

Integer result = invoke(getFunctionPointer(installedCode), x, param1, param2, param3);
Integer resultStatic = invoke(getFunctionPointer(installedCodeStatic), param1, param2, param3);

installedCode.invalidate();
installedCodeStatic.invalidate();
}

public static void testNoParam() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod2);

RuntimeCompilations x = new RuntimeCompilations(11);

Integer result = (Integer) invoke(getFunctionPointer(installedCode), x);

installedCode.invalidate();
}

public static void testVoid() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod3);

RuntimeCompilations x = new RuntimeCompilations(11);

invoke(getFunctionPointer(installedCode), x);

installedCode.invalidate();
}

public static void testPrimitiveReturn() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod4);

RuntimeCompilations x = new RuntimeCompilations(11);
int param1 = 42;

int result = invoke(getFunctionPointer(installedCode), x, param1);

installedCode.invalidate();
}

public static void testArray() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod5);

RuntimeCompilations x = new RuntimeCompilations(11);
int[] param1 = new int[] {1,2,3,4};
String[] param2 = new String[] {"this", "is", "an", "array"};

Integer[] result = invoke(getFunctionPointer(installedCode), x, param1, param2);

installedCode.invalidate();
}

public static void testLocals() {

InstalledCode installedCode = SubstrateGraalUtils.compileAndInstall(getHolder().testMethod6);

RuntimeCompilations x = new RuntimeCompilations(11);
String param1 = "test";

float result = invoke(getFunctionPointer(installedCode), x, param1);

installedCode.invalidate();
}

public static void testAOTCompiled() {

RuntimeCompilations x = new RuntimeCompilations(11);
int param1 = 27;
String param2 = "test";
Object param3 = new ArrayList<>();

Integer result = x.paramMethod(param1, param2, param3);
Integer result2 = RuntimeCompilations.staticMethod(param1, param2, param3);
Integer result3 = x.noParamMethod();
}

public static void main(String[] args) {
/* Run startup hooks to, e.g., install the segfault handler so that we get crash reports. */
VMRuntime.initialize();

// aot compiled code for comparing generated debug infos
testAOTCompiled();

// use runtime compiled code
testParams();
testNoParam();
testVoid();
testPrimitiveReturn();
testArray();
testLocals();
}
}