1448 // : clear z flag if retry count exceeded |
1448 // : clear z flag if retry count exceeded |
1449 // tmp_Reg, scr_Reg, flags are killed |
1449 // tmp_Reg, scr_Reg, flags are killed |
1450 void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg, |
1450 void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg, |
1451 Register tmp_Reg, Register scr_Reg, Label& retryLabel) { |
1451 Register tmp_Reg, Register scr_Reg, Label& retryLabel) { |
1452 Label SpinLoop, SpinExit, doneRetry; |
1452 Label SpinLoop, SpinExit, doneRetry; |
1453 // Clean monitor_value bit to get valid pointer |
1453 int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner); |
1454 int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value; |
|
1455 |
1454 |
1456 testl(retry_count_Reg, retry_count_Reg); |
1455 testl(retry_count_Reg, retry_count_Reg); |
1457 jccb(Assembler::zero, doneRetry); |
1456 jccb(Assembler::zero, doneRetry); |
1458 decrementl(retry_count_Reg); |
1457 decrementl(retry_count_Reg); |
1459 movptr(scr_Reg, RTMSpinLoopCount); |
1458 movptr(scr_Reg, RTMSpinLoopCount); |
1530 } |
1529 } |
1531 |
1530 |
1532 // Use RTM for inflating locks |
1531 // Use RTM for inflating locks |
1533 // inputs: objReg (object to lock) |
1532 // inputs: objReg (object to lock) |
1534 // boxReg (on-stack box address (displaced header location) - KILLED) |
1533 // boxReg (on-stack box address (displaced header location) - KILLED) |
1535 // tmpReg (ObjectMonitor address + 2(monitor_value)) |
1534 // tmpReg (ObjectMonitor address + markOopDesc::monitor_value) |
1536 void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg, |
1535 void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg, |
1537 Register scrReg, Register retry_on_busy_count_Reg, |
1536 Register scrReg, Register retry_on_busy_count_Reg, |
1538 Register retry_on_abort_count_Reg, |
1537 Register retry_on_abort_count_Reg, |
1539 RTMLockingCounters* rtm_counters, |
1538 RTMLockingCounters* rtm_counters, |
1540 Metadata* method_data, bool profile_rtm, |
1539 Metadata* method_data, bool profile_rtm, |
1541 Label& DONE_LABEL) { |
1540 Label& DONE_LABEL) { |
1542 assert(UseRTMLocking, "why call this otherwise?"); |
1541 assert(UseRTMLocking, "why call this otherwise?"); |
1543 assert(tmpReg == rax, ""); |
1542 assert(tmpReg == rax, ""); |
1544 assert(scrReg == rdx, ""); |
1543 assert(scrReg == rdx, ""); |
1545 Label L_rtm_retry, L_decrement_retry, L_on_abort; |
1544 Label L_rtm_retry, L_decrement_retry, L_on_abort; |
1546 // Clean monitor_value bit to get valid pointer |
1545 int owner_offset = OM_OFFSET_NO_MONITOR_VALUE_TAG(owner); |
1547 int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value; |
|
1548 |
1546 |
1549 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
1547 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
1550 movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); |
1548 movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); |
1551 movptr(boxReg, tmpReg); // Save ObjectMonitor address |
1549 movptr(boxReg, tmpReg); // Save ObjectMonitor address |
1552 |
1550 |
1821 } else { |
1819 } else { |
1822 #endif // INCLUDE_RTM_OPT |
1820 #endif // INCLUDE_RTM_OPT |
1823 |
1821 |
1824 #ifndef _LP64 |
1822 #ifndef _LP64 |
1825 // The object is inflated. |
1823 // The object is inflated. |
1826 // |
|
1827 // TODO-FIXME: eliminate the ugly use of manifest constants: |
|
1828 // Use markOopDesc::monitor_value instead of "2". |
|
1829 // use markOop::unused_mark() instead of "3". |
|
1830 // The tmpReg value is an objectMonitor reference ORed with |
|
1831 // markOopDesc::monitor_value (2). We can either convert tmpReg to an |
|
1832 // objectmonitor pointer by masking off the "2" bit or we can just |
|
1833 // use tmpReg as an objectmonitor pointer but bias the objectmonitor |
|
1834 // field offsets with "-2" to compensate for and annul the low-order tag bit. |
|
1835 // |
|
1836 // I use the latter as it avoids AGI stalls. |
|
1837 // As such, we write "mov r, [tmpReg+OFFSETOF(Owner)-2]" |
|
1838 // instead of "mov r, [tmpReg+OFFSETOF(Owner)]". |
|
1839 // |
|
1840 #define OFFSET_SKEWED(f) ((ObjectMonitor::f ## _offset_in_bytes())-2) |
|
1841 |
1824 |
1842 // boxReg refers to the on-stack BasicLock in the current frame. |
1825 // boxReg refers to the on-stack BasicLock in the current frame. |
1843 // We'd like to write: |
1826 // We'd like to write: |
1844 // set box->_displaced_header = markOop::unused_mark(). Any non-0 value suffices. |
1827 // set box->_displaced_header = markOopDesc::unused_mark(). Any non-0 value suffices. |
1845 // This is convenient but results a ST-before-CAS penalty. The following CAS suffers |
1828 // This is convenient but results a ST-before-CAS penalty. The following CAS suffers |
1846 // additional latency as we have another ST in the store buffer that must drain. |
1829 // additional latency as we have another ST in the store buffer that must drain. |
1847 |
1830 |
1848 if (EmitSync & 8192) { |
1831 if (EmitSync & 8192) { |
1849 movptr(Address(boxReg, 0), 3); // results in ST-before-CAS penalty |
1832 movptr(Address(boxReg, 0), 3); // results in ST-before-CAS penalty |
1851 movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] |
1834 movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] |
1852 movptr(tmpReg, NULL_WORD); // consider: xor vs mov |
1835 movptr(tmpReg, NULL_WORD); // consider: xor vs mov |
1853 if (os::is_MP()) { |
1836 if (os::is_MP()) { |
1854 lock(); |
1837 lock(); |
1855 } |
1838 } |
1856 cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1839 cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1857 } else |
1840 } else |
1858 if ((EmitSync & 128) == 0) { // avoid ST-before-CAS |
1841 if ((EmitSync & 128) == 0) { // avoid ST-before-CAS |
1859 movptr(scrReg, boxReg); |
1842 movptr(scrReg, boxReg); |
1860 movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] |
1843 movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2] |
1861 |
1844 |
1862 // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes |
1845 // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes |
1863 if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
1846 if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
1864 // prefetchw [eax + Offset(_owner)-2] |
1847 // prefetchw [eax + Offset(_owner)-2] |
1865 prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1848 prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1866 } |
1849 } |
1867 |
1850 |
1868 if ((EmitSync & 64) == 0) { |
1851 if ((EmitSync & 64) == 0) { |
1869 // Optimistic form: consider XORL tmpReg,tmpReg |
1852 // Optimistic form: consider XORL tmpReg,tmpReg |
1870 movptr(tmpReg, NULL_WORD); |
1853 movptr(tmpReg, NULL_WORD); |
1871 } else { |
1854 } else { |
1872 // Can suffer RTS->RTO upgrades on shared or cold $ lines |
1855 // Can suffer RTS->RTO upgrades on shared or cold $ lines |
1873 // Test-And-CAS instead of CAS |
1856 // Test-And-CAS instead of CAS |
1874 movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner |
1857 movptr(tmpReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); // rax, = m->_owner |
1875 testptr(tmpReg, tmpReg); // Locked ? |
1858 testptr(tmpReg, tmpReg); // Locked ? |
1876 jccb (Assembler::notZero, DONE_LABEL); |
1859 jccb (Assembler::notZero, DONE_LABEL); |
1877 } |
1860 } |
1878 |
1861 |
1879 // Appears unlocked - try to swing _owner from null to non-null. |
1862 // Appears unlocked - try to swing _owner from null to non-null. |
1885 // (rsp or the address of the box) into m->owner is harmless. |
1868 // (rsp or the address of the box) into m->owner is harmless. |
1886 // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. |
1869 // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. |
1887 if (os::is_MP()) { |
1870 if (os::is_MP()) { |
1888 lock(); |
1871 lock(); |
1889 } |
1872 } |
1890 cmpxchgptr(scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1873 cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1891 movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3 |
1874 movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3 |
1892 jccb (Assembler::notZero, DONE_LABEL); |
1875 jccb (Assembler::notZero, DONE_LABEL); |
1893 get_thread (scrReg); // beware: clobbers ICCs |
1876 get_thread (scrReg); // beware: clobbers ICCs |
1894 movptr(Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2), scrReg); |
1877 movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg); |
1895 xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success |
1878 xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success |
1896 |
1879 |
1897 // If the CAS fails we can either retry or pass control to the slow-path. |
1880 // If the CAS fails we can either retry or pass control to the slow-path. |
1898 // We use the latter tactic. |
1881 // We use the latter tactic. |
1899 // Pass the CAS result in the icc.ZFlag into DONE_LABEL |
1882 // Pass the CAS result in the icc.ZFlag into DONE_LABEL |
1906 movptr(boxReg, tmpReg); |
1889 movptr(boxReg, tmpReg); |
1907 |
1890 |
1908 // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes |
1891 // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes |
1909 if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
1892 if ((EmitSync & 2048) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
1910 // prefetchw [eax + Offset(_owner)-2] |
1893 // prefetchw [eax + Offset(_owner)-2] |
1911 prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1894 prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1912 } |
1895 } |
1913 |
1896 |
1914 if ((EmitSync & 64) == 0) { |
1897 if ((EmitSync & 64) == 0) { |
1915 // Optimistic form |
1898 // Optimistic form |
1916 xorptr (tmpReg, tmpReg); |
1899 xorptr (tmpReg, tmpReg); |
1917 } else { |
1900 } else { |
1918 // Can suffer RTS->RTO upgrades on shared or cold $ lines |
1901 // Can suffer RTS->RTO upgrades on shared or cold $ lines |
1919 movptr(tmpReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); // rax, = m->_owner |
1902 movptr(tmpReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); // rax, = m->_owner |
1920 testptr(tmpReg, tmpReg); // Locked ? |
1903 testptr(tmpReg, tmpReg); // Locked ? |
1921 jccb (Assembler::notZero, DONE_LABEL); |
1904 jccb (Assembler::notZero, DONE_LABEL); |
1922 } |
1905 } |
1923 |
1906 |
1924 // Appears unlocked - try to swing _owner from null to non-null. |
1907 // Appears unlocked - try to swing _owner from null to non-null. |
1949 |
1932 |
1950 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
1933 // Without cast to int32_t a movptr will destroy r10 which is typically obj |
1951 movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); |
1934 movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); |
1952 |
1935 |
1953 movptr (boxReg, tmpReg); |
1936 movptr (boxReg, tmpReg); |
1954 movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1937 movptr(tmpReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1955 testptr(tmpReg, tmpReg); |
1938 testptr(tmpReg, tmpReg); |
1956 jccb (Assembler::notZero, DONE_LABEL); |
1939 jccb (Assembler::notZero, DONE_LABEL); |
1957 |
1940 |
1958 // It's inflated and appears unlocked |
1941 // It's inflated and appears unlocked |
1959 if (os::is_MP()) { |
1942 if (os::is_MP()) { |
1960 lock(); |
1943 lock(); |
1961 } |
1944 } |
1962 cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
1945 cmpxchgptr(r15_thread, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
1963 // Intentional fall-through into DONE_LABEL ... |
1946 // Intentional fall-through into DONE_LABEL ... |
1964 #endif // _LP64 |
1947 #endif // _LP64 |
1965 |
1948 |
1966 #if INCLUDE_RTM_OPT |
1949 #if INCLUDE_RTM_OPT |
1967 } // use_rtm() |
1950 } // use_rtm() |
2100 // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. |
2082 // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. |
2101 #ifndef _LP64 |
2083 #ifndef _LP64 |
2102 get_thread (boxReg); |
2084 get_thread (boxReg); |
2103 if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
2085 if ((EmitSync & 4096) && VM_Version::supports_3dnow_prefetch() && os::is_MP()) { |
2104 // prefetchw [ebx + Offset(_owner)-2] |
2086 // prefetchw [ebx + Offset(_owner)-2] |
2105 prefetchw(Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2087 prefetchw(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2106 } |
2088 } |
2107 |
2089 |
2108 // Note that we could employ various encoding schemes to reduce |
2090 // Note that we could employ various encoding schemes to reduce |
2109 // the number of loads below (currently 4) to just 2 or 3. |
2091 // the number of loads below (currently 4) to just 2 or 3. |
2110 // Refer to the comments in synchronizer.cpp. |
2092 // Refer to the comments in synchronizer.cpp. |
2111 // In practice the chain of fetches doesn't seem to impact performance, however. |
2093 // In practice the chain of fetches doesn't seem to impact performance, however. |
2112 if ((EmitSync & 65536) == 0 && (EmitSync & 256)) { |
2094 if ((EmitSync & 65536) == 0 && (EmitSync & 256)) { |
2113 // Attempt to reduce branch density - AMD's branch predictor. |
2095 // Attempt to reduce branch density - AMD's branch predictor. |
2114 xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2096 xorptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2115 orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); |
2097 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); |
2116 orptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); |
2098 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); |
2117 orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); |
2099 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); |
2118 jccb (Assembler::notZero, DONE_LABEL); |
2100 jccb (Assembler::notZero, DONE_LABEL); |
2119 movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); |
2101 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); |
2120 jmpb (DONE_LABEL); |
2102 jmpb (DONE_LABEL); |
2121 } else { |
2103 } else { |
2122 xorptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2104 xorptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2123 orptr(boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); |
2105 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); |
2124 jccb (Assembler::notZero, DONE_LABEL); |
2106 jccb (Assembler::notZero, DONE_LABEL); |
2125 movptr(boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); |
2107 movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); |
2126 orptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); |
2108 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); |
2127 jccb (Assembler::notZero, CheckSucc); |
2109 jccb (Assembler::notZero, CheckSucc); |
2128 movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); |
2110 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); |
2129 jmpb (DONE_LABEL); |
2111 jmpb (DONE_LABEL); |
2130 } |
2112 } |
2131 |
2113 |
2132 // The Following code fragment (EmitSync & 65536) improves the performance of |
2114 // The Following code fragment (EmitSync & 65536) improves the performance of |
2133 // contended applications and contended synchronization microbenchmarks. |
2115 // contended applications and contended synchronization microbenchmarks. |
2171 // remains in M-state for the lock:orl. |
2153 // remains in M-state for the lock:orl. |
2172 // |
2154 // |
2173 // We currently use (3), although it's likely that switching to (2) |
2155 // We currently use (3), although it's likely that switching to (2) |
2174 // is correct for the future. |
2156 // is correct for the future. |
2175 |
2157 |
2176 movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), NULL_WORD); |
2158 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); |
2177 if (os::is_MP()) { |
2159 if (os::is_MP()) { |
2178 if (VM_Version::supports_sse2() && 1 == FenceInstruction) { |
2160 if (VM_Version::supports_sse2() && 1 == FenceInstruction) { |
2179 mfence(); |
2161 mfence(); |
2180 } else { |
2162 } else { |
2181 lock (); addptr(Address(rsp, 0), 0); |
2163 lock (); addptr(Address(rsp, 0), 0); |
2182 } |
2164 } |
2183 } |
2165 } |
2184 // Ratify _succ remains non-null |
2166 // Ratify _succ remains non-null |
2185 cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0); |
2167 cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), 0); |
2186 jccb (Assembler::notZero, LSuccess); |
2168 jccb (Assembler::notZero, LSuccess); |
2187 |
2169 |
2188 xorptr(boxReg, boxReg); // box is really EAX |
2170 xorptr(boxReg, boxReg); // box is really EAX |
2189 if (os::is_MP()) { lock(); } |
2171 if (os::is_MP()) { lock(); } |
2190 cmpxchgptr(rsp, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2172 cmpxchgptr(rsp, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2191 jccb (Assembler::notEqual, LSuccess); |
2173 jccb (Assembler::notEqual, LSuccess); |
2192 // Since we're low on registers we installed rsp as a placeholding in _owner. |
2174 // Since we're low on registers we installed rsp as a placeholding in _owner. |
2193 // Now install Self over rsp. This is safe as we're transitioning from |
2175 // Now install Self over rsp. This is safe as we're transitioning from |
2194 // non-null to non=null |
2176 // non-null to non=null |
2195 get_thread (boxReg); |
2177 get_thread (boxReg); |
2196 movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), boxReg); |
2178 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), boxReg); |
2197 // Intentional fall-through into LGoSlowPath ... |
2179 // Intentional fall-through into LGoSlowPath ... |
2198 |
2180 |
2199 bind (LGoSlowPath); |
2181 bind (LGoSlowPath); |
2200 orptr(boxReg, 1); // set ICC.ZF=0 to indicate failure |
2182 orptr(boxReg, 1); // set ICC.ZF=0 to indicate failure |
2201 jmpb (DONE_LABEL); |
2183 jmpb (DONE_LABEL); |
2226 if ((EmitSync & 65536) == 0) { |
2208 if ((EmitSync & 65536) == 0) { |
2227 bind (CheckSucc); |
2209 bind (CheckSucc); |
2228 } |
2210 } |
2229 #else // _LP64 |
2211 #else // _LP64 |
2230 // It's inflated |
2212 // It's inflated |
2231 movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2213 movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2232 xorptr(boxReg, r15_thread); |
2214 xorptr(boxReg, r15_thread); |
2233 orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)); |
2215 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); |
2234 jccb (Assembler::notZero, DONE_LABEL); |
2216 jccb (Assembler::notZero, DONE_LABEL); |
2235 movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)); |
2217 movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); |
2236 orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)); |
2218 orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); |
2237 jccb (Assembler::notZero, CheckSucc); |
2219 jccb (Assembler::notZero, CheckSucc); |
2238 movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD); |
2220 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD); |
2239 jmpb (DONE_LABEL); |
2221 jmpb (DONE_LABEL); |
2240 |
2222 |
2241 if ((EmitSync & 65536) == 0) { |
2223 if ((EmitSync & 65536) == 0) { |
2242 Label LSuccess, LGoSlowPath ; |
2224 Label LSuccess, LGoSlowPath ; |
2243 bind (CheckSucc); |
2225 bind (CheckSucc); |
2244 cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD); |
2226 cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD); |
2245 jccb (Assembler::zero, LGoSlowPath); |
2227 jccb (Assembler::zero, LGoSlowPath); |
2246 |
2228 |
2247 // I'd much rather use lock:andl m->_owner, 0 as it's faster than the |
2229 // I'd much rather use lock:andl m->_owner, 0 as it's faster than the |
2248 // the explicit ST;MEMBAR combination, but masm doesn't currently support |
2230 // the explicit ST;MEMBAR combination, but masm doesn't currently support |
2249 // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc |
2231 // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc |
2250 // are all faster when the write buffer is populated. |
2232 // are all faster when the write buffer is populated. |
2251 movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD); |
2233 movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t)NULL_WORD); |
2252 if (os::is_MP()) { |
2234 if (os::is_MP()) { |
2253 lock (); addl (Address(rsp, 0), 0); |
2235 lock (); addl (Address(rsp, 0), 0); |
2254 } |
2236 } |
2255 cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD); |
2237 cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), (int32_t)NULL_WORD); |
2256 jccb (Assembler::notZero, LSuccess); |
2238 jccb (Assembler::notZero, LSuccess); |
2257 |
2239 |
2258 movptr (boxReg, (int32_t)NULL_WORD); // box is really EAX |
2240 movptr (boxReg, (int32_t)NULL_WORD); // box is really EAX |
2259 if (os::is_MP()) { lock(); } |
2241 if (os::is_MP()) { lock(); } |
2260 cmpxchgptr(r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); |
2242 cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); |
2261 jccb (Assembler::notEqual, LSuccess); |
2243 jccb (Assembler::notEqual, LSuccess); |
2262 // Intentional fall-through into slow-path |
2244 // Intentional fall-through into slow-path |
2263 |
2245 |
2264 bind (LGoSlowPath); |
2246 bind (LGoSlowPath); |
2265 orl (boxReg, 1); // set ICC.ZF=0 to indicate failure |
2247 orl (boxReg, 1); // set ICC.ZF=0 to indicate failure |