bytecode rewrite and breakpoint
Coleen Phillimore
coleen.phillimore at oracle.com
Mon Jan 12 18:23:49 UTC 2015
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