Hi Volker, Happy New Year. I'd like to ask some question about hotspot of openjdk.

David Holmes - Sun Microsystems David.Holmes at Sun.COM
Tue Jan 6 04:07:48 PST 2009


Alex,

As I said look in bytecodeInterpreter for where 
InterpreterRuntime::monitorenter gets called as the code preceding that 
defines the fast-path. eg this is the non-biased-locking case for 
locking a synchronized method:

       markOop displaced = rcvr->mark()->set_unlocked();
       mon->lock()->set_displaced_header(displaced);
       if (Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != 
displaced) {
         // Is it simple recursive case?
         if (THREAD->is_lock_owned((address) 
displaced->clear_lock_bits())) {
           mon->lock()->set_displaced_header(NULL);
         } else {
           CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), 
handle_exception);
         }
       }

the cmpxchg_ptr tries to acquire the lock by updating the header of the 
object (fast-path), if it finds the object locked by another thread then 
it invokes InterpreterRuntime::monitorenter (slow-path).

Note that here the slow-path is what (may) lead to the monitor being 
inflated; there is yet another fast-path/slow-path in the 
ObjectSynchronizer code.

David

xinweix at cse.unsw.edu.au said the following on 01/06/09 21:04:
> Hi David,
> Thanks for your reply.
> I've check out the "Hotspot Runtime Overview", which says that slow-path 
> means the lock state is inflated. In other words, it is locked or 
> unlocked but shared and contented.
> 
>> InterpreterRuntime::monitorentry is the slow-path entry point for 
>> monitor acquisition.
> Where is the fast-path entry point in the template interpreter, as I 
> need to know all information about each accessing of share variant?
> 
> Regards,
> Alex Xie
> --------------------------------------------------
> From: "David Holmes - Sun Microsystems" <David.Holmes at Sun.COM>
> Sent: Tuesday, January 06, 2009 3:08 PM
> To: <xinweix at cse.unsw.edu.au>
> Cc: <hotspot-dev at openjdk.java.net>
> Subject: Re: Hi Volker,    Happy New Year. I'd like to ask some question 
> about hotspot of    openjdk.
> 
>> Alex,
>>
>> -Xint runs only the interpreter, the JIT compiler is disabled.
>>
>> InterpreterRuntime::monitorentry is the slow-path entry point for 
>> monitor acquisition. If you look in bytecodeInterpreter.cpp you will 
>> see the fast-path code that is used - see line 612 for method calls 
>> for example. If you search for the calls to 
>> InterpreterRuntime::monitorentry you will see the fast-path code for 
>> the different cases preceding it. Note that there are two different 
>> fast-paths depending on whether biased-locking is enabled or not.
>>
>> If you want to track all monitor acquisitions then you will need to 
>> modify the interpreter itself to add your tracking code.
>>
>> Hope this helps.
>>
>> David Holmes
>>
>>
>> xinweix at cse.unsw.edu.au said the following on 01/06/09 16:48:
>>> Hi Volker,
>>>
>>> Thanks very much for your great help. I'd like to discuss with you 
>>> the following questions:
>>>
>>> 1. I've followed your advise of using '-XX:+TraceBytecodes' and 
>>> identify the specific bytecode instruction. However, I encountered 
>>> the problem of SEGV fault when it is executing in 'monitorenter' 
>>> bytecode. I tried several times, but failed all the same.
>>>
>>> 2. If I follow the option of '-Xint', is the mechanism of JIT 
>>> compiler working there? If not, is it in the mixed mode? How can it 
>>> be activated? Are there some entry points? I found some compiler 
>>> introductions and optimizations published in some papers, such as 
>>> HIR(Highlevel Intermediate Representation), LIR and SSA forms, etc. 
>>> The IR is another type of bytecode. If I want to instrument bytecode, 
>>> such as 'monitorenter', 'monitorexit', is it feasible to work on the IR?
>>>
>>> 3. I tried to use '-XX:+PrintAssembly' option to get some ouputs, 
>>> that are composed of the assembly codes with respect to each 
>>> bytecode. Is it that each bunch of assembly codes will be executed 
>>> when 'Interpreter' executes each bytecode?
>>>
>>> 4. Is it that the function InterpreterRuntime::monitor is the entry 
>>> with respect to 'monitorenter' so that I can do something here?
>>>
>>> Regards,
>>>
>>> Alex Xie
>>>
>>> --------------------------------------------------
>>> From: "Volker Simonis" <volker.simonis at gmail.com>
>>> Sent: Monday, January 05, 2009 9:50 PM
>>> To: <xinweix at cse.unsw.edu.au>
>>> Cc: <hotspot-dev at openjdk.java.net>
>>> Subject: Re: Hi Volker, Happy New Year. I'd like to ask some question 
>>> about hotspot of openjdk.
>>>
>>>> Hi Alex,
>>>>
>>>> there are some things to consider if you want to debug the HotSpot 
>>>> interpreter:
>>>>
>>>> - gdb should work fairy well, however for some historic reasons, the
>>>> debug version of HotSpot on Linux/x86 is built with "-gstabs". To get
>>>> a better debugging experience, you should change this to "-g" at the
>>>> end of the file "hotspot/make/linux/makefiles/gcc.make" and rebuild
>>>> the VM with these new settings.
>>>>
>>>> - in general, the "java" launcher will "execv()" itself to ensure it
>>>> has the right LD_LIBRARY_PATH settings but this "execv()" can confuse
>>>> gdb. To avoid it, you can either use the "gamma" launcher as explained
>>>> in my blog ("gamma" does not execv, because the user is responsible to
>>>> set the right LD_LIBRARY_PATH before calling "gamma"). The other
>>>> possibility is to set the LD_LIBRARY_PATH manually before running
>>>> "java" such that it begins with the prefix expected by the the
>>>> launcher. In  this case the launcher does not need to do an "execv()".
>>>> To achieve this, you can set a breakpoint in
>>>> "CreateExecutionEnvironment()" in "src/solaris/bin/java_md.c" (solaris
>>>> is no typo here!!!) and check the path the launcher expects to see for
>>>> LD_LIBRARY_PATH (look for the value of "newpath").
>>>>
>>>> - even if you followed the two points above, you can not easily set a
>>>> breakpoint in the interpreter, because the interpreter is generated at
>>>> startup. This means that there are no C-sources for the interpretation
>>>> of a bytecode (instead there's C-code which generates code which will
>>>> execute a bytecode). You can display the generated interpreter and the
>>>> various stubs with the options "-XX:+PrintInterpreter" and
>>>> "-XX:+PrintStubCode". You should use this together with
>>>> "-XX:+PrintAssembly" to get a disassembly of the generated templates
>>>> and stubs. (Notice that you need to compile and use the additional
>>>> library "disassembler.so" for this to work. More information on the
>>>> disassembler library can be found under:
>>>> http://wikis.sun.com/display/HotSpotInternals/PrintAssembly).
>>>>
>>>> - I suggest you run the VM once with "-XX:+PrintAssembly
>>>> -XX:+PrintInterpreter -XX:+PrintStubCode" and save the output to a
>>>> file. You should do this in the debugger, such that the addresses of
>>>> the generated code are the same like in the actual debug run. During a
>>>> debugging session, you can then always cross check in which generated
>>>> part of the interpreter you are. For a HotSpot debug build, you can
>>>> also call the global "help()" function right from the debuger prompt.
>>>> This will list some global helper functions from within libjvm.so
>>>> which can be used during debugging (among them "find(<address>" which
>>>> can be used to print out some information about an address which
>>>> belongs to the VM (e.g. a compiled method, an interpreter template, a
>>>> stub and s.o.)).
>>>>
>>>> - the "-XX:StopInterpreterAt=<bytecodenumber>" is implemented in such
>>>> a way, that every generated Java bytecode template first of all
>>>> increments a global bytecode counter and then checks its value against
>>>> the argument of "StopInterpreterAt". If the two numbers are equal, the
>>>> global function "breakpoint()" will be called. "breakpoint()" is an
>>>> empty, global C-function defined in "src/os/linux/vm/os_linux.cpp". If
>>>> you want to stop at the execution of a certain Java bytecode, you
>>>> should first of all run your program with "-XX:+TraceBytecodes" to
>>>> determine the exact position of the bytecode you're interested in
>>>> (hopefully this won't take to long, because indeed the VM already
>>>> executes about half a million bytecodes before even arriving to your
>>>> program's "main()" method - this is all class loading and
>>>> initialization stuff). Then start the VM again with the appropriate
>>>> "StopInterpreterAt" option AND set a breakpoint for the global
>>>> "breakpoint()" function. The VM will now stop just before the
>>>> execution of the bytecode you're interested in, but it will stop in
>>>> the "breakpoint()" function. Issuing a "finish" command in gdb, will
>>>> return you to the code template you're interested in (you should be
>>>> able to verify this by looking up the current address within the file
>>>> which contains the generated interpreter that we've created in the
>>>> previous step). Notice that at this point, all you can do in gdb is
>>>> stepping at assembler level ("stepi", "nexti") because you're in
>>>> generated code now and there is no associated symbolic information for
>>>> this code ("next" and "step" won't work).
>>>>
>>>>
>>>> - certain, complex functionality of some bytecodes isn't handled
>>>> directly in the generated code. Instead, some helper methods
>>>> implemented in C++ in the VM are called. This is the case for example
>>>> for InterpreterRuntime::monitorenter. You can check the bytecode
>>>> generators, to see where there are calls into the runtime.
>>>>
>>>> Hope this helps.
>>>> Regards,
>>>> Volker
>>>>
>>>> On Mon, Jan 5, 2009 at 6:32 AM,  <xinweix at cse.unsw.edu.au> wrote:
>>>>> Hi Volker,
>>>>>
>>>>> Happy New Year.
>>>>> Sorry to bother you. Thank you for your attention.
>>>>>
>>>>> I found your email about Hotspot build instruction from the 
>>>>> hotspot-dev
>>>>> maillist and your blog. I do appreciate your great help. However, I 
>>>>> still
>>>>> can't quite understand the mechanism of the interpreter in hotspot. 
>>>>> May I
>>>>> ask you some questions?
>>>>>
>>>>> 1) I used ddd, a graphic based client of gdb, to set up some 
>>>>> breakpoints and
>>>>> stepped into the hotspot jvm. I can find how exactly the bytecode is
>>>>> executed, just like the following maillist:
>>>>> http://markmail.org/message/lu6izmxpqzzej4lr?q=interpreter+openjdk&page=14#query:interpreter%20openjdk+page:14+mid:wvzcrnvxlqlj5oxa+state:results 
>>>>> .Do
>>>>> you have some idea about that?
>>>>>
>>>>> BTW, I successfully step into to breakpoint of 
>>>>> StubRountes::call_stub while
>>>>> using another debuger: "insight". I use '-XX:+TraceBytecode -Xint' 
>>>>> to see
>>>>> what is going in the Interpreter. However, it even generates a great
>>>>> amount of bytecodes when it is initializing and load the system 
>>>>> class. I
>>>>> don't know when the interpreter runtime is initialized.
>>>>>
>>>>>
>>>>> 2) I tried to use some options, as '-Xint', '-XX:StopInterpreterAt=1',
>>>>> aiming at stopping at a specific bytecode when I can inspect the 
>>>>> runtime
>>>>> datastructure. Unfortunately I failed. I don't understand why
>>>>> '-XX:StopInterpreterAt=1' doesn't work. The question is how to 
>>>>> configure it
>>>>> correctly that I can stop where exactly I want.
>>>>>
>>>>> 3) My object is to get some information, especially about the lock and
>>>>> thread information when threads concurrently access a shared 
>>>>> variant or try
>>>>> to lock before access using monitorenter. Can you give me some 
>>>>> advise how
>>>>> and where I can start? Is it related to the
>>>>> InterpreterRuntime::monitorenter?
>>>>>
>>>>> I am looking forward to hearing from you.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Alex Xie,
>>>>> University of New South Wales, Australia.
>>>>
>>



More information about the hotspot-dev mailing list