Point where code installed by C1 and C2 is loaded?
Vladimir Ivanov
vladimir.x.ivanov at oracle.com
Thu Oct 13 17:12:59 UTC 2022
> Looking at set_code it seems to me like the redirection is done in
>
> mh->_from_compiled_entry = code->verified_entry_point();
>
> while
>
> mh->_from_interpreted_entry = mh->get_i2c_entry();
>
> is done to make execution jump to compiled code if it was running in the
> interpreter prior, did i get that right? Seems a little strange to me
> that _code is also stored in the Method if it's not actually used in
> execution, but I guess it's probably used for other reasons. Given the
Method::code() is extensively used to get the nmethod associated with
the particular Method instance. It's possible to derive the same
information from Method::_from_compiled_entry, but it's much easier to
just keep a pointer to the nmethod itself.
> comments accompanying _from_compiled_entry and _from_interpreted_entry:
>
> // Entry point for calling from compiled code, to compiled code if it exists
> // or else the interpreter.
>
> // Cache of _code ? _adapter->i2c_entry() : _i2i_entry
> // Cache of: _code ? _code->entry_point() : _adapter->c2i_entry()
>
> If i understand this correctly, if _code != NULL,
> _from_interpreted_entry would be _adapter->i2c_entry(), which is(?) a
> CodeBlob containing assembly to transfer control to the associated
> nmethod, and vice versa for _from_compiled_entry? I am somewhat curious
> about where these are actually loaded during frame creation, and how the
> runtime would know whether what it just received were the contents of
> an nmethod that could be executed immediately, or a method running in
> the interpreter that needs to be decoded, dispatched, etc.
I'm not sure I fully understood your question.
Interpreter and compiled code have different calling conventions, that's
the reason why they use distinct entry points. i2c/c2i are frameless
adapters which perform conversion between those calling conventions as
part of invocation. See SharedRuntime::generate_i2c2i_adapters() for
details [1].
Best regards,
Vladimir Ivanov
[1]
https://github.com/openjdk/jdk/blob/master/src/hotspot/share/runtime/sharedRuntime.hpp#L394-L426
>
> I appreciate the response explaining method invocation!
>
> best regards,
> Julian
>
> On Thu, Oct 13, 2022 at 1:13 AM Vladimir Ivanov
> <vladimir.x.ivanov at oracle.com <mailto:vladimir.x.ivanov at oracle.com>> wrote:
>
> 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 <https://urldefense.com/v3/__https://github.com/openjdk/jdk/blob/master/src/hotspot/share/oops/method.hpp*L109-L118__;Iw!!ACWV5N9M2RV99hQ!MUt3I6g-RaNuCNWRFRx0pelLvi4jGEvnVQw2OwfKU7V9di9xQwY3yDF30lqD8l7cNrqEYwuGB5m3gV1i3mPU6tXk7j8D-Q$>
>
> 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