mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-12 19:35:24 +00:00
173 lines
5.6 KiB
C++
173 lines
5.6 KiB
C++
/*
|
|
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*
|
|
*/
|
|
|
|
#include "precompiled.hpp"
|
|
#include "asm/assembler.hpp"
|
|
#include "asm/assembler.inline.hpp"
|
|
#include "opto/c2_MacroAssembler.hpp"
|
|
#include "runtime/basicLock.hpp"
|
|
|
|
// TODO: 8 bytes at a time? pre-fetch?
|
|
// Compare char[] arrays aligned to 4 bytes.
|
|
void C2_MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
|
Register limit, Register result,
|
|
Register chr1, Register chr2, Label& Ldone) {
|
|
Label Lvector, Lloop;
|
|
|
|
// if (ary1 == ary2)
|
|
// return true;
|
|
cmpoop(ary1, ary2);
|
|
b(Ldone, eq);
|
|
|
|
// Note: limit contains number of bytes (2*char_elements) != 0.
|
|
tst(limit, 0x2); // trailing character ?
|
|
b(Lvector, eq);
|
|
|
|
// compare the trailing char
|
|
sub(limit, limit, sizeof(jchar));
|
|
ldrh(chr1, Address(ary1, limit));
|
|
ldrh(chr2, Address(ary2, limit));
|
|
cmp(chr1, chr2);
|
|
mov(result, 0, ne); // not equal
|
|
b(Ldone, ne);
|
|
|
|
// only one char ?
|
|
tst(limit, limit);
|
|
mov(result, 1, eq);
|
|
b(Ldone, eq);
|
|
|
|
// word by word compare, don't need alignment check
|
|
bind(Lvector);
|
|
|
|
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
|
add(ary1, limit, ary1);
|
|
add(ary2, limit, ary2);
|
|
neg(limit, limit);
|
|
|
|
bind(Lloop);
|
|
ldr_u32(chr1, Address(ary1, limit));
|
|
ldr_u32(chr2, Address(ary2, limit));
|
|
cmp_32(chr1, chr2);
|
|
mov(result, 0, ne); // not equal
|
|
b(Ldone, ne);
|
|
adds(limit, limit, 2*sizeof(jchar));
|
|
b(Lloop, ne);
|
|
|
|
// Caller should set it:
|
|
// mov(result_reg, 1); //equal
|
|
}
|
|
|
|
void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
|
|
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
|
assert_different_registers(Roop, Rbox, Rscratch, Rscratch2);
|
|
|
|
Label fast_lock, done;
|
|
|
|
if (DiagnoseSyncOnValueBasedClasses != 0) {
|
|
load_klass(Rscratch, Roop);
|
|
ldrb(Rscratch, Address(Rscratch, Klass::misc_flags_offset()));
|
|
tst(Rscratch, KlassFlags::_misc_is_value_based_class);
|
|
b(done, ne);
|
|
}
|
|
|
|
if (LockingMode == LM_LIGHTWEIGHT) {
|
|
|
|
lightweight_lock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
|
1 /* savemask (save t1) */, done);
|
|
|
|
// Success: set Z
|
|
cmp(Roop, Roop);
|
|
|
|
} else if (LockingMode == LM_LEGACY) {
|
|
|
|
Register Rmark = Rscratch2;
|
|
|
|
ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
|
|
tst(Rmark, markWord::unlocked_value);
|
|
b(fast_lock, ne);
|
|
|
|
// Check for recursive lock
|
|
// See comments in InterpreterMacroAssembler::lock_object for
|
|
// explanations on the fast recursive locking check.
|
|
// -1- test low 2 bits
|
|
movs(Rscratch, AsmOperand(Rmark, lsl, 30));
|
|
// -2- test (hdr - SP) if the low two bits are 0
|
|
sub(Rscratch, Rmark, SP, eq);
|
|
movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
|
|
// If still 'eq' then recursive locking OK
|
|
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
|
|
str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
|
b(done);
|
|
|
|
bind(fast_lock);
|
|
str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
|
|
|
bool allow_fallthrough_on_failure = true;
|
|
bool one_shot = true;
|
|
cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
|
}
|
|
|
|
bind(done);
|
|
|
|
// At this point flags are set as follows:
|
|
// EQ -> Success
|
|
// NE -> Failure, branch to slow path
|
|
}
|
|
|
|
void C2_MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
|
|
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
|
assert_different_registers(Roop, Rbox, Rscratch, Rscratch2);
|
|
|
|
Label done;
|
|
|
|
if (LockingMode == LM_LIGHTWEIGHT) {
|
|
|
|
lightweight_unlock(Roop /* obj */, Rbox /* t1 */, Rscratch /* t2 */, Rscratch2 /* t3 */,
|
|
1 /* savemask (save t1) */, done);
|
|
|
|
cmp(Roop, Roop); // Success: Set Z
|
|
// Fall through
|
|
|
|
} else if (LockingMode == LM_LEGACY) {
|
|
|
|
Register Rmark = Rscratch2;
|
|
|
|
// Find the lock address and load the displaced header from the stack.
|
|
ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
|
// If hdr is null, we've got recursive locking and there's nothing more to do
|
|
cmp(Rmark, 0);
|
|
b(done, eq);
|
|
|
|
// Restore the object header
|
|
bool allow_fallthrough_on_failure = true;
|
|
bool one_shot = true;
|
|
cas_for_lock_release(Rbox, Rmark, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
|
}
|
|
bind(done);
|
|
|
|
// At this point flags are set as follows:
|
|
// EQ -> Success
|
|
// NE -> Failure, branch to slow path
|
|
}
|