Point where code installed by C1 and C2 is loaded?

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Oct 12 17:12:54 UTC 2022


At runtime, every method is invoked either through 
Method::_from_compiled_entry or Method::_from_interpreted_entry 
(depending on where the call is performed from).

As part of nmethod installation (ciEnv::register_method()), entry points 
of the relevant method (the root of the compilation) are updated (by 
Method::set_code()) and Method::_from_compiled_entry starts to point to 
the entry point of the freshly installed nmethod.

(Also, there is a special case of OSR compilation, but I don't cover it 
here.)

src/hotspot/share/oops/method.hpp [1]:

class Method : public Metadata {
...
   // Entry point for calling from compiled code, to compiled code if it 
exists
   // or else the interpreter.
   volatile address _from_compiled_entry;        // Cache of: _code ? 
_code->entry_point() : _adapter->c2i_entry()
   // The entry point for calling both from and to compiled code is
   // "_code->entry_point()".  Because of tiered compilation and de-opt, 
this
   // field can come and go.  It can transition from NULL to not-null at any
   // time (whenever a compile completes).  It can transition from 
not-null to
   // NULL only at safepoints (because of a de-opt).
   CompiledMethod* volatile _code;                       // Points to 
the corresponding piece of native code
   volatile address           _from_interpreted_entry; // Cache of _code 
? _adapter->i2c_entry() : _i2i_entry

Hp

Best regards,
Vladimir Ivanov

[1] 
https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/method.hpp#L109-L118

On 10/12/22 08:18, Julian Waters wrote:
> Hi all,
> 
> I apologise if this is a silly question, but where exactly is code 
> installed by C1 and C2 loaded and executed by the runtime? I've tried 
> looking through the entirety of hotspot, but haven't found anything that 
> seems to be related. All I can surmise is that the compiler interface 
> ultimately creates an nmethod that allocates itself on the CodeCache 
> using a CodeBuffer containing C1 or C2 emitted instructions, and then 
> Method::set_code sets the method's _code to reference that entry in the 
> cache (or method->method_holder()->add_osr_nmethod(nm); is called in 
> other circumstances, I don't quite understand what the difference is but 
> I assume the end result is probably the same). Given my rudimentary 
> understanding of hotspot's execution pipeline I'd assume that when a new 
> frame (frame.hpp) is created, the frame's code blob would be set to 
> reference the nmethod in the method that was called, or otherwise 
> somehow jump back to the interpreter if that method hasn't been compiled 
> yet. But there doesn't seem to be any point where method->code() is 
> called to load the instructions emitted by either C1 or C2 into a frame, 
> so where does that happen?
> 
> I guess this is probably more a question of how hotspot runs loaded 
> programs in general, which seems to me at a glance like it's chaining 
> assembly in CodeBlobs together and jumping to the next blob/codelet (in 
> the next frame?) when it's finished, but I can't really figure out where 
> those codelets are set for each frame, or how it chooses between one 
> compiled by C1 or C2, and the handwritten assembly codelets that make up 
> the interpreter (or for that matter how it even finds the correct 
> interpreter codelet).
> 
> I appreciate any help with this query, sorry if this isn't the correct 
> list to post this question to, but it seemed like the most appropriate.
> 
> best regards,
> Julian


More information about the hotspot-compiler-dev mailing list