Getting ciObject from oop/jobject

Krystal Mok rednaxelafx at gmail.com
Thu Aug 1 23:21:46 PDT 2013


Oops, I tried to put together a demo, but it seems like my earlier
suggestion doesn't work.

Here's the demo (that doesn't work):
https://gist.github.com/rednaxelafx/6137819

The patch is against tip version of hsx/hotspot-comp/hotspot.
Applying this patch gives you a VM that builds, but when it tries to
compile and inline our special intrinsic method, it crashes
in SharedRuntime::java_calling_convention().

The reason is that HotSpot's Java calling convention only expects the 12
basic types: boolean / byte / char / short / int / float / long / double /
address / object / array / void.
But "metadata" is not one of them. Before the PermGen removal project, it
used to be that metadata were "oops" too, so this kind of code would have
worked. Now "metadata" is distinct from "object", so...I'm not sure how to
proceed with this right now.

Sorry about it. Let's see if someone else would come up with a viable
solution.

(Actually, you don't have to generate inline code to make an intrinsic
work. Just as there's a fallback in the VM for Reflection.getCallerClass(),
which is JVM_GetCallerClass(). You could just implement your feature
without making it an inline intrinsic first. That way you can at least get
a running program and move on.)

- Kris


On Fri, Aug 2, 2013 at 10:19 AM, Krystal Mok <rednaxelafx at gmail.com> wrote:

> On Fri, Aug 2, 2013 at 10:15 AM, Nick Williams <
> nicholas+openjdk at nicholaswilliams.net> wrote:
>
>>
>> On Aug 1, 2013, at 9:07 PM, Krystal Mok wrote:
>>
>> Hi Nick,
>>
>> All right, that explains everything. My take on this:
>>
>> In HotSpot VM, the compiler threads shouldn't manipulate the Java object
>> graph; in other words, although the compilers have access to certain Java
>> objects through the Compiler Interface, it should only be "reading", but
>> not "writing" or creating new Java objects.
>>
>> In your case, calling java_lang_StackTraceFrame::create() from compiler
>> code creates a new object, and that's probably not the right way.
>> You're trying to embed a pointer to a StackTraceFrame object in the
>> generated code, as a constant. You don't have to do that. It might work if
>> you embed the Method* (as a TypeMetadataPtr), and generate a runtime call
>> to java_lang_StackTraceFrame::create() with that pointer, instead of
>> calling it at compile time.
>>
>>
>> Sounds good, but I'm not exactly sure how to do it. Do you mind assisting
>> a bit? Remember that "ciMethod* m" is the executing method on the stack
>> frame we're interested in. "Method* method" is the same thing, just in a
>> different form. It sounds like I need to actually embed a runtime call to
>> java_lang_StackTraceFrame::create()? I may be missing something. :-)
>>
>> Sure. I can give it a shot and see if it works.
> Do you have a full patch that I can use as a base, or would you just like
> to see a demo of doing a runtime call passing an embedded pointer constant?
>
> - Kris
>
>
>> Nick
>>
>>
>> HTH,
>> Kris
>>
>>
>> On Fri, Aug 2, 2013 at 9:28 AM, Nick Williams <
>> nicholas+openjdk at nicholaswilliams.net> wrote:
>>
>>> Well let me explain what I'm trying to do, and maybe someone can point
>>> me in the right direction.
>>>
>>> On the core-libs-dev mailing list, I proposed a public API replacement
>>> for the sun.reflect.Reflection#getCallerClass(int) of old and
>>> the sun.reflect.Reflection#getCallerClass() of now. The new class,
>>> java.lang.StackTraceFrame, has the following four methods that are relevant
>>> to this discussion:
>>>
>>> @CallerSensitive
>>> public native Class<?> getCallerClass();
>>> public native Class<?> getCallerClass(int);
>>> @CallerSensitive
>>> public native StackTraceFrame getCallerFrame();
>>> public native StackTraceFrame getCallerFrame(int);
>>>
>>> There is code in library_call.cpp that inlines
>>> Reflection.getCallerClass(), and I took advantage of that code to also
>>> inline StackTraceFrame.getCallerClass(). I also recreated (with changes
>>> necessary due to new way of doing things in library_call.cpp) the inline
>>> code for Reflection.getCallerClass(int) from the jdk7 source code. All of
>>> that works perfectly. Code is inlined as expected, and all is well.
>>>
>>> Now I want to inline getCallerFrame() and getCallerFrame(int) as well.
>>> If the Class<?> versions can be inlined, I see no reason that the
>>> StackTraceFrame versions can't be inlined, but that may be my first wrong
>>> assumption. If these methods aren't eligible for inlining for some reason,
>>> please let me know and I can move on.
>>>
>>> So the code that gets the Class<?> and sets it as an inline constant
>>> replacing the method call works like this (where m is a ciMethod*):
>>>
>>>           // Acquire method holder as java.lang.Class and push as
>>> constant.
>>>           ciInstanceKlass* caller_klass = m->holder();
>>>           ciInstance* caller_mirror = caller_klass->java_mirror();
>>>           set_result(makecon(TypeInstPtr::make(caller_mirror)));
>>>
>>> In javaClasses.cpp, I already have a method that can create a
>>> StackTraceFrame from a Method* (not ciMethod*), method version (int), and
>>> bci (int):
>>>
>>> oop java_lang_StackTraceFrame::create(Method* method, int version, int
>>> bci, TRAPS);
>>>
>>> I tried calling that to create the StackTraceFrame, but it appears I
>>> can't actually set it to the result. First I tried this:
>>>
>>>           // Acquire java.lang.StackTraceFrame and push as constant
>>>           Method* method = (Method*)m->constant_encoding();
>>>           oop stFrame = java_lang_StackTraceFrame::create(method,
>>> method->constants()->version(), caller_jvms->bci(), NULL);
>>>           set_result(makecon(TypeInstPtr::make(oop)));
>>>
>>> But this obviously didn't work because there is no TypeInstPtr::make()
>>> method that takes an oopDesc&. So I looked around trying to figure out how
>>> to convert an oop (or jobject, which I can get from an oop)  to a ciObject.
>>> I discovered that ciObject actually holds a jobject internally, so I
>>> figured surely this is possible. I found a few methods that appear to do
>>> it. ciObjectFactory has a ciObject* get(oop) method, but I can't figure out
>>> how to get the ciObjectFactory. ciEnv has a ciObject* get_object(oop)
>>> method which I tried to use, only to discover that it was private:
>>>
>>>           // Acquire java.lang.StackTraceFrame and push as constant
>>>           Method* method = (Method*)m->constant_encoding();
>>>           oop stFrame = java_lang_StackTraceFrame::create(method,
>>> method->constants()->version(), caller_jvms->bci(), NULL);
>>>           ciObject* stfObject = ciEnv::current()->get_object(stFrame);
>>>           set_result(makecon(TypeInstPtr::make(stfObject)));
>>>
>>> So that obviously doesn't work either. I'll admit, I'm a little out of
>>> my league here. I was pretty confident working in javaClasses.hpp/cpp and
>>> jvm.h/cpp, but this inlining/compiler stuff is pretty over my head.
>>> Hopefully one of the knowledgeable people on this list can help me out with
>>> this. I want my code to perform as well as possible and also be
>>> stable--more likely to get accepted that way. :-)
>>>
>>> Thanks,
>>>
>>> Nick
>>>
>>> On Aug 1, 2013, at 8:16 AM, Krystal Mok wrote:
>>>
>>> Hi Nick,
>>>
>>> This topic is related to HotSpot Server Compiler instead of the Java
>>> core library, so I'm cc'ing this email to hotspot-compiler-dev and dropping
>>> core-libs-dev.
>>>
>>> As you already know, HotSpot compilers are shielded from VM runtime
>>> implementation details via the Compiler Interface (CI). That's why you
>>> shouldn't be getting raw oops in C2 code.
>>>
>>> Where are you getting the oopInstance from? If it can be found from some
>>> known "roots", e.g. "well-known classes", fields of "well-known classes",
>>> or the holder class of the method to be compiled, etc., then it's already
>>> available through CI.
>>>
>>> - Kris
>>>
>>>
>>> On Thu, Aug 1, 2013 at 3:17 AM, Nick Williams <
>>> nicholas+openjdk at nicholaswilliams.net> wrote:
>>>
>>>> In native code (library_call.cpp), if I have an oop (which I can
>>>> convert to a jobject if need be), how do I get a ciObject? I see that ciEnv
>>>> has a ciObject* get_object(oop) method, but it's private. And
>>>> ciObjectFactory has a ciObject* get(oop) method, but I can't figure out how
>>>> to get the ciObjectFactory instance.
>>>>
>>>> I know that ciObject keeps a jobject internally, and I know that
>>>> ciObject has a ciObject(oop) constructor, but it's protected (for good
>>>> reason).
>>>>
>>>> If it helps, I'm trying to inline a method and need to
>>>> set_result(makecon(TypeInstPtr::make(oopInstance))). I may be going down
>>>> the wrong path.
>>>>
>>>> Thanks in advance for any help,
>>>>
>>>> Nick
>>>
>>>
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20130802/e4dc776e/attachment.html 


More information about the hotspot-compiler-dev mailing list