RFR: 8360389: Support printing from C2 compiled code

Benoît Maillard bmaillard at openjdk.org
Mon Aug 18 07:07:00 UTC 2025


On Mon, 28 Jul 2025 05:44:02 GMT, Tobias Hartmann <thartmann 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_new<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
>> ## 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 tim...
>
> src/hotspot/share/opto/runtime.cpp line 1787:
> 
>> 1785:   switch (parm->bottom_type()->basic_type()) {
>> 1786:     case T_BOOLEAN:
>> 1787:       fields[(*argp)++] = TypeInt::BOOL;
> 
> I think you can use `Type::get_const_basic_type(parm->bottom_type()->basic_type())` here and special case `T_DOUBLE` / `T_LONG`.

I was actually looking for something like this but must have missed it! Thanks

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

PR Review Comment: https://git.openjdk.org/jdk/pull/26475#discussion_r2238784716


More information about the hotspot-dev mailing list