< prev index next >

src/cpu/aarch32/vm/sharedRuntime_aarch32.cpp

Print this page
rev 8069 : 8164652: aarch32: C1 port


1029   // We always ignore the frame_slots arg and just use the space just below frame pointer
1030   // which by this time is free to use
1031   switch (ret_type) {
1032   case T_FLOAT:
1033     __ vldr_f32(d0, Address(rfp, -2 * wordSize));
1034     break;
1035   case T_DOUBLE:
1036     __ vldr_f64(d0, Address(rfp, -3 * wordSize));
1037     break;
1038   case T_LONG:
1039     __ ldrd(r0, r1, Address(rfp, -3 * wordSize));
1040     break;
1041   case T_VOID:
1042     break;
1043   default:
1044     __ ldr(r0, Address(rfp, -2 * wordSize));
1045     break;
1046   }
1047 }
1048 
1049 static void save_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) {
1050   RegSet x;

1051   for ( int i = first_arg ; i < arg_count ; i++ ) {
1052     if (args[i].first()->is_Register()) {
1053       x = x + args[i].first()->as_Register();

1054     } else if (args[i].first()->is_FloatRegister()) {
1055       FloatRegister fr = args[i].first()->as_FloatRegister();
1056 
1057       if (args[i].second()->is_FloatRegister()) {
1058     assert(args[i].is_single_phys_reg(), "doubles should be 2 consequents float regs");
1059         __ decrement(sp, 2 * wordSize);
1060     __ vstr_f64(fr, Address(sp));

1061       } else {
1062         __ decrement(sp, wordSize);
1063     __ vstr_f32(fr, Address(sp));

1064       }
1065     }
1066   }
1067   __ push(x, sp);

1068 }
1069 
1070 static void restore_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) {
1071   RegSet x;
1072   for ( int i = first_arg ; i < arg_count ; i++ ) {
1073     if (args[i].first()->is_Register()) {
1074       x = x + args[i].first()->as_Register();
1075     } else {
1076       ;
1077     }
1078   }
1079   __ pop(x, sp);
1080   for ( int i = first_arg ; i < arg_count ; i++ ) {
1081     if (args[i].first()->is_Register()) {
1082       ;
1083     } else if (args[i].first()->is_FloatRegister()) {
1084       FloatRegister fr = args[i].first()->as_FloatRegister();
1085 
1086       if (args[i].second()->is_FloatRegister()) {
1087     assert(args[i].is_single_phys_reg(), "doubles should be 2 consequents float regs");


1748   }
1749 
1750   // Change state to native (we save the return address in the thread, since it might not
1751   // be pushed on the stack when we do a a stack traversal). It is enough that the pc()
1752   // points into the right code segment. It does not have to be the correct return pc.
1753   // We use the same pc/oopMap repeatedly when we call out
1754 
1755   intptr_t the_pc = (intptr_t) __ pc();
1756   oop_maps->add_gc_map(the_pc - start, map);
1757 
1758   __ set_last_Java_frame(sp, noreg, (address)the_pc, rscratch1);
1759 
1760 
1761   // We have all of the arguments setup at this point. We must not touch any register
1762   // argument registers at this point (what if we save/restore them there are no oop?
1763 
1764 #ifdef DTRACE_ENABLED
1765   {
1766     SkipIfEqual skip(masm, &DTraceMethodProbes, false);
1767     // protect the args we've loaded
1768     save_args(masm, total_c_args, c_arg, out_regs);
1769     __ mov_metadata(c_rarg1, method());
1770     __ call_VM_leaf(
1771       CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
1772       rthread, c_rarg1);
1773     restore_args(masm, total_c_args, c_arg, out_regs);
1774   }
1775 #endif
1776 
1777   // RedefineClasses() tracing support for obsolete method entry
1778   if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
1779     // protect the args we've loaded
1780     save_args(masm, total_c_args, c_arg, out_regs);
1781     __ mov_metadata(c_rarg1, method());
1782     __ call_VM_leaf(
1783       CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
1784       rthread, c_rarg1);
1785     restore_args(masm, total_c_args, c_arg, out_regs);
1786   }
1787 
1788   // Lock a synchronized method
1789 
1790   // Register definitions used by locking and unlocking
1791 
1792   Label slow_path_lock;
1793   Label lock_done;
1794 
1795   if (method->is_synchronized()) {
1796     assert(!is_critical_native, "unhandled");
1797     // TODO Fast path disabled as requires at least 4 registers, which already contain arguments prepared for call











1798 
1799     // Get the handle (the 2nd argument)
1800     __ mov(oop_handle_reg, c_rarg1);
1801     __ b(slow_path_lock);






















1802 
1803     // Slow path will re-enter here
1804     __ bind(lock_done);
1805   }
1806 
1807 
1808   // Finally just about ready to make the JNI call
1809 
1810 
1811   // get JNIEnv* which is first argument to native
1812   if (!is_critical_native) {
1813     __ lea(c_rarg0, Address(rthread, in_bytes(JavaThread::jni_environment_offset())));
1814   }
1815 
1816   // Now set thread in native
1817   __ mov(rscratch1, _thread_in_native);
1818   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1819   __ dmb(Assembler::ISH);
1820   __ str(rscratch1, rscratch2);
1821 


1839   case T_VOID: break;
1840   case T_LONG: break;
1841   default       : ShouldNotReachHere();
1842   }
1843 
1844   // Switch thread to "native transition" state before reading the synchronization state.
1845   // This additional state is necessary because reading and testing the synchronization
1846   // state is not atomic w.r.t. GC, as this scenario demonstrates:
1847   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
1848   //     VM thread changes sync state to synchronizing and suspends threads for GC.
1849   //     Thread A is resumed to finish this native method, but doesn't block here since it
1850   //     didn't see any synchronization is progress, and escapes.
1851   __ mov(rscratch1, _thread_in_native_trans);
1852   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1853   __ dmb(Assembler::ISH);
1854   __ str(rscratch1, rscratch2);
1855 
1856   if(os::is_MP()) {
1857     if (UseMembar) {
1858       // Force this write out before the read below
1859       __ dmb(Assembler::SY);
1860     } else {
1861       // Write serialization page so VM thread can do a pseudo remote membar.
1862       // We use the current thread pointer to calculate a thread specific
1863       // offset to write to within the page. This minimizes bus traffic
1864       // due to cache line collision.
1865       __ serialize_memory(rthread, rscratch1);
1866     }
1867   }
1868 
1869   Label after_transition;
1870 
1871   // check for safepoint operation in progress and/or pending suspend requests
1872   {
1873     Label Continue;
1874 
1875     __ mov(rscratch1, ExternalAddress((address)SafepointSynchronize::address_of_state()));
1876     __ ldr(rscratch1, Address(rscratch1));
1877     __ cmp(rscratch1, SafepointSynchronize::_not_synchronized);
1878 
1879     Label L;


1912   // change thread state
1913   __ mov(rscratch1, _thread_in_Java);
1914   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1915   __ dmb(Assembler::ISH);
1916   __ str(rscratch1, rscratch2);
1917   __ bind(after_transition);
1918 
1919   Label reguard;
1920   Label reguard_done;
1921   __ ldrb(rscratch1, Address(rthread, JavaThread::stack_guard_state_offset()));
1922   __ cmp(rscratch1, JavaThread::stack_guard_yellow_disabled);
1923   __ b(reguard, Assembler::EQ);
1924   __ bind(reguard_done);
1925 
1926   // native result if any is live
1927 
1928   // Unlock
1929   Label unlock_done;
1930   Label slow_path_unlock;
1931   if (method->is_synchronized()) {
1932     // TODO fast path disabled as requires at least 4 registers, but r0,r1 contains result
1933     __ b(slow_path_unlock);





















1934 
1935     // slow path re-enters here
1936     __ bind(unlock_done);
1937   }
1938 
1939 #ifdef DTRACE_ENABLED
1940   {
1941     SkipIfEqual skip(masm, &DTraceMethodProbes, false);
1942     save_native_result(masm, ret_type, stack_slots);
1943     __ mov_metadata(c_rarg1, method());
1944     __ call_VM_leaf(
1945          CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit),
1946          rthread, c_rarg1);
1947     restore_native_result(masm, ret_type, stack_slots);
1948   }
1949 #endif
1950 
1951   __ reset_last_Java_frame(false, true);
1952 
1953   // Unpack oop result


1980   // Unexpected paths are out of line and go here
1981 
1982   if (!is_critical_native) {
1983     // forward the exception
1984     __ bind(exception_pending);
1985 
1986     // and forward the exception
1987     __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
1988   }
1989 
1990   // Slow path locking & unlocking
1991   if (method->is_synchronized()) {
1992 
1993     // BEGIN Slow path lock
1994     __ bind(slow_path_lock);
1995 
1996     // has last_Java_frame setup. No exceptions so do vanilla call not call_VM
1997     // args are (oop obj, BasicLock* lock, JavaThread* thread)
1998 
1999     // protect the args we've loaded
2000     save_args(masm, total_c_args, c_arg, out_regs);
2001 
2002     __ ldr(c_rarg0, Address(oop_handle_reg));
2003     __ lea(c_rarg1, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
2004     __ mov(c_rarg2, rthread);
2005 
2006     // Not a leaf but we have last_Java_frame setup as we want
2007     __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), 3);
2008     restore_args(masm, total_c_args, c_arg, out_regs);
2009 
2010 #ifdef ASSERT
2011     { Label L;
2012       __ ldr(rscratch1, Address(rthread, in_bytes(Thread::pending_exception_offset())));
2013       __ cbz(rscratch1, L);
2014       __ stop("no pending exception allowed on exit from monitorenter");
2015       __ bind(L);
2016     }
2017 #endif
2018     __ b(lock_done);
2019 
2020     // END Slow path lock
2021 
2022     // BEGIN Slow path unlock
2023     __ bind(slow_path_unlock);




1029   // We always ignore the frame_slots arg and just use the space just below frame pointer
1030   // which by this time is free to use
1031   switch (ret_type) {
1032   case T_FLOAT:
1033     __ vldr_f32(d0, Address(rfp, -2 * wordSize));
1034     break;
1035   case T_DOUBLE:
1036     __ vldr_f64(d0, Address(rfp, -3 * wordSize));
1037     break;
1038   case T_LONG:
1039     __ ldrd(r0, r1, Address(rfp, -3 * wordSize));
1040     break;
1041   case T_VOID:
1042     break;
1043   default:
1044     __ ldr(r0, Address(rfp, -2 * wordSize));
1045     break;
1046   }
1047 }
1048 
1049 static int save_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) {
1050   RegSet x;
1051   int saved_slots = 0;
1052   for ( int i = first_arg ; i < arg_count ; i++ ) {
1053     if (args[i].first()->is_Register()) {
1054       x = x + args[i].first()->as_Register();
1055       ++saved_slots;
1056     } else if (args[i].first()->is_FloatRegister()) {
1057       FloatRegister fr = args[i].first()->as_FloatRegister();
1058 
1059       if (args[i].second()->is_FloatRegister()) {
1060     assert(args[i].is_single_phys_reg(), "doubles should be 2 consequents float regs");
1061         __ decrement(sp, 2 * wordSize);
1062     __ vstr_f64(fr, Address(sp));
1063         saved_slots += 2;
1064       } else {
1065         __ decrement(sp, wordSize);
1066     __ vstr_f32(fr, Address(sp));
1067         ++saved_slots;
1068       }
1069     }
1070   }
1071   __ push(x, sp);
1072   return saved_slots;
1073 }
1074 
1075 static void restore_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) {
1076   RegSet x;
1077   for ( int i = first_arg ; i < arg_count ; i++ ) {
1078     if (args[i].first()->is_Register()) {
1079       x = x + args[i].first()->as_Register();
1080     } else {
1081       ;
1082     }
1083   }
1084   __ pop(x, sp);
1085   for ( int i = first_arg ; i < arg_count ; i++ ) {
1086     if (args[i].first()->is_Register()) {
1087       ;
1088     } else if (args[i].first()->is_FloatRegister()) {
1089       FloatRegister fr = args[i].first()->as_FloatRegister();
1090 
1091       if (args[i].second()->is_FloatRegister()) {
1092     assert(args[i].is_single_phys_reg(), "doubles should be 2 consequents float regs");


1753   }
1754 
1755   // Change state to native (we save the return address in the thread, since it might not
1756   // be pushed on the stack when we do a a stack traversal). It is enough that the pc()
1757   // points into the right code segment. It does not have to be the correct return pc.
1758   // We use the same pc/oopMap repeatedly when we call out
1759 
1760   intptr_t the_pc = (intptr_t) __ pc();
1761   oop_maps->add_gc_map(the_pc - start, map);
1762 
1763   __ set_last_Java_frame(sp, noreg, (address)the_pc, rscratch1);
1764 
1765 
1766   // We have all of the arguments setup at this point. We must not touch any register
1767   // argument registers at this point (what if we save/restore them there are no oop?
1768 
1769 #ifdef DTRACE_ENABLED
1770   {
1771     SkipIfEqual skip(masm, &DTraceMethodProbes, false);
1772     // protect the args we've loaded
1773     (void) save_args(masm, total_c_args, c_arg, out_regs);
1774     __ mov_metadata(c_rarg1, method());
1775     __ call_VM_leaf(
1776       CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
1777       rthread, c_rarg1);
1778     restore_args(masm, total_c_args, c_arg, out_regs);
1779   }
1780 #endif
1781 
1782   // RedefineClasses() tracing support for obsolete method entry
1783   if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) {
1784     // protect the args we've loaded
1785     (void) save_args(masm, total_c_args, c_arg, out_regs);
1786     __ mov_metadata(c_rarg1, method());
1787     __ call_VM_leaf(
1788       CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry),
1789       rthread, c_rarg1);
1790     restore_args(masm, total_c_args, c_arg, out_regs);
1791   }
1792 
1793   // Lock a synchronized method
1794 
1795   // Register definitions used by locking and unlocking
1796 
1797   Label slow_path_lock;
1798   Label lock_done;
1799 
1800   if (method->is_synchronized()) {
1801     assert(!is_critical_native, "unhandled");
1802 
1803     // registers below are not used to pass parameters
1804     // and they are caller save in C1
1805     // => safe to use as temporary here
1806 #ifdef COMPILER2
1807     stop("fix temporary register set below");
1808 #endif
1809     const Register swap_reg = r5;
1810     const Register obj_reg  = r6;  // Will contain the oop
1811     const Register lock_reg = r7;  // Address of compiler lock object (BasicLock)
1812 
1813     const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
1814 
1815     // Get the handle (the 2nd argument)
1816     __ mov(oop_handle_reg, c_rarg1);
1817 
1818     // Get address of the box
1819 
1820     __ lea(lock_reg, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
1821 
1822     // Load the oop from the handle
1823     __ ldr(obj_reg, Address(oop_handle_reg, 0));
1824 
1825     if (UseBiasedLocking) {
1826       __ biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch2, false, lock_done, &slow_path_lock);
1827     }
1828 
1829     // Load (object->mark() | 1) into swap_reg %r0
1830     __ ldr(swap_reg, Address(obj_reg, 0));
1831     __ orr(swap_reg, swap_reg, 1);
1832 
1833     // Save (object->mark() | 1) into BasicLock's displaced header
1834     __ str(swap_reg, Address(lock_reg, mark_word_offset));
1835 
1836     // src -> dest iff dest == r0 else r0 <- dest
1837     { Label here;
1838       __ cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, lock_done, &slow_path_lock);
1839     }
1840 
1841     // Slow path will re-enter here
1842     __ bind(lock_done);
1843   }
1844 
1845 
1846   // Finally just about ready to make the JNI call
1847 
1848 
1849   // get JNIEnv* which is first argument to native
1850   if (!is_critical_native) {
1851     __ lea(c_rarg0, Address(rthread, in_bytes(JavaThread::jni_environment_offset())));
1852   }
1853 
1854   // Now set thread in native
1855   __ mov(rscratch1, _thread_in_native);
1856   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1857   __ dmb(Assembler::ISH);
1858   __ str(rscratch1, rscratch2);
1859 


1877   case T_VOID: break;
1878   case T_LONG: break;
1879   default       : ShouldNotReachHere();
1880   }
1881 
1882   // Switch thread to "native transition" state before reading the synchronization state.
1883   // This additional state is necessary because reading and testing the synchronization
1884   // state is not atomic w.r.t. GC, as this scenario demonstrates:
1885   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
1886   //     VM thread changes sync state to synchronizing and suspends threads for GC.
1887   //     Thread A is resumed to finish this native method, but doesn't block here since it
1888   //     didn't see any synchronization is progress, and escapes.
1889   __ mov(rscratch1, _thread_in_native_trans);
1890   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1891   __ dmb(Assembler::ISH);
1892   __ str(rscratch1, rscratch2);
1893 
1894   if(os::is_MP()) {
1895     if (UseMembar) {
1896       // Force this write out before the read below
1897       __ membar(Assembler::AnyAny);
1898     } else {
1899       // Write serialization page so VM thread can do a pseudo remote membar.
1900       // We use the current thread pointer to calculate a thread specific
1901       // offset to write to within the page. This minimizes bus traffic
1902       // due to cache line collision.
1903       __ serialize_memory(rthread, rscratch1);
1904     }
1905   }
1906 
1907   Label after_transition;
1908 
1909   // check for safepoint operation in progress and/or pending suspend requests
1910   {
1911     Label Continue;
1912 
1913     __ mov(rscratch1, ExternalAddress((address)SafepointSynchronize::address_of_state()));
1914     __ ldr(rscratch1, Address(rscratch1));
1915     __ cmp(rscratch1, SafepointSynchronize::_not_synchronized);
1916 
1917     Label L;


1950   // change thread state
1951   __ mov(rscratch1, _thread_in_Java);
1952   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1953   __ dmb(Assembler::ISH);
1954   __ str(rscratch1, rscratch2);
1955   __ bind(after_transition);
1956 
1957   Label reguard;
1958   Label reguard_done;
1959   __ ldrb(rscratch1, Address(rthread, JavaThread::stack_guard_state_offset()));
1960   __ cmp(rscratch1, JavaThread::stack_guard_yellow_disabled);
1961   __ b(reguard, Assembler::EQ);
1962   __ bind(reguard_done);
1963 
1964   // native result if any is live
1965 
1966   // Unlock
1967   Label unlock_done;
1968   Label slow_path_unlock;
1969   if (method->is_synchronized()) {
1970     const Register obj_reg  = r2;  // Will contain the oop
1971     const Register lock_reg = rscratch1; // Address of compiler lock object (BasicLock)
1972     const Register old_hdr  = r3;  // value of old header at unlock time
1973 
1974     // Get locked oop from the handle we passed to jni
1975     __ ldr(obj_reg, Address(oop_handle_reg, 0));
1976 
1977     if (UseBiasedLocking) {
1978       __ biased_locking_exit(obj_reg, old_hdr, unlock_done);
1979     }
1980 
1981     // Simple recursive lock?
1982     // get address of the stack lock
1983     __ lea(lock_reg, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size));
1984 
1985     //  get old displaced header
1986     __ ldr(old_hdr, Address(lock_reg, 0));
1987     __ cbz(old_hdr, unlock_done);
1988 
1989     // Atomic swap old header if oop still contains the stack lock
1990     Label succeed;
1991     __ cmpxchgptr(lock_reg, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock);
1992     __ bind(succeed);
1993 
1994     // slow path re-enters here
1995     __ bind(unlock_done);
1996   }
1997 
1998 #ifdef DTRACE_ENABLED
1999   {
2000     SkipIfEqual skip(masm, &DTraceMethodProbes, false);
2001     save_native_result(masm, ret_type, stack_slots);
2002     __ mov_metadata(c_rarg1, method());
2003     __ call_VM_leaf(
2004          CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit),
2005          rthread, c_rarg1);
2006     restore_native_result(masm, ret_type, stack_slots);
2007   }
2008 #endif
2009 
2010   __ reset_last_Java_frame(false, true);
2011 
2012   // Unpack oop result


2039   // Unexpected paths are out of line and go here
2040 
2041   if (!is_critical_native) {
2042     // forward the exception
2043     __ bind(exception_pending);
2044 
2045     // and forward the exception
2046     __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry()));
2047   }
2048 
2049   // Slow path locking & unlocking
2050   if (method->is_synchronized()) {
2051 
2052     // BEGIN Slow path lock
2053     __ bind(slow_path_lock);
2054 
2055     // has last_Java_frame setup. No exceptions so do vanilla call not call_VM
2056     // args are (oop obj, BasicLock* lock, JavaThread* thread)
2057 
2058     // protect the args we've loaded
2059     const int extra_words = save_args(masm, total_c_args, c_arg, out_regs);
2060 
2061     __ ldr(c_rarg0, Address(oop_handle_reg));
2062     __ lea(c_rarg1, Address(sp, (extra_words + lock_slot_offset) * VMRegImpl::stack_slot_size));
2063     __ mov(c_rarg2, rthread);
2064 
2065     // Not a leaf but we have last_Java_frame setup as we want
2066     __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), 3);
2067     restore_args(masm, total_c_args, c_arg, out_regs);
2068 
2069 #ifdef ASSERT
2070     { Label L;
2071       __ ldr(rscratch1, Address(rthread, in_bytes(Thread::pending_exception_offset())));
2072       __ cbz(rscratch1, L);
2073       __ stop("no pending exception allowed on exit from monitorenter");
2074       __ bind(L);
2075     }
2076 #endif
2077     __ b(lock_done);
2078 
2079     // END Slow path lock
2080 
2081     // BEGIN Slow path unlock
2082     __ bind(slow_path_unlock);


< prev index next >