src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp

Print this page
rev 7516 : 8069593: AARCH64: Changes to JavaThread::_thread_state must use acquire and release
Summary: Use release stores for all changes to thread state.
Reviewed-by: kvn


1828     // Save the test result, for recursive case, the result is zero
1829     __ str(swap_reg, Address(lock_reg, mark_word_offset));
1830     __ br(Assembler::NE, slow_path_lock);
1831 
1832     // Slow path will re-enter here
1833 
1834     __ bind(lock_done);
1835   }
1836 
1837 
1838   // Finally just about ready to make the JNI call
1839 
1840 
1841   // get JNIEnv* which is first argument to native
1842   if (!is_critical_native) {
1843     __ lea(c_rarg0, Address(rthread, in_bytes(JavaThread::jni_environment_offset())));
1844   }
1845 
1846   // Now set thread in native
1847   __ mov(rscratch1, _thread_in_native);
1848   __ str(rscratch1, Address(rthread, JavaThread::thread_state_offset()));

1849 
1850   {
1851     int return_type = 0;
1852     switch (ret_type) {
1853     case T_VOID: break;
1854       return_type = 0; break;
1855     case T_CHAR:
1856     case T_BYTE:
1857     case T_SHORT:
1858     case T_INT:
1859     case T_BOOLEAN:
1860     case T_LONG:
1861       return_type = 1; break;
1862     case T_ARRAY:
1863     case T_OBJECT:
1864       return_type = 1; break;
1865     case T_FLOAT:
1866       return_type = 2; break;
1867     case T_DOUBLE:
1868       return_type = 3; break;


1885   case T_DOUBLE :
1886   case T_FLOAT  :
1887     // Result is in v0 we'll save as needed
1888     break;
1889   case T_ARRAY:                 // Really a handle
1890   case T_OBJECT:                // Really a handle
1891       break; // can't de-handlize until after safepoint check
1892   case T_VOID: break;
1893   case T_LONG: break;
1894   default       : ShouldNotReachHere();
1895   }
1896 
1897   // Switch thread to "native transition" state before reading the synchronization state.
1898   // This additional state is necessary because reading and testing the synchronization
1899   // state is not atomic w.r.t. GC, as this scenario demonstrates:
1900   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
1901   //     VM thread changes sync state to synchronizing and suspends threads for GC.
1902   //     Thread A is resumed to finish this native method, but doesn't block here since it
1903   //     didn't see any synchronization is progress, and escapes.
1904   __ mov(rscratch1, _thread_in_native_trans);
1905   __ str(rscratch1, Address(rthread, JavaThread::thread_state_offset()));

1906 
1907   if(os::is_MP()) {
1908     if (UseMembar) {
1909       // Force this write out before the read below
1910       __ dmb(Assembler::SY);
1911     } else {
1912       // Write serialization page so VM thread can do a pseudo remote membar.
1913       // We use the current thread pointer to calculate a thread specific
1914       // offset to write to within the page. This minimizes bus traffic
1915       // due to cache line collision.
1916       __ serialize_memory(rthread, r2);
1917     }
1918   }
1919 
1920   Label after_transition;
1921 
1922   // check for safepoint operation in progress and/or pending suspend requests
1923   {
1924     Label Continue;
1925 


1949       __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
1950     } else {
1951       __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition)));
1952     }
1953     __ blrt(rscratch1, 1, 0, 1);
1954     __ maybe_isb();
1955     // Restore any method result value
1956     restore_native_result(masm, ret_type, stack_slots);
1957 
1958     if (is_critical_native) {
1959       // The call above performed the transition to thread_in_Java so
1960       // skip the transition logic below.
1961       __ b(after_transition);
1962     }
1963 
1964     __ bind(Continue);
1965   }
1966 
1967   // change thread state
1968   __ mov(rscratch1, _thread_in_Java);
1969   __ str(rscratch1, Address(rthread, JavaThread::thread_state_offset()));

1970   __ bind(after_transition);
1971 
1972   Label reguard;
1973   Label reguard_done;
1974   __ ldrb(rscratch1, Address(rthread, JavaThread::stack_guard_state_offset()));
1975   __ cmpw(rscratch1, JavaThread::stack_guard_yellow_disabled);
1976   __ br(Assembler::EQ, reguard);
1977   __ bind(reguard_done);
1978 
1979   // native result if any is live
1980 
1981   // Unlock
1982   Label unlock_done;
1983   Label slow_path_unlock;
1984   if (method->is_synchronized()) {
1985 
1986     // Get locked oop from the handle we passed to jni
1987     __ ldr(obj_reg, Address(oop_handle_reg, 0));
1988 
1989     Label done;




1828     // Save the test result, for recursive case, the result is zero
1829     __ str(swap_reg, Address(lock_reg, mark_word_offset));
1830     __ br(Assembler::NE, slow_path_lock);
1831 
1832     // Slow path will re-enter here
1833 
1834     __ bind(lock_done);
1835   }
1836 
1837 
1838   // Finally just about ready to make the JNI call
1839 
1840 
1841   // get JNIEnv* which is first argument to native
1842   if (!is_critical_native) {
1843     __ lea(c_rarg0, Address(rthread, in_bytes(JavaThread::jni_environment_offset())));
1844   }
1845 
1846   // Now set thread in native
1847   __ mov(rscratch1, _thread_in_native);
1848   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1849   __ stlrw(rscratch1, rscratch2);
1850 
1851   {
1852     int return_type = 0;
1853     switch (ret_type) {
1854     case T_VOID: break;
1855       return_type = 0; break;
1856     case T_CHAR:
1857     case T_BYTE:
1858     case T_SHORT:
1859     case T_INT:
1860     case T_BOOLEAN:
1861     case T_LONG:
1862       return_type = 1; break;
1863     case T_ARRAY:
1864     case T_OBJECT:
1865       return_type = 1; break;
1866     case T_FLOAT:
1867       return_type = 2; break;
1868     case T_DOUBLE:
1869       return_type = 3; break;


1886   case T_DOUBLE :
1887   case T_FLOAT  :
1888     // Result is in v0 we'll save as needed
1889     break;
1890   case T_ARRAY:                 // Really a handle
1891   case T_OBJECT:                // Really a handle
1892       break; // can't de-handlize until after safepoint check
1893   case T_VOID: break;
1894   case T_LONG: break;
1895   default       : ShouldNotReachHere();
1896   }
1897 
1898   // Switch thread to "native transition" state before reading the synchronization state.
1899   // This additional state is necessary because reading and testing the synchronization
1900   // state is not atomic w.r.t. GC, as this scenario demonstrates:
1901   //     Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted.
1902   //     VM thread changes sync state to synchronizing and suspends threads for GC.
1903   //     Thread A is resumed to finish this native method, but doesn't block here since it
1904   //     didn't see any synchronization is progress, and escapes.
1905   __ mov(rscratch1, _thread_in_native_trans);
1906   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1907   __ stlrw(rscratch1, rscratch2);
1908 
1909   if(os::is_MP()) {
1910     if (UseMembar) {
1911       // Force this write out before the read below
1912       __ dmb(Assembler::SY);
1913     } else {
1914       // Write serialization page so VM thread can do a pseudo remote membar.
1915       // We use the current thread pointer to calculate a thread specific
1916       // offset to write to within the page. This minimizes bus traffic
1917       // due to cache line collision.
1918       __ serialize_memory(rthread, r2);
1919     }
1920   }
1921 
1922   Label after_transition;
1923 
1924   // check for safepoint operation in progress and/or pending suspend requests
1925   {
1926     Label Continue;
1927 


1951       __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
1952     } else {
1953       __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition)));
1954     }
1955     __ blrt(rscratch1, 1, 0, 1);
1956     __ maybe_isb();
1957     // Restore any method result value
1958     restore_native_result(masm, ret_type, stack_slots);
1959 
1960     if (is_critical_native) {
1961       // The call above performed the transition to thread_in_Java so
1962       // skip the transition logic below.
1963       __ b(after_transition);
1964     }
1965 
1966     __ bind(Continue);
1967   }
1968 
1969   // change thread state
1970   __ mov(rscratch1, _thread_in_Java);
1971   __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
1972   __ stlrw(rscratch1, rscratch2);
1973   __ bind(after_transition);
1974 
1975   Label reguard;
1976   Label reguard_done;
1977   __ ldrb(rscratch1, Address(rthread, JavaThread::stack_guard_state_offset()));
1978   __ cmpw(rscratch1, JavaThread::stack_guard_yellow_disabled);
1979   __ br(Assembler::EQ, reguard);
1980   __ bind(reguard_done);
1981 
1982   // native result if any is live
1983 
1984   // Unlock
1985   Label unlock_done;
1986   Label slow_path_unlock;
1987   if (method->is_synchronized()) {
1988 
1989     // Get locked oop from the handle we passed to jni
1990     __ ldr(obj_reg, Address(oop_handle_reg, 0));
1991 
1992     Label done;