bytecode rewrite and breakpoint
Coleen Phillimore
coleen.phillimore at oracle.com
Tue Jan 13 21:21:25 UTC 2015
Okay, yes, I see now. We dispatch on the aload_0 bytecode as if it were
in the stream. Very tricky.
Coleen
On 1/13/15, 6:56 AM, San Hong Li wrote:
> HI Coleen,
> yes, your understanding is exactly what I meant. But I would like to
> explain why that code is necessary.
> (actually I get the answer from the implementation of
> TemplateTable::_*breakpoint )*
> Suppose we have following bytecode stream, the _bp has been set at
> this moment:
>
> bcp ----> | _bp | ----- original (aload_0)
> | _fast_igetfield |
>
> The bcp (r13) currently points to _bp, so the interpreter will
> execute TemplateTable::_*breakpoint * at this time.
>
> In TemplateTable::_*breakpoint *:
>
>
> void TemplateTable::_breakpoint() {
> // Note: We get here even if we are single stepping..
> // jbug inists on setting breakpoints at every bytecode
> // even if we are in single step mode.
>
> transition(vtos, vtos);
>
> // get the unpatched byte code
> __ get_method(c_rarg1);
> __ call_VM(noreg,
> CAST_FROM_FN_PTR(address,
> InterpreterRuntime::get_original_bytecode_at),
> c_rarg1, r13);
> __ mov(rbx, rax);
>
> // post the breakpoint event
> __ get_method(c_rarg1);
> __ call_VM(noreg,
> CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint),
> c_rarg1, r13);
>
> // complete the execution of original bytecode
> __ dispatch_only_normal(vtos);
> }
>
> The key point here is: the next original bytecode (aload_0) was
> loaded into rbx by __ mov(rbx, rax) but without r13' advance, so
> that after the interpreter resumed from breakpoint (e.g: the user
> typed 'cont' command in jdb for continuous)
>
> The next bytecode aload_0 (loaded in rbx) will get executed, the
> bytecode stream is still:
>
> bcp ----> | _bp | ----- original (aload_0)
> | _fast_igetfield |
> although we are now executing aload_0 .
>
> In execution of aload_0, the patch_bytecode will be called for
> (aload_0+_fast_igetfield ) which will be patched as _fast_iaccess_0.
>
> Then back in TemplateTable::patch_bytecode:
> Tthe interpreter will see _bp is at _bcp(0), but NOT aload_0 ---- as
> the r13 is not advanced**
>
> Thanks!
> San Hong
>
> On Tue, Jan 13, 2015 at 2:23 AM, Coleen Phillimore
> <coleen.phillimore at oracle.com <mailto:coleen.phillimore at oracle.com>>
> wrote:
>
>
> Hi,
>
> This is an interesting question actually.
>
> On 1/12/15, 7:33 AM, San Hong Li wrote:
>> Hi Coleen:
>> Thanks for your attention and reply. I would like to clarify my
>> question again:
>> Given that we have the following bytecde stream:
>> |bp|
>> -------------------------------------------------
>> | x | x | aload_0 | x | x | x |
>> -------------------------------------------------
>> and we suppose that the breakpoint gets inserted at the
>> position of "aload_0 ", the steam would be updated as follows:
>>
>> -------------------------------------------------
>> | x | x | bp(202)| x | x | x |
>> -------------------------------------------------
>> (original: aload_0 )
>>
>> The key point here is : bp and aload_0 have the same bcp index -
>> I just deduced this from the implementation of
>> TemplateTable::_*breakpoint.*
>> *
>> *
>> *
>> *
>> Based on this layout, when the *TemplateTable::patch_bytecode
>> *was called for **aload_0
>> The interpreter will see that the bp will be at bcp(0) (*NOT
>> aload_0 *at this time)
>
> If we are executing the code TemplateTable::patch_bytecode, then
> the bytecode stream had an aload_0 in it *not* _bp, so I'm not
> sure why we'd all of a sudden find a _bp in the bytecode stream at
> this point. The JVMTI set_breakpoint code seems to only set
> breakpoints at safepoints, and while there's a safepoint at each
> bytecode, there is not one after we've started executing the
> bytecode in the template interpreter. It appears that a different
> thread cannot change the bytecode to _bp after the _aload_0 is
> read from the stream.
>
> So I don't see how we need this code. It's been there forever.
> Maybe the breakpoint code used to work differently in the past
> which made this code necessary. But a word of warning, this is
> just my reading of this today, I could be surprised by some other
> reason that this code is needed.
>
> Did I understand your question this time? It's a good one that I
> don't know the answer to.
>
> Thanks,
> Coleen
>
>
>>
>> This explained that why the HotSpot must have the below block in
>> *TemplateTable::patch_bytecode *
>> to handle the case when the at bcp(0) is bp.
>> *(Actually this was the intention of my original question)*
>>
>> if (JvmtiExport::can_post_breakpoint()) {
>> Label L_fast_patch;
>> // if a breakpoint is present we can't rewrite the stream
>> directly
>> __ movzbl(temp_reg, at_bcp(0));
>> __ cmpl(temp_reg, Bytecodes::_breakpoint);
>> __ jcc(Assembler::notEqual, L_fast_patch);
>> __ get_method(temp_reg);
>> // Let breakpoint table handling rewrite to quicker bytecode
>> __ call_VM(noreg, CAST_FROM_FN_PTR(address,
>> InterpreterRuntime::set_original_bytecode_at), temp_reg, r13,
>> bc_reg);
>> #ifndef ASSERT
>> __ jmpb(L_patch_done);
>> #else
>> __ jmp(L_patch_done);
>> #endif
>> __ bind(L_fast_patch);
>> }
>>
>> Hopefully I explain my question and answer clearly :-)
>>
>> On Fri, Jan 9, 2015 at 11:35 AM, San Hong Li <sherrylso at gmail.com
>> <mailto:sherrylso at gmail.com>> wrote:
>>
>> Hmmm, finally I got the answer for this question.
>> The at_bcp(0) would be the Bytecodes::_breakpoint if the
>> patch_code happened after the break point is set.
>> The following example shows this:
>>
>> 33: getstatic #8; //Field
>> java/lang/System.in:Ljava/io/InputStream;
>> 36: invokevirtual #9; //Method java/io/InputStream.read:()I
>> 39: pop
>> 40: aload_0 <---------------------- set break point here.
>> 41: getfield #2; //Field myInt:I
>> 44: istore 6
>> 46: iload 6
>>
>> If we set the breakpoint at 40 , when the patch_code in
>> aload happened later, the interpreter will see the
>> Bytecodes::_breakpoint at bcp(0).
>>
>> hmmm, actually i just missed the info present
>> in TemplateTable::_breakpoint - the breakpoint used the same
>> index with the original bytecode.
>>
>> Anyway, thanks every one.
>>
>> On Tue, Jan 6, 2015 at 10:18 PM, San Hong Li
>> <sherrylso at gmail.com <mailto:sherrylso at gmail.com>> wrote:
>>
>> Hi All:
>>
>> For the bytecode patch path, the interpreter does have
>> some special handling for breakpoint bytecode, that is,
>> if a breakpoint is present at_bcp(0), the bytecode
>> patching will be skipped and handled by breakpoint table
>> later.
>>
>> The related implementation is in
>> TemplateTable::patch_bytecode:
>>
>> if (JvmtiExport::can_post_breakpoint()) {
>> Label L_fast_patch;
>> // if a breakpoint is present we can't rewrite the
>> stream directly
>> __ movzbl(temp_reg, at_bcp(0));
>> __ cmpl(temp_reg, Bytecodes::_breakpoint);
>> __ jcc(Assembler::notEqual, L_fast_patch);
>> __ get_method(temp_reg);
>> // Let breakpoint table handling rewrite to quicker
>> bytecode
>> __ call_VM(noreg, CAST_FROM_FN_PTR(address,
>> InterpreterRuntime::set_original_bytecode_at), temp_reg,
>> r13, bc_reg);
>> #ifndef ASSERT
>> __ jmpb(L_patch_done);
>> #else
>> __ jmp(L_patch_done);
>> #endif
>> __ bind(L_fast_patch);
>> }
>>
>> My understanding is the breakpoint can only be set in
>> safepoint,
>> when the interpreter thread resumes from safepoint,
>> because it will retrieve the next bytecode for executing
>> again,the breakpoint bytecode which is set in safepoint
>> before will get chance to be executed. I can not imagine
>> when the bcp(0) could be changed as breakpoint in above code?
>> So I am curious whether the above code is already dead?
>> If not, anyone can help to me to clarify that how the
>> bytecode which is currently executed by interpreter could
>> be replaced with breakpoint? which case could trigger
>> the "InterpreterRuntime::set_original_bytecode_at" to be
>> called?
>>
>> Appreciated for your help in advance.
>>
>>
>>
>
>
More information about the hotspot-runtime-dev
mailing list