Question on TemplateTable::prepare_invoke
Tom Rodriguez
Thomas.Rodriguez at Sun.COM
Wed Mar 3 12:11:33 PST 2010
While call_VM generally takes care of saving off any needed state it's not implicitly safe to use every context. In particular I'd be suspicious of calling it after load_invoke_cp_cache_entry since that sets up state for use by later parts of the invoke path.
tom
On Mar 3, 2010, at 11:56 AM, Peng Du wrote:
> Hi, John
>
> Thanks for the hint. I tried using TraceBytecodes and StopInterpreterAt,
> but with no luck because the order in which each class in JDK is loaded
> is totally nondeterministic. Therefore, the bytecode index corresponding
> to String.java:1218 is distinct in each run.
>
> I also tried putting NOPs in the interpreter. However, I am not very
> proficient in debugging HotSpot at this level. So, I couldn't stop at
> the right place.
>
> Given the information in my first post, can someone shed some light on
> what could possibly be the reason of the error?
>
> Thanks
>
>
>
> On Wed, 2010-03-03 at 00:10 -0800, John Cuthbertson wrote:
>> Hi Peng,
>>
>> You may have to manually examine the generated interpreter code in a
>> debugger to detect a register overwrite. Be warned that the code that
>> gets generated for a call_VM macro is quite large - I find inserting
>> sequences of nops helps locate the code I'm interested in. You could
>> also try the TraceBytecodes and StopInterpreterAt flags in debug JVM and
>> then do instruction stepping within a debugger.
>>
>> As for register usage/conventions with the interpreter - the best source
>> is probably assembler_x86.hpp.
>>
>> Regards,
>>
>> JohnC
>>
>> Peng Du wrote:
>>> Hello,
>>>
>>> I have a very specific question about an error I ran into today. I am
>>> very familiar
>>> with assembly programming. So, please bear with me.
>>>
>>> If I understand correctly, TemplateTable::prepare_invoke is a helper
>>> methods for
>>> the invokeXXX bytecodes. What I tried to do was to pass the oop of the
>>> method
>>> receiver to InterpreterRuntime::cache_object, which simply caches it
>>> in the current
>>> thread.
>>>
>>> Below is an excerpt in templateTable_x86_64.cpp) that I modified, the
>>> cache_object method in interpreterRuntime.cpp, and the cache_object
>>> method
>>> in thread.hpp:
>>>
>>> ===========================================================
>>> void TemplateTable::prepare_invoke(Register, Register, int) {
>>> const Register recv = rcx;
>>> ...
>>> // load receiver if needed (note: no return address pushed yet)
>>> if (load_receiver) {
>>> __ movl(recv, flags);
>>> __ andl(recv, 0xFF);
>>> if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
>>> Address recv_addr(rsp, recv, Address::times_8,
>>> -Interpreter::expr_offset_in_bytes(1));
>>> if (is_invokedynamic) {
>>> __ lea(recv, recv_addr);
>>> } else {
>>> __ movptr(recv, recv_addr);
>>> __ verify_oop(recv);
>>> }
>>>
>>> // !!! cache receiver object !!!
>>> __ call_VM(noreg, CAST_FROM_FN_PTR(address,
>>> InterpreterRuntime::cache_object), recv);
>>> }
>>> ...
>>>
>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>
>>> IRT_ENTRY(void, InterpreterRuntime::cache_object(JavaThread* thread,
>>> oop o))
>>> thread->cache_object(o);
>>> IRT_END
>>>
>>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> class JavaThread {
>>> ...
>>> inline void cache_object(oop o) { _object = o; }
>>>
>>> ===========================================================
>>>
>>> However, this failed even in test_gamma with the following error:
>>> Error occurred during initialization of VM
>>> java.lang.StackOverflowError
>>> at java.lang.NullPointerException.<init>(NullPointerException.java:53)
>>> at java.lang.NullPointerException.<init>(NullPointerException.java:53)
>>> < a long list of NullPointerException same as above ... >
>>> at java.lang.String.<clinit>(String.java:1218)
>>>
>>> It appeared to me there is infinite recursive creations of
>>> NullPointerException
>>> somewhere caused by the static initializer in String class.
>>> String.java:1218
>>> looks like this:
>>>
>>> public static final Comparator<String> CASE_INSENSITIVE_ORDER = new
>>> CaseInsensitiveComparator();
>>>
>>> Is it because I somehow clobber the recv (rcx) register? Or can
>>> someone tell me
>>> what I did was wrong and how to fix it? Moreover, is there any
>>> documentation on
>>> the rules that how registers are used in template interpreter?
>>>
>>>
>>>
>>
>
>
More information about the hotspot-dev
mailing list