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