< prev index next >

src/cpu/aarch64/vm/macroAssembler_aarch64.cpp

Print this page
rev 9227 : 8143067: aarch64: guarantee failure in javac
Summary: Fix adrp going out of range during code relocation
Reviewed-by: duke

*** 95,112 **** // 1 - adrp Rx, target_page // ldr/str Ry, [Rx, #offset_in_page] // 2 - adrp Rx, target_page // add Ry, Rx, #offset_in_page // 3 - adrp Rx, target_page (page aligned reloc, offset == 0) ! // In the first 2 cases we must check that Rx is the same in the adrp and the ! // subsequent ldr/str or add instruction. Otherwise we could accidentally end ! // up treating a type 3 relocation as a type 1 or 2 just because it happened ! // to be followed by a random unrelated ldr/str or add instruction. ! // ! // In the case of a type 3 relocation, we know that these are only generated ! // for the safepoint polling page, or for the card type byte map base so we ! // assert as much and of course that the offset is 0. // unsigned insn2 = ((unsigned*)branch)[1]; if (Instruction_aarch64::extract(insn2, 29, 24) == 0b111001 && Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 9, 5)) { --- 95,107 ---- // 1 - adrp Rx, target_page // ldr/str Ry, [Rx, #offset_in_page] // 2 - adrp Rx, target_page // add Ry, Rx, #offset_in_page // 3 - adrp Rx, target_page (page aligned reloc, offset == 0) ! // nop/movk Rx, #imm12<<32 ! // In all cases we check that Rx is the same in the adrp and the subsequent ! // ldr/str, add or movk. // unsigned insn2 = ((unsigned*)branch)[1]; if (Instruction_aarch64::extract(insn2, 29, 24) == 0b111001 && Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 9, 5)) {
*** 121,137 **** Instruction_aarch64::extract(insn2, 4, 0)) { // add (immediate) Instruction_aarch64::patch(branch + sizeof (unsigned), 21, 10, offset_lo); instructions = 2; } else { ! assert((jbyte *)target == ! ((CardTableModRefBS*)(Universe::heap()->barrier_set()))->byte_map_base || ! target == StubRoutines::crc_table_addr() || ! (address)target == os::get_polling_page(), ! "adrp must be polling page or byte map base"); ! assert(offset_lo == 0, "offset must be 0 for polling page or byte map base"); } } int offset_lo = offset & 3; offset >>= 2; Instruction_aarch64::spatch(branch, 23, 5, offset); --- 116,137 ---- Instruction_aarch64::extract(insn2, 4, 0)) { // add (immediate) Instruction_aarch64::patch(branch + sizeof (unsigned), 21, 10, offset_lo); instructions = 2; + } else if (insn2 == aarch64_NOP || // NOP or MOVK Rx, #imm12 << 32 + (Instruction_aarch64::extract(insn2, 31, 21) == 0b11110010110) && + Instruction_aarch64::extract(insn, 4, 0) == + Instruction_aarch64::extract(insn2, 4, 0)) { + if (offset >= -(1<<20) && offset < (1<<20)) { + *(unsigned *)(branch + 4) = aarch64_NOP; + } else { + Instruction_aarch64::patch_movk(branch, 4, 20, 5, (uint64_t)target, 32); + offset &= (1<<20)-1; + } } else { ! ShouldNotReachHere(); } } int offset_lo = offset & 3; offset >>= 2; Instruction_aarch64::spatch(branch, 23, 5, offset);
*** 213,229 **** // 1 - adrp Rx, target_page // ldr/str Ry, [Rx, #offset_in_page] // 2 - adrp Rx, target_page ] // add Ry, Rx, #offset_in_page // 3 - adrp Rx, target_page (page aligned reloc, offset == 0) // // In the first two cases we check that the register is the same and // return the target_page + the offset within the page. ! // Otherwise we assume it is a page aligned relocation and return ! // the target page only. The only cases this is generated is for ! // the safepoint polling page or for the card table byte map base so ! // we assert as much. // unsigned insn2 = ((unsigned*)insn_addr)[1]; if (Instruction_aarch64::extract(insn2, 29, 24) == 0b111001 && Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 9, 5)) { --- 213,228 ---- // 1 - adrp Rx, target_page // ldr/str Ry, [Rx, #offset_in_page] // 2 - adrp Rx, target_page ] // add Ry, Rx, #offset_in_page // 3 - adrp Rx, target_page (page aligned reloc, offset == 0) + // nop/movk Rx, #imm12<<32 // // In the first two cases we check that the register is the same and // return the target_page + the offset within the page. ! // ! // In the third case we return just the target_page // unsigned insn2 = ((unsigned*)insn_addr)[1]; if (Instruction_aarch64::extract(insn2, 29, 24) == 0b111001 && Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 9, 5)) {
*** 235,250 **** Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 4, 0)) { // add (immediate) unsigned int byte_offset = Instruction_aarch64::extract(insn2, 21, 10); return address(target_page + byte_offset); ! } else { ! assert((jbyte *)target_page == ! ((CardTableModRefBS*)(Universe::heap()->barrier_set()))->byte_map_base || ! (address)target_page == os::get_polling_page(), ! "adrp must be polling page or byte map base"); return (address)target_page; } } else { ShouldNotReachHere(); } } else if (Instruction_aarch64::extract(insn, 31, 23) == 0b110100101) { --- 234,254 ---- Instruction_aarch64::extract(insn, 4, 0) == Instruction_aarch64::extract(insn2, 4, 0)) { // add (immediate) unsigned int byte_offset = Instruction_aarch64::extract(insn2, 21, 10); return address(target_page + byte_offset); ! } else if (insn2 == aarch64_NOP || // NOP or MOVK Rx, #imm12 << 32 ! (Instruction_aarch64::extract(insn2, 31, 21) == 0b11110010110) && ! Instruction_aarch64::extract(insn, 4, 0) == ! Instruction_aarch64::extract(insn2, 4, 0)) { ! if (insn2 != aarch64_NOP) { ! target_page = (target_page & 0xffffffff) | ! ((uint64_t)Instruction_aarch64::extract(insn2, 20, 5) << 32); ! } return (address)target_page; + } else { + ShouldNotReachHere(); } } else { ShouldNotReachHere(); } } else if (Instruction_aarch64::extract(insn, 31, 23) == 0b110100101) {
*** 3071,3081 **** str(rscratch1, adr); } void MacroAssembler::cmpptr(Register src1, Address src2) { unsigned long offset; ! adrp(rscratch1, src2, offset); ldr(rscratch1, Address(rscratch1, offset)); cmp(src1, rscratch1); } void MacroAssembler::store_check(Register obj, Address dst) { --- 3075,3085 ---- str(rscratch1, adr); } void MacroAssembler::cmpptr(Register src1, Address src2) { unsigned long offset; ! far_adrp(rscratch1, src2, offset); ldr(rscratch1, Address(rscratch1, offset)); cmp(src1, rscratch1); } void MacroAssembler::store_check(Register obj, Address dst) {
*** 3099,3109 **** assert(CardTableModRefBS::dirty_card_val() == 0, "must be"); { ExternalAddress cardtable((address) ct->byte_map_base); unsigned long offset; ! adrp(rscratch1, cardtable, offset); assert(offset == 0, "byte_map_base is misaligned"); } if (UseCondCardMark) { Label L_already_dirty; --- 3103,3113 ---- assert(CardTableModRefBS::dirty_card_val() == 0, "must be"); { ExternalAddress cardtable((address) ct->byte_map_base); unsigned long offset; ! far_adrp(rscratch1, cardtable, offset); assert(offset == 0, "byte_map_base is misaligned"); } if (UseCondCardMark) { Label L_already_dirty;
*** 3594,3604 **** const Register card_addr = tmp; lsr(card_addr, store_addr, CardTableModRefBS::card_shift); unsigned long offset; ! adrp(tmp2, cardtable, offset); // get the address of the card add(card_addr, card_addr, tmp2); ldrb(tmp2, Address(card_addr, offset)); cmpw(tmp2, (int)G1SATBCardTableModRefBS::g1_young_card_val()); --- 3598,3608 ---- const Register card_addr = tmp; lsr(card_addr, store_addr, CardTableModRefBS::card_shift); unsigned long offset; ! far_adrp(tmp2, cardtable, offset); // get the address of the card add(card_addr, card_addr, tmp2); ldrb(tmp2, Address(card_addr, offset)); cmpw(tmp2, (int)G1SATBCardTableModRefBS::g1_young_card_val());
*** 3781,3791 **** strw(t1, Address(top, arrayOopDesc::length_offset_in_bytes())); // set klass to intArrayKlass { unsigned long offset; // dubious reloc why not an oop reloc? ! adrp(rscratch1, ExternalAddress((address)Universe::intArrayKlassObj_addr()), offset); ldr(t1, Address(rscratch1, offset)); } // store klass last. concurrent gcs assumes klass length is valid if // klass field is not null. --- 3785,3795 ---- strw(t1, Address(top, arrayOopDesc::length_offset_in_bytes())); // set klass to intArrayKlass { unsigned long offset; // dubious reloc why not an oop reloc? ! far_adrp(rscratch1, ExternalAddress((address)Universe::intArrayKlassObj_addr()), offset); ldr(t1, Address(rscratch1, offset)); } // store klass last. concurrent gcs assumes klass length is valid if // klass field is not null.
*** 3846,3865 **** Register heap_end = rscratch2; Label retry; bind(retry); { unsigned long offset; ! adrp(rscratch1, ExternalAddress((address) Universe::heap()->end_addr()), offset); ldr(heap_end, Address(rscratch1, offset)); } ExternalAddress heap_top((address) Universe::heap()->top_addr()); // Get the current top of the heap { unsigned long offset; ! adrp(rscratch1, heap_top, offset); // Use add() here after ARDP, rather than lea(). // lea() does not generate anything if its offset is zero. // However, relocs expect to find either an ADD or a load/store // insn after an ADRP. add() always generates an ADD insn, even // for add(Rn, Rn, 0). --- 3850,3869 ---- Register heap_end = rscratch2; Label retry; bind(retry); { unsigned long offset; ! far_adrp(rscratch1, ExternalAddress((address) Universe::heap()->end_addr()), offset); ldr(heap_end, Address(rscratch1, offset)); } ExternalAddress heap_top((address) Universe::heap()->top_addr()); // Get the current top of the heap { unsigned long offset; ! far_adrp(rscratch1, heap_top, offset); // Use add() here after ARDP, rather than lea(). // lea() does not generate anything if its offset is zero. // However, relocs expect to find either an ADD or a load/store // insn after an ADRP. add() always generates an ADD insn, even // for add(Rn, Rn, 0).
*** 3946,3956 **** } address MacroAssembler::read_polling_page(Register r, address page, relocInfo::relocType rtype) { unsigned long off; ! adrp(r, Address(page, rtype), off); InstructionMark im(this); code_section()->relocate(inst_mark(), rtype); ldrw(zr, Address(r, off)); return inst_mark(); } --- 3950,3960 ---- } address MacroAssembler::read_polling_page(Register r, address page, relocInfo::relocType rtype) { unsigned long off; ! far_adrp(r, Address(page, rtype), off); InstructionMark im(this); code_section()->relocate(inst_mark(), rtype); ldrw(zr, Address(r, off)); return inst_mark(); }
*** 3960,3987 **** code_section()->relocate(inst_mark(), rtype); ldrw(zr, Address(r, 0)); return inst_mark(); } ! void MacroAssembler::adrp(Register reg1, const Address &dest, unsigned long &byte_offset) { ! relocInfo::relocType rtype = dest.rspec().reloc()->type(); ! if (uabs(pc() - dest.target()) >= (1LL << 32)) { ! guarantee(rtype == relocInfo::none ! || rtype == relocInfo::external_word_type ! || rtype == relocInfo::poll_type ! || rtype == relocInfo::poll_return_type, ! "can only use a fixed address with an ADRP"); ! // Out of range. This doesn't happen very often, but we have to ! // handle it ! mov(reg1, dest); ! byte_offset = 0; } else { InstructionMark im(this); code_section()->relocate(inst_mark(), dest.rspec()); byte_offset = (uint64_t)dest.target() & 0xfff; _adrp(reg1, dest.target()); - } } void MacroAssembler::build_frame(int framesize) { assert(framesize > 0, "framesize must be > 0"); if (framesize < ((1 << 9) + 2 * wordSize)) { --- 3964,4000 ---- code_section()->relocate(inst_mark(), rtype); ldrw(zr, Address(r, 0)); return inst_mark(); } ! void MacroAssembler::far_adrp(Register reg1, const Address &dest, unsigned long &byte_offset) { ! uint64_t pc_page = (uint64_t)pc() >> 12; ! uint64_t adr_page = (uint64_t)dest.target() >> 12; ! int64_t offset = adr_page - pc_page; ! ! InstructionMark im(this); ! code_section()->relocate(inst_mark(), dest.rspec()); ! if (offset >= -(1<<20) && offset < (1<<20)) { ! _adrp(reg1, dest.target()); ! nop(); } else { + offset = (offset & ((1<<20)-1)) << 12; + _adrp(reg1, pc()+offset); + movk(reg1, ((uint64_t)dest.target() >> 32) & 0xffff, 32); + } + byte_offset = (uint64_t)dest.target() & 0xfff; + } + + void MacroAssembler::adrp(Register reg1, const Address &dest, unsigned long &byte_offset) { + uint64_t pc_page = (uint64_t)pc() >> 12; + uint64_t adr_page = (uint64_t)dest.target() >> 12; + int64_t offset = adr_page - pc_page; + guarantee(offset >= -(1<<20) && offset < (1<<20), "adrp out of range, use far_adrp"); InstructionMark im(this); code_section()->relocate(inst_mark(), dest.rspec()); byte_offset = (uint64_t)dest.target() & 0xfff; _adrp(reg1, dest.target()); } void MacroAssembler::build_frame(int framesize) { assert(framesize > 0, "framesize must be > 0"); if (framesize < ((1 << 9) + 2 * wordSize)) {
< prev index next >