RFR: 8360389: Support printing from C2 compiled code [v8]

Emanuel Peter epeter at openjdk.org
Mon Sep 1 13:17:46 UTC 2025


On Tue, 26 Aug 2025 14:41:21 GMT, Benoît Maillard <bmaillard at openjdk.org> wrote:

>> This PR adds support for printf-style debugging from C2 compiled code. This is implemented as a runtime call to a C++ method that prints the values of the nodes passed as arguments. The runtime C++ method is implemented with the help of variadic templates, as it is expected to support various combinations of argument types.
>> 
>> ## Usage
>> 
>> Suppose we have this piece of Java code, that simply computes an arithmetic operation, and
>> that we compile `square` with C2.
>> 
>> class Square {
>>     static int square(int a) {
>>         return a * a;
>>     }
>> 
>>     public static void main(String[] args) {
>>         square(9);
>>     }
>> }
>> 
>> 
>> We would like to inspect the node that contains the value returned in this method.
>> We can add a call to `Compile::make_debug_print` and pass a message, the IGVN instance, as well as the node(s) that we would like to inspect.
>> 
>> ```c++
>> void Compile::return_values(JVMState* jvms) {
>>   GraphKit kit(jvms);
>>   Node* ret = new ReturnNode(TypeFunc::Parms,
>>                              kit.control(),
>>                              kit.i_o(),
>>                              kit.reset_memory(),
>>                              kit.frameptr(),
>>                              kit.returnadr());
>>   // Add zero or 1 return values
>>   int ret_size = tf()->range()->cnt() - TypeFunc::Parms;
>> 
>>   
>>   Node* return_value;
>>   if (ret_size > 0) {
>>     kit.inc_sp(-ret_size);  // pop the return value(s)
>>     kit.sync_jvms();
>>     return_value = kit.argument(0);
>>     ret->add_req(return_value);
>> 
>>     // <-------------------- Simply insert this
>>     C->make_debug_print<jint>("return: ", initial_gvn(), return_value);
>>   }
>>   
>>   // bind it to root
>>   root()->add_req(ret);
>>   record_for_igvn(ret);
>>   initial_gvn()->transform(ret);
>> }
>> 
>> 
>> We can then call run our code with `-XX:CompileCommand="compileonly,Square::square`
>> and we get the following output:
>> 
>> 
>> return:
>> int 81
>> 
>> 
>> This case is of course trivial, but more useful examples are shown later.
>> 
>> ## Implementation
>> 
>> The debugging capability is implemented as a runtime call to a C++ printing method. For this, `Compile::make_debug_print` inserts a `CallLeafNode` into the graph and rewires control flow as needed.
>> 
>> The actual printing is handled by the `SharedRuntime::debug_print` method, written with a variadic template to support various argument type combinations. A pointer to this runtime method is obtained at compile time and is passed to the ...
>
> Benoît Maillard has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Fix mismatch with #ifdef COMPILER2 between .hpp and .cpp

I have not read the PR in any detail. Just tried to use it in a bug I'm trying to fix. [JDK-8366490](https://bugs.openjdk.org/browse/JDK-8366490)

So I did this:


diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp
index cd5aba6c31d..1b1f7c2f6f2 100644
--- a/src/hotspot/share/opto/vectorization.cpp
+++ b/src/hotspot/share/opto/vectorization.cpp
@@ -1046,6 +1046,8 @@ BoolNode* VPointer::make_speculative_aliasing_check_with(const VPointer& other)
       tty->print("size2: "); size2->dump();
       tty->print_cr("span1: "); span1->dump_bfs(5, nullptr, "");
       tty->print_cr("span2: "); span2->dump_bfs(5, nullptr, "");
+
+      phase->C->make_debug_print<jlong>("span ", &igvn, span1);
     }
 #endif


And ran my test:
`./java -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,Reduced1::test -XX:CompileCommand=printcompilation,Reduced1::* -XX:CompileCommand=dontinline,Reduced1::allocateArrays -XX:-TieredCompilation -Xbatch -XX:+StressGCM -XX:+TraceLoopOpts -XX:CompileCommand=TraceAutoVectorization,Reduced1::test,SW_INFO,SPECULATIVE_ALIASING_ANALYSIS -XX:+TraceNewVectors -XX:-LoopMultiversioning -XX:SuperWordAutomaticAlignment=0 -XX:+TraceDeoptimization Reduced1.java`


class Reduced1 {
    static final int N = 400;

    static void allocateArrays() {
        for (int i = 0; 200_000 > i; ++i) {
            int[] a = new int[N];
        }
    }

    static int[] test() {
        int a[] = new int[N];
        allocateArrays();
        for (int k = 0; k < 500; k++) {
            for (int i = 1; i < 69; i++) {
                a[i] =  14;
                a[4] -= 14;
            }
        }
        return a;
    }

    public static void main(String[] args) {
        int[] gold = test();
        for (int r = 0; r < 10; r++) {
            int[] a = test();
            System.out.println("a[4]: " + a[4]);
            if (a[4] != gold[4]) {
                throw new RuntimeException("wrong value " + gold[4] + " " + a[4]);
            }
        }
    }
}


But that got me some assert:

#  Internal Error (/home/empeter/Documents/oracle/jdk-fork2/open/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp:1126), pid=2630187, tid=2630207
#  assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID) failed: expecting half

    33 Stack: [0x00007fe32ed13000,0x00007fe32ee13000],  sp=0x00007fe32ee0e8d0,  free space=1006k
    34 Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
    35 V  [libjvm.so+0x19a3163]  SharedRuntime::c_calling_convention(BasicType const*, VMRegPair*, int)+0x673  (sharedRuntime_x86_64.cpp:1126)
    36 V  [libjvm.so+0x1658abe]  Matcher::match_sfpt(SafePointNode*)+0xd6e  (matcher.cpp:1396)
    37 V  [libjvm.so+0x165b695]  Matcher::xform(Node*, int)+0x1075  (matcher.cpp:1159)
    38 V  [libjvm.so+0x1661b53]  Matcher::match()+0x1113  (matcher.cpp:369)
    39 V  [libjvm.so+0xb7b6ce]  Compile::Code_Gen()+0x1fe  (compile.cpp:3024)
    40 V  [libjvm.so+0xb81103]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1fd3  (compile.cpp:892)
    41 V  [libjvm.so+0x9a1f76]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x466  (c2compiler.cpp:147)
    42 V  [libjvm.so+0xb904c8]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xb48  (compileBroker.cpp:2342)
    43 V  [libjvm.so+0xb91650]  CompileBroker::compiler_thread_loop()+0x530  (compileBroker.cpp:1986)
    44 V  [libjvm.so+0x10f258b]  JavaThread::thread_main_inner()+0x13b  (javaThread.cpp:775)
    45 V  [libjvm.so+0x1b63d16]  Thread::call_run()+0xb6  (thread.cpp:243)
    46 V  [libjvm.so+0x17d94d8]  thread_native_entry(Thread*)+0x128  (os_linux.cpp:892)

Am I doing something wrong here, or is that maybe a limitation of the current implementation?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/26475#issuecomment-3242340816


More information about the hotspot-dev mailing list