< prev index next >

src/cpu/aarch64/vm/macroAssembler_aarch64.cpp

Print this page
rev 10703 : [backport] More AArch64 assembler cleanups
rev 10719 : [backport] Fix up superfluous changes against upstream
rev 10764 : [backport] Rename BrooksPointer to ShenandoahBrooksPointer
rev 10777 : [backport] Remove ShenandoahWriteBarrierRB flag
   1 
   2 /*
   3 /*
   4  * Copyright (c) 2013, Red Hat Inc.
   5  * Copyright (c) 1997, 2012, Oracle and/or its affiliates.
   6  * All rights reserved.
   7  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   8  *
   9  * This code is free software; you can redistribute it and/or modify it
  10  * under the terms of the GNU General Public License version 2 only, as
  11  * published by the Free Software Foundation.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  *
  27  */
  28 
  29 #include <sys/types.h>
  30 
  31 #include "precompiled.hpp"
  32 #include "asm/assembler.hpp"
  33 #include "asm/assembler.inline.hpp"
  34 #include "interpreter/interpreter.hpp"
  35 
  36 #include "compiler/disassembler.hpp"
  37 #include "gc_interface/collectedHeap.inline.hpp"
  38 #include "gc_implementation/shenandoah/brooksPointer.hpp"
  39 #include "gc_implementation/shenandoah/shenandoahHeap.hpp"
  40 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  41 #include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp"
  42 #include "memory/resourceArea.hpp"
  43 #include "runtime/biasedLocking.hpp"
  44 #include "runtime/interfaceSupport.hpp"
  45 #include "runtime/sharedRuntime.hpp"
  46 
  47 // #include "gc_interface/collectedHeap.inline.hpp"
  48 // #include "interpreter/interpreter.hpp"
  49 // #include "memory/cardTableModRefBS.hpp"
  50 // #include "prims/methodHandles.hpp"
  51 // #include "runtime/biasedLocking.hpp"
  52 // #include "runtime/interfaceSupport.hpp"
  53 // #include "runtime/objectMonitor.hpp"
  54 // #include "runtime/os.hpp"
  55 // #include "runtime/sharedRuntime.hpp"
  56 // #include "runtime/stubRoutines.hpp"
  57 
  58 #if INCLUDE_ALL_GCS


1417 
1418 void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) {
1419   assert(arg_0 != c_rarg3, "smashed arg");
1420   assert(arg_1 != c_rarg3, "smashed arg");
1421   assert(arg_2 != c_rarg3, "smashed arg");
1422   pass_arg3(this, arg_3);
1423   assert(arg_0 != c_rarg2, "smashed arg");
1424   assert(arg_1 != c_rarg2, "smashed arg");
1425   pass_arg2(this, arg_2);
1426   assert(arg_0 != c_rarg1, "smashed arg");
1427   pass_arg1(this, arg_1);
1428   pass_arg0(this, arg_0);
1429   MacroAssembler::call_VM_leaf_base(entry_point, 4);
1430 }
1431 
1432 void MacroAssembler::null_check(Register reg, int offset) {
1433   if (needs_explicit_null_check(offset)) {
1434     // provoke OS NULL exception if reg = NULL by
1435     // accessing M[reg] w/o changing any registers
1436     // NOTE: this is plenty to provoke a segv
1437 
1438     ldr(zr, Address(reg));
1439   } else {
1440     // nothing to do, (later) access of M[reg + offset]
1441     // will provoke OS NULL exception if reg = NULL
1442   }
1443 }
1444 
1445 // MacroAssembler protected routines needed to implement
1446 // public methods
1447 
1448 void MacroAssembler::mov(Register r, Address dest) {
1449   code_section()->relocate(pc(), dest.rspec());
1450   u_int64_t imm64 = (u_int64_t)dest.target();
1451   movptr(r, imm64);
1452 }
1453 
1454 // Move a constant pointer into r.  In AArch64 mode the virtual
1455 // address space is 48 bits in size, so we only need three
1456 // instructions to create a patchable instruction sequence that can
1457 // reach anywhere.


2003   return count;
2004 }
2005 #ifdef ASSERT
2006 void MacroAssembler::verify_heapbase(const char* msg) {
2007 #if 0
2008   assert (UseCompressedOops || UseCompressedClassPointers, "should be compressed");
2009   assert (Universe::heap() != NULL, "java heap should be initialized");
2010   if (CheckCompressedOops) {
2011     Label ok;
2012     push(1 << rscratch1->encoding(), sp); // cmpptr trashes rscratch1
2013     cmpptr(rheapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()));
2014     br(Assembler::EQ, ok);
2015     stop(msg);
2016     bind(ok);
2017     pop(1 << rscratch1->encoding(), sp);
2018   }
2019 #endif
2020 }
2021 #endif
2022 
2023 void MacroAssembler::stop(const char* msg, Label *l) {
2024   address ip = pc();
2025   pusha();
2026   // We use movptr rather than mov here because we need code size not
2027   // to depend on the pointer value of msg otherwise C2 can observe
2028   // the same node with different sizes when emitted in a scratch
2029   // buffer and later when emitted for good.
2030   movptr(c_rarg0, (uintptr_t)msg);
2031   if (! l) {
2032     adr(c_rarg1, (address)ip);
2033   } else {
2034     adr(c_rarg1, *l);
2035   }
2036   mov(c_rarg2, sp);
2037   mov(c_rarg3, CAST_FROM_FN_PTR(address, MacroAssembler::debug64));
2038   // call(c_rarg3);
2039   blrt(c_rarg3, 3, 0, 1);
2040   hlt(0);
2041 }
2042 
2043 // If a constant does not fit in an immediate field, generate some
2044 // number of MOV instructions and then perform the operation.
2045 void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
2046                                            add_sub_imm_insn insn1,
2047                                            add_sub_reg_insn insn2) {
2048   assert(Rd != zr, "Rd = zr and not setting flags?");
2049   if (operand_valid_for_add_sub_immediate((int)imm)) {
2050     (this->*insn1)(Rd, Rn, imm);
2051   } else {
2052     if (uabs(imm) < (1 << 24)) {
2053        (this->*insn1)(Rd, Rn, imm & -(1 << 12));
2054        (this->*insn1)(Rd, Rd, imm & ((1 << 12)-1));
2055     } else {


2377   str(t1, Address(thread, in_bytes(JavaThread::allocated_bytes_offset())));
2378 }
2379 
2380 #ifndef PRODUCT
2381 extern "C" void findpc(intptr_t x);
2382 #endif
2383 
2384 void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
2385 {
2386   // In order to get locks to work, we need to fake a in_VM state
2387   if (ShowMessageBoxOnError ) {
2388     JavaThread* thread = JavaThread::current();
2389     JavaThreadState saved_state = thread->thread_state();
2390     thread->set_thread_state(_thread_in_vm);
2391 #ifndef PRODUCT
2392     if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
2393       ttyLocker ttyl;
2394       BytecodeCounter::print();
2395     }
2396 #endif
2397 
2398     if (os::message_box(msg, "Execution stopped, print registers?")) {
2399       ttyLocker ttyl;
2400       tty->print_cr(" pc = 0x%016lx", pc);
2401 #ifndef PRODUCT
2402       tty->cr();
2403       findpc(pc);
2404       tty->cr();
2405 #endif
2406       tty->print_cr(" r0 = 0x%016lx", regs[0]);
2407       tty->print_cr(" r1 = 0x%016lx", regs[1]);
2408       tty->print_cr(" r2 = 0x%016lx", regs[2]);
2409       tty->print_cr(" r3 = 0x%016lx", regs[3]);
2410       tty->print_cr(" r4 = 0x%016lx", regs[4]);
2411       tty->print_cr(" r5 = 0x%016lx", regs[5]);
2412       tty->print_cr(" r6 = 0x%016lx", regs[6]);
2413       tty->print_cr(" r7 = 0x%016lx", regs[7]);
2414       tty->print_cr(" r8 = 0x%016lx", regs[8]);
2415       tty->print_cr(" r9 = 0x%016lx", regs[9]);
2416       tty->print_cr("r10 = 0x%016lx", regs[10]);
2417       tty->print_cr("r11 = 0x%016lx", regs[11]);


3805 
3806   bind(done);
3807 }
3808 
3809 void MacroAssembler::shenandoah_write_barrier(Register dst) {
3810   assert(UseShenandoahGC && ShenandoahWriteBarrier, "Should be enabled");
3811   assert(dst != rscratch1, "need rscratch1");
3812   assert(dst != rscratch2, "need rscratch2");
3813 
3814   Label done;
3815 
3816   Address gc_state(rthread, in_bytes(JavaThread::gc_state_offset()));
3817   ldrb(rscratch1, gc_state);
3818 
3819   // Check for heap stability
3820   mov(rscratch2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION);
3821   tst(rscratch1, rscratch2);
3822   br(Assembler::EQ, done);
3823 
3824   // Heap is unstable, need to perform the read-barrier even if WB is inactive
3825   if (ShenandoahWriteBarrierRB) {
3826     ldr(dst, Address(dst, BrooksPointer::byte_offset()));
3827   }
3828 
3829   // Check for evacuation-in-progress and jump to WB slow-path if needed
3830   mov(rscratch2, ShenandoahHeap::EVACUATION);
3831   tst(rscratch1, rscratch2);
3832   br(Assembler::EQ, done);
3833 
3834   RegSet to_save = RegSet::of(r0);
3835   if (dst != r0) {
3836     push(to_save, sp);
3837     mov(r0, dst);
3838   }
3839 
3840   assert(StubRoutines::aarch64::shenandoah_wb() != NULL, "need write barrier stub");
3841   far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::aarch64::shenandoah_wb())));
3842 
3843   if (dst != r0) {
3844     mov(dst, r0);
3845     pop(to_save, sp);
3846   }
3847   block_comment("} Shenandoah write barrier");



   1 /*
   2 /*
   3  * Copyright (c) 2013, Red Hat Inc.
   4  * Copyright (c) 1997, 2012, Oracle and/or its affiliates.
   5  * All rights reserved.
   6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   7  *
   8  * This code is free software; you can redistribute it and/or modify it
   9  * under the terms of the GNU General Public License version 2 only, as
  10  * published by the Free Software Foundation.
  11  *
  12  * This code is distributed in the hope that it will be useful, but WITHOUT
  13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15  * version 2 for more details (a copy is included in the LICENSE file that
  16  * accompanied this code).
  17  *
  18  * You should have received a copy of the GNU General Public License version
  19  * 2 along with this work; if not, write to the Free Software Foundation,
  20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  21  *
  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  *
  26  */
  27 
  28 #include <sys/types.h>
  29 
  30 #include "precompiled.hpp"
  31 #include "asm/assembler.hpp"
  32 #include "asm/assembler.inline.hpp"
  33 #include "interpreter/interpreter.hpp"
  34 
  35 #include "compiler/disassembler.hpp"
  36 #include "gc_interface/collectedHeap.inline.hpp"
  37 #include "gc_implementation/shenandoah/shenandoahBrooksPointer.hpp"
  38 #include "gc_implementation/shenandoah/shenandoahHeap.hpp"
  39 #include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
  40 #include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp"
  41 #include "memory/resourceArea.hpp"
  42 #include "runtime/biasedLocking.hpp"
  43 #include "runtime/interfaceSupport.hpp"
  44 #include "runtime/sharedRuntime.hpp"
  45 
  46 // #include "gc_interface/collectedHeap.inline.hpp"
  47 // #include "interpreter/interpreter.hpp"
  48 // #include "memory/cardTableModRefBS.hpp"
  49 // #include "prims/methodHandles.hpp"
  50 // #include "runtime/biasedLocking.hpp"
  51 // #include "runtime/interfaceSupport.hpp"
  52 // #include "runtime/objectMonitor.hpp"
  53 // #include "runtime/os.hpp"
  54 // #include "runtime/sharedRuntime.hpp"
  55 // #include "runtime/stubRoutines.hpp"
  56 
  57 #if INCLUDE_ALL_GCS


1416 
1417 void MacroAssembler::super_call_VM_leaf(address entry_point, Register arg_0, Register arg_1, Register arg_2, Register arg_3) {
1418   assert(arg_0 != c_rarg3, "smashed arg");
1419   assert(arg_1 != c_rarg3, "smashed arg");
1420   assert(arg_2 != c_rarg3, "smashed arg");
1421   pass_arg3(this, arg_3);
1422   assert(arg_0 != c_rarg2, "smashed arg");
1423   assert(arg_1 != c_rarg2, "smashed arg");
1424   pass_arg2(this, arg_2);
1425   assert(arg_0 != c_rarg1, "smashed arg");
1426   pass_arg1(this, arg_1);
1427   pass_arg0(this, arg_0);
1428   MacroAssembler::call_VM_leaf_base(entry_point, 4);
1429 }
1430 
1431 void MacroAssembler::null_check(Register reg, int offset) {
1432   if (needs_explicit_null_check(offset)) {
1433     // provoke OS NULL exception if reg = NULL by
1434     // accessing M[reg] w/o changing any registers
1435     // NOTE: this is plenty to provoke a segv

1436     ldr(zr, Address(reg));
1437   } else {
1438     // nothing to do, (later) access of M[reg + offset]
1439     // will provoke OS NULL exception if reg = NULL
1440   }
1441 }
1442 
1443 // MacroAssembler protected routines needed to implement
1444 // public methods
1445 
1446 void MacroAssembler::mov(Register r, Address dest) {
1447   code_section()->relocate(pc(), dest.rspec());
1448   u_int64_t imm64 = (u_int64_t)dest.target();
1449   movptr(r, imm64);
1450 }
1451 
1452 // Move a constant pointer into r.  In AArch64 mode the virtual
1453 // address space is 48 bits in size, so we only need three
1454 // instructions to create a patchable instruction sequence that can
1455 // reach anywhere.


2001   return count;
2002 }
2003 #ifdef ASSERT
2004 void MacroAssembler::verify_heapbase(const char* msg) {
2005 #if 0
2006   assert (UseCompressedOops || UseCompressedClassPointers, "should be compressed");
2007   assert (Universe::heap() != NULL, "java heap should be initialized");
2008   if (CheckCompressedOops) {
2009     Label ok;
2010     push(1 << rscratch1->encoding(), sp); // cmpptr trashes rscratch1
2011     cmpptr(rheapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()));
2012     br(Assembler::EQ, ok);
2013     stop(msg);
2014     bind(ok);
2015     pop(1 << rscratch1->encoding(), sp);
2016   }
2017 #endif
2018 }
2019 #endif
2020 
2021 void MacroAssembler::stop(const char* msg) {
2022   address ip = pc();
2023   pusha();
2024   mov(c_rarg0, (address)msg);
2025   mov(c_rarg1, (address)ip);








2026   mov(c_rarg2, sp);
2027   mov(c_rarg3, CAST_FROM_FN_PTR(address, MacroAssembler::debug64));
2028   // call(c_rarg3);
2029   blrt(c_rarg3, 3, 0, 1);
2030   hlt(0);
2031 }
2032 
2033 // If a constant does not fit in an immediate field, generate some
2034 // number of MOV instructions and then perform the operation.
2035 void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm,
2036                                            add_sub_imm_insn insn1,
2037                                            add_sub_reg_insn insn2) {
2038   assert(Rd != zr, "Rd = zr and not setting flags?");
2039   if (operand_valid_for_add_sub_immediate((int)imm)) {
2040     (this->*insn1)(Rd, Rn, imm);
2041   } else {
2042     if (uabs(imm) < (1 << 24)) {
2043        (this->*insn1)(Rd, Rn, imm & -(1 << 12));
2044        (this->*insn1)(Rd, Rd, imm & ((1 << 12)-1));
2045     } else {


2367   str(t1, Address(thread, in_bytes(JavaThread::allocated_bytes_offset())));
2368 }
2369 
2370 #ifndef PRODUCT
2371 extern "C" void findpc(intptr_t x);
2372 #endif
2373 
2374 void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
2375 {
2376   // In order to get locks to work, we need to fake a in_VM state
2377   if (ShowMessageBoxOnError ) {
2378     JavaThread* thread = JavaThread::current();
2379     JavaThreadState saved_state = thread->thread_state();
2380     thread->set_thread_state(_thread_in_vm);
2381 #ifndef PRODUCT
2382     if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
2383       ttyLocker ttyl;
2384       BytecodeCounter::print();
2385     }
2386 #endif

2387     if (os::message_box(msg, "Execution stopped, print registers?")) {
2388       ttyLocker ttyl;
2389       tty->print_cr(" pc = 0x%016lx", pc);
2390 #ifndef PRODUCT
2391       tty->cr();
2392       findpc(pc);
2393       tty->cr();
2394 #endif
2395       tty->print_cr(" r0 = 0x%016lx", regs[0]);
2396       tty->print_cr(" r1 = 0x%016lx", regs[1]);
2397       tty->print_cr(" r2 = 0x%016lx", regs[2]);
2398       tty->print_cr(" r3 = 0x%016lx", regs[3]);
2399       tty->print_cr(" r4 = 0x%016lx", regs[4]);
2400       tty->print_cr(" r5 = 0x%016lx", regs[5]);
2401       tty->print_cr(" r6 = 0x%016lx", regs[6]);
2402       tty->print_cr(" r7 = 0x%016lx", regs[7]);
2403       tty->print_cr(" r8 = 0x%016lx", regs[8]);
2404       tty->print_cr(" r9 = 0x%016lx", regs[9]);
2405       tty->print_cr("r10 = 0x%016lx", regs[10]);
2406       tty->print_cr("r11 = 0x%016lx", regs[11]);


3794 
3795   bind(done);
3796 }
3797 
3798 void MacroAssembler::shenandoah_write_barrier(Register dst) {
3799   assert(UseShenandoahGC && ShenandoahWriteBarrier, "Should be enabled");
3800   assert(dst != rscratch1, "need rscratch1");
3801   assert(dst != rscratch2, "need rscratch2");
3802 
3803   Label done;
3804 
3805   Address gc_state(rthread, in_bytes(JavaThread::gc_state_offset()));
3806   ldrb(rscratch1, gc_state);
3807 
3808   // Check for heap stability
3809   mov(rscratch2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::EVACUATION);
3810   tst(rscratch1, rscratch2);
3811   br(Assembler::EQ, done);
3812 
3813   // Heap is unstable, need to perform the read-barrier even if WB is inactive
3814   ldr(dst, Address(dst, ShenandoahBrooksPointer::byte_offset()));


3815 
3816   // Check for evacuation-in-progress and jump to WB slow-path if needed
3817   mov(rscratch2, ShenandoahHeap::EVACUATION);
3818   tst(rscratch1, rscratch2);
3819   br(Assembler::EQ, done);
3820 
3821   RegSet to_save = RegSet::of(r0);
3822   if (dst != r0) {
3823     push(to_save, sp);
3824     mov(r0, dst);
3825   }
3826 
3827   assert(StubRoutines::aarch64::shenandoah_wb() != NULL, "need write barrier stub");
3828   far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::aarch64::shenandoah_wb())));
3829 
3830   if (dst != r0) {
3831     mov(dst, r0);
3832     pop(to_save, sp);
3833   }
3834   block_comment("} Shenandoah write barrier");


< prev index next >