RFR: tune native call site check
Anton Kozlov
akozlov at azul.com
Mon Sep 12 15:49:37 UTC 2016
Oh, I see. Agree, is_call_before is incorrect same way as nativeCall_before
prior 1st patch; and if no single instruction will be found on offset (-4), it
will try to find 3-instruction sequence there, possibly going beyound CodeCache
boundary.
Thanks! I suggest second version of patch. Yang, could you check it still works
for you?
Anton
***** patch start *****
diff --git a/src/cpu/aarch32/vm/nativeInst_aarch32.cpp b/src/cpu/aarch32/vm/nativeInst_aarch32.cpp
--- a/src/cpu/aarch32/vm/nativeInst_aarch32.cpp
+++ b/src/cpu/aarch32/vm/nativeInst_aarch32.cpp
@@ -104,8 +104,16 @@
}
bool NativeCall::is_call_before(address return_address) {
- return is_at(return_address - NativeImmCall::instruction_size) ||
- is_at(return_address - NativeCall::instruction_size);
+ if (NativeTrampolineCall::is_at(return_address - NativeCall::instruction_size)) {
+ return true;
+ } else if (NativeMovConstReg::is_at(return_address - NativeCall::instruction_size)) {
+ NativeMovConstReg *nm = NativeMovConstReg::from(return_address - NativeCall::instruction_size);
+ address next_instr = nm->next_instruction_address();
+ return NativeRegCall::is_at(next_instr) && NativeRegCall::from(next_instr)->destination() == nm->destination();
+ } else if (NativeImmCall::is_at(return_address - NativeBranchType::instruction_size)) {
+ return true;
+ }
+ return false;
}
address NativeCall::next_instruction_address() const {
diff --git a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
--- a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
+++ b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
@@ -303,20 +303,6 @@
return NativeCall::from(address);
}
-inline NativeCall* nativeCall_before(address return_address) {
- address call_addr = NULL;
- if (NativeCall::is_at(return_address - NativeBranchType::instruction_size)) {
- call_addr = return_address - NativeBranchType::instruction_size;
- } else if (NativeCall::is_at(return_address - NativeCall::instruction_size)) {
- call_addr = return_address - NativeCall::instruction_size;
- } else {
- ShouldNotReachHere();
- }
-
- return NativeCall::from(call_addr);
-}
-
-
// An interface for accessing/manipulating native moves of the form:
// mov[b/w/l/q] [reg + offset], reg (instruction_code_reg2mem)
// mov[b/w/l/q] reg, [reg+offset] (instruction_code_mem2reg
@@ -505,4 +491,27 @@
inline bool NativeInstruction::is_imm_jump() const { return NativeImmJump::is_at(addr()); }
inline bool NativeInstruction::is_reg_jump() const { return NativeRegJump::is_at(addr()); }
+inline NativeCall* nativeCall_before(address return_address) {
+ address call_addr = NULL;
+ if (NativeTrampolineCall::is_at(return_address - NativeCall::instruction_size)) {
+ call_addr = return_address - NativeCall::instruction_size;
+ } else if (NativeMovConstReg::is_at(return_address - NativeCall::instruction_size)) {
+ NativeMovConstReg *nm = NativeMovConstReg::from(return_address - NativeCall::instruction_size);
+ address next_instr = nm->next_instruction_address();
+ if (NativeRegCall::is_at(next_instr) &&
+ NativeRegCall::from(next_instr)->destination() == nm->destination()) {
+ call_addr = return_address - NativeCall::instruction_size;
+ }
+ }
+ if (!call_addr) {
+ if (NativeImmCall::is_at(return_address - NativeBranchType::instruction_size)) {
+ call_addr = return_address - NativeBranchType::instruction_size;
+ } else {
+ ShouldNotReachHere();
+ }
+ }
+
+ return NativeCall::from(call_addr);
+}
+
#endif // CPU_AARCH32_VM_NATIVEINST_AARCH32_HPP
***** patch end ******
On Mon, 2016-09-12 at 13:37 +0000, yangyongyong wrote:
> Yes, please. Yang is my surname and of course you can call me that.
>
> I think NativeCall* nativeCall_before() is ok now.
> However it seems that NativeCall::is_call_before() would incur a similar crash
> as you mentioned in an earlier email.
>
> Regards.
>
> -----Original Message-----
> From: Anton Kozlov [mailto:akozlov at azul.com]
> Sent: Monday, September 12, 2016 8:34 PM
> To: yangyongyong; aarch32-port-dev at openjdk.java.net
> Subject: Re: RFR: tune native call site check
>
> Hi, Yang (sorry, is it correct?),
>
> I can't remember well, it reproduced on some jtreg test. But it also should be
> reproduced in release mode by specifying small values for InitialCodeCacheSize
> and CodeCacheExpansionSize JVM options, like 4K.
>
> We've prepared another patch after your email with suggestions implemented
> (Andrey Petushkov), in attach and below.
>
> I think that nativeCall_before should be enough. The problem is that
> nativeCall_before is not sure where instruction sequence is started, but it
> calls NativeCall::is_at() anyway. NativeCall::is_at is supposed to be called
> on start of instruction sequence; with this precondition, I see no
> possibilities for is_at to misdecode target address. Please, correct me if I'm
> wrong.
>
> Thanks,
> Anton
>
> ***** patch begin ******
> diff --git a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
> b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
> --- a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
> +++ b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp
> @@ -303,20 +303,6 @@
> return NativeCall::from(address);
> }
>
> -inline NativeCall* nativeCall_before(address return_address) {
> - address call_addr = NULL;
> - if (NativeCall::is_at(return_address - NativeBranchType::instruction_size))
> {
> - call_addr = return_address - NativeBranchType::instruction_size;
> - } else if (NativeCall::is_at(return_address -
> NativeCall::instruction_size)) {
> - call_addr = return_address - NativeCall::instruction_size;
> - } else {
> - ShouldNotReachHere();
> - }
> -
> - return NativeCall::from(call_addr);
> -}
> -
> -
> // An interface for accessing/manipulating native moves of the form:
> // mov[b/w/l/q] [reg + offset], reg (instruction_code_reg2mem)
> // mov[b/w/l/q] reg, [reg+offset] (instruction_code_mem2reg @@
> -505,4 +491,27 @@
> inline bool NativeInstruction::is_imm_jump() const { return
> NativeImmJump::is_at(addr()); }
> inline bool NativeInstruction::is_reg_jump() const { return
> NativeRegJump::is_at(addr()); }
>
> +inline NativeCall* nativeCall_before(address return_address) {
> + address call_addr = NULL;
> + if (NativeTrampolineCall::is_at(return_address -
> +NativeCall::instruction_size)) {
> + call_addr = return_address - NativeCall::instruction_size;
> + } else if (NativeMovConstReg::is_at(return_address -
> +NativeCall::instruction_size)) {
> + NativeMovConstReg *nm = NativeMovConstReg::from(return_address -
> +NativeCall::instruction_size);
> + address next_instr = nm->next_instruction_address();
> + if (NativeRegCall::is_at(next_instr) &&
> + NativeRegCall::from(next_instr)->destination() ==
> +nm->destination()) {
> + call_addr = return_address - NativeCall::instruction_size;
> + }
> + }
> + if (!call_addr) {
> + if (NativeImmCall::is_at(return_address -
> +NativeBranchType::instruction_size)) {
> + call_addr = return_address - NativeBranchType::instruction_size;
> + } else {
> + ShouldNotReachHere();
> + }
> + }
> +
> + return NativeCall::from(call_addr);
> +}
> +
> #endif // CPU_AARCH32_VM_NATIVEINST_AARCH32_HPP
>
> ***** patch end ******
>
> On Sat, 2016-09-10 at 07:14 +0000, yangyongyong wrote:
> >
> > Thank you, Anton,
> >
> > My patch *improves* the check logic a little but it does not handle
> > the situation you mentioned.
> > How is it reproduced? Do you have a patch at hand already?
> >
> > Your suggestion seems more rational. The check logic should better not
> > mix up the situations of offset -4 and -12.
> >
> > Meanwhile, please note that NativeCall::is_at() is invoked somewhere
> > else, so perhaps some minor modification of nativeCall_before() is not
> > enough.
> >
> > -----Original Message-----
> > From: Anton Kozlov [mailto:akozlov at azul.com]
> > Sent: Friday, September 09, 2016 8:35 PM
> > To: yangyongyong; aarch32-port-dev at openjdk.java.net
> > Subject: Re: RFR: tune native call site check
> >
> > Hi!
> >
> > Thanks for finding this! You're right, this is a bug.
> >
> > However, if NativeCall::is_at will be fixed like suggested, then the
> > long instruction sequence will be checked before short one. And now
> > consider situation, when this call is the last instruction of last
> > method in CodeCache, unluckily placed at end of page. "Long" check
> > will try to read next page of CodeCache (forbidden for r/w/x) and will
> > trigger segfault, which is not expected and not handled by JVM.
> > Actually, we've seen that =)
> >
> > There is a suggestion to fix only nativeCall_before, by explicitly
> > checking NativeImmCall, NativeTrampolineCall, NativeRegCall there with
> > appropriate offsets. Actually, it looks more correct instead of trying
> > to find any of these
> > 3 Native* at offset 4 and then at offset 12.
> >
> > Thanks,
> > Anton
> >
> > On Fri, 2016-09-09 at 10:57 +0000, yangyongyong wrote:
> > >
> > >
> > > Roughly there are 3 kinds of native call site checked by
> > > nativeCall_before():
> > >
> > > 1. Native-Trampoline-Call takes the form of:
> > >
> > > add lr, pc, #4
> > > ldr pc, [pc, -4]
> > > 0x???????? # call_destination
> > > #return_address:
> > > Some_insn
> > >
> > >
> > > 2. Native-Imm-Call
> > >
> > > bl imm # call_destination
> > > #return_address:
> > > Some_insn
> > >
> > >
> > > 3. Native-Reg-Call
> > >
> > >
> > > movw regx, #call_destination
> > >
> > > movt regx, #call_destination
> > > bl regx # call destination
> > > #return_address:
> > > Some_insn
> > >
> > > Current check logic incurs a problem if the encoding of the call
> > > destination of type 1 can by any chance be disassembled as a “bl imm”
> > > instruction.
> > > And thus the call address is calculated improperly and then the
> > > relocation info will not be found, which causes assert failure in
> > > CompiledIC::CompiledIC(nmethod* nm, NativeCall* call):
> > > assert(ret == true, "relocInfo must exist at this address");
> > >
> > > This failure can be reproduced simply by “java -Xcomp
> > > -XX:ReservedCodeCacheSize=xx”. Please tune xx and make sure some of
> > > the JITed code is placed at address 0x?B??????.
> > > The attached patch improves the check logic:
> > > ----------------- patch begins ---------------- diff -r 80b7b526cffb
> > > src/cpu/aarch32/vm/nativeInst_aarch32.cpp
> > > --- a/src/cpu/aarch32/vm/nativeInst_aarch32.cpp Sun Sep 04
> > > 20:52:43
> > > 2016 +0100
> > > +++ b/src/cpu/aarch32/vm/nativeInst_aarch32.cpp Fri Sep 09
> > > +++ 17:38:34 2016
> > > +0800
> > > @@ -132,14 +132,14 @@
> > > }
> > > bool NativeCall::is_at(address addr) {
> > > - if (NativeImmCall::is_at(addr)) {
> > > + if (NativeTrampolineCall::is_at(addr)) {
> > > return true;
> > > } else if (NativeMovConstReg::is_at(addr)) {
> > > NativeMovConstReg *nm = NativeMovConstReg::from(addr);
> > > address next_instr = nm->next_instruction_address();
> > > return NativeRegCall::is_at(next_instr) &&
> > > NativeRegCall::from(next_instr)->destination() ==
> > > nm->destination();
> > > - } else if (NativeTrampolineCall::is_at(addr)) {
> > > + } else if (NativeImmCall::is_at(addr)) {
> > > return true;
> > > }
> > > return false;
> > > diff -r 80b7b526cffb src/cpu/aarch32/vm/nativeInst_aarch32.hpp
> > > --- a/src/cpu/aarch32/vm/nativeInst_aarch32.hpp Sun Sep 04
> > > 20:52:43
> > > 2016 +0100
> > > +++ b/src/cpu/aarch32/vm/nativeInst_aarch32.hpp Fri Sep 09
> > > +++ 17:38:34 2016
> > > +0800
> > > @@ -306,10 +306,10 @@
> > > inline NativeCall* nativeCall_before(address return_address) {
> > > address call_addr = NULL;
> > > - if (NativeCall::is_at(return_address -
> > > NativeBranchType::instruction_size))
> > > {
> > > + if (NativeCall::is_at(return_address -
> > > +NativeCall::instruction_size)) {
> > > + call_addr = return_address - NativeCall::instruction_size;
> > > + } else if (NativeCall::is_at(return_address -
> > > NativeBranchType::instruction_size)) {
> > > call_addr = return_address -
> > > NativeBranchType::instruction_size;
> > > - } else if (NativeCall::is_at(return_address -
> > > NativeCall::instruction_size)) {
> > > - call_addr = return_address - NativeCall::instruction_size;
> > > } else {
> > > ShouldNotReachHere();
> > > }
> > > ----------------- patch ends ----------------
> > >
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nativeInstr_before2.patch
Type: text/x-patch
Size: 3264 bytes
Desc: nativeInstr_before2.patch
URL: <http://mail.openjdk.java.net/pipermail/aarch32-port-dev/attachments/20160912/2cc0d789/nativeInstr_before2-0001.patch>
More information about the aarch32-port-dev
mailing list