// The spec is not clear whether the CFA is part of the saved state and tools differ in the
// behaviour, so explicitly set the CFA to avoid any ambiguity.
// The restored CFA state should match the CFA state during CFI_REMEMBER_STATE.
.macro CFI_RESTORE_STATE_AND_DEF_CFA reg, offset
.cfi_restore_state
.cfi_def_cfa \reg, \offset
.endm
.macro SAVE_ALL_ARGS_INCREASE_FRAME extra_space
// Reserve space for all argument registers, plus the extra space.
INCREASE_FRAME (ALL_ARGS_SIZE + \extra_space)
.macro LOAD_RUNTIME_INSTANCE reg
#if __has_feature(hwaddress_sanitizer)
#error "ART does not support HWASAN on RISC-V yet"
#else
la \reg, _ZN3art7Runtime9instance_E
#endif ld \reg, 0(\reg)
.endm
// We need to save callee-save GPRs on the stack as they may contain references, and must be
// visible to GC (unless the called method holds mutator lock and prevents GC from happening).
// FP callee-saves shall be preserved by whatever runtime function we call, so they do not need
// to be saved.
.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL
#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 8*(1 + 8 + 7 + 11 + 1))
#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(RISCV64) size not as expected."
#endif
// stack slot (0*8)(sp) is for ArtMethod*
// CFI note. This macro is used where the CFA rule is a dwarf expression, so adjustment of SP does
// not affect CFA computation. We also elide CFI descriptors for the argument registers, because
// they can be recovered from the stack in a debugging scenario.
.macro SPILL_ALL_ARGUMENTS
#if (FRAME_SIZE_SAVE_ARGS_ONLY != 128)
#error "FRAME_SIZE_SAVE_ARGS_ONLY(riscv64) not as expected."
#endif
addi sp, sp, -FRAME_SIZE_SAVE_ARGS_ONLY
sd a0, (8*0)(sp)
sd a1, (8*1)(sp)
sd a2, (8*2)(sp)
sd a3, (8*3)(sp)
sd a4, (8*4)(sp)
sd a5, (8*5)(sp)
sd a6, (8*6)(sp)
sd a7, (8*7)(sp)
fsd fa0, (8*8)(sp)
fsd fa1, (8*9)(sp)
fsd fa2, (8*10)(sp)
fsd fa3, (8*11)(sp)
fsd fa4, (8*12)(sp)
fsd fa5, (8*13)(sp)
fsd fa6, (8*14)(sp)
fsd fa7, (8*15)(sp)
.endm
// Macro that calls through to artDeliverPendingExceptionFromCode, where the pending exception is
// Thread::Current()->exception_ when the runtime method frame is ready.
.macro DELIVER_PENDING_EXCEPTION_FRAME_READY
mv a0, xSELF
call artDeliverPendingExceptionFromCode
call art_quick_do_long_jump // (Context*)
unimp // Unreached
.endm
// Macro that calls through to artDeliverPendingExceptionFromCode, where the pending exception is
// Thread::Current()->exception_.
.macro DELIVER_PENDING_EXCEPTION
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
DELIVER_PENDING_EXCEPTION_FRAME_READY
.endm
// Macro to emit a single LUI to load the given value while checking that the low 12 bits are zero.
.macro LUI_VALUE reg, value
.if (\value & 0xfff) != 0
.error "Cannot use LUI to materialize a value with some of the low 12 bits set."
.endif
lui \reg, (\value) >> 12
.endm
// Locking is needed for both managed code and JNI stubs.
.macro LOCK_OBJECT_FAST_PATH obj, slow_lock, can_be_null
// Use scratch registers T1-T6 as temporaries.
// Note: T0 is used as the argument register for `art_jni_lock_object` and passed as `obj`.
lw t2, THREAD_ID_OFFSET(xSELF)
.if \can_be_null
beqz \obj, \slow_lock
.endif
addi t1, \obj, MIRROR_OBJECT_LOCK_WORD_OFFSET // Exclusive load/store has no offset. 1:
// Note: The LR/SC sequence must be at most 16 instructions, so we cannot have the
// recursive locking in a slow-path as on other architectures.
lr.w.aq t3, (t1) // Acquire needed only in most common case.
LUI_VALUE t5, LOCK_WORD_GC_STATE_MASK_SHIFTED // Prepare mask for testing non-gc bits.
xor t4, t3, t2 // Prepare the value to store if unlocked
// (thread id, count of 0 and preserved read barrier bits),
// or prepare to compare thread id for recursive lock check
// (lock_word.ThreadId() ^ self->ThreadId()).
or t6, t5, t3 // Test the non-gc bits.
beq t6, t5, 2f // Check if unlocked.
// Check lock word state and thread id together,
LUI_VALUE \
t5, 0xffffffff ^ (LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED)
or t6, t5, t4
bne t6, t5, \slow_lock
LUI_VALUE t4, LOCK_WORD_THIN_LOCK_COUNT_ONE // Increment the recursive lock count.
addw t4, t3, t4
LUI_VALUE t5, LOCK_WORD_THIN_LOCK_COUNT_MASK_SHIFTED // Test the new thin lock count.
and t5, t4, t5
beqz t5, \slow_lock // Zero as the new count indicates overflow, go slow path. 2:
// Store the prepared value:
// - if unlocked, original lock word plus thread id,
// - if already locked, original lock word plus incremented lock count.
sc.w t3, t4, (t1)
bnez t3, 1b // If the store failed, retry.
ret
.endm
// Unlocking is needed for both managed code and JNI stubs.
.macro UNLOCK_OBJECT_FAST_PATH obj, slow_unlock, can_be_null
// Use scratch registers T1-T6 as temporaries.
// Note: T0 is used as the argument register for `art_jni_unlock_object` and passed as `obj`.
lw t2, THREAD_ID_OFFSET(xSELF)
.if \can_be_null
beqz \obj, \slow_unlock
.endif
addi t1, \obj, MIRROR_OBJECT_LOCK_WORD_OFFSET // Exclusive load/store has no offset. 1:
// Note: Without read barriers, we could do plain LW here but there is no store-release
// other than SC on riscv64, so we do this with LR/SC for all cofigurations.
// Note: The LR/SC sequence must be at most 16 instructions, so we cannot have the
// recursive unlocking in a slow-path as on other architectures.
lr.w t3, (t1)
LUI_VALUE t5, LOCK_WORD_GC_STATE_MASK_SHIFTED // Prepare mask for testing non-gc bits.
xor t4, t3, t2 // Prepare the value to store if simply locked
// (mostly 0s, and preserved read barrier bits),
// or prepare to compare thread id for recursive lock check
// (lock_word.ThreadId() ^ self->ThreadId()).
or t6, t5, t4 // Test the non-gc bits.
beq t6, t5, 2f // Simply locked by this thread?
// Check lock word state and thread id together.
LUI_VALUE \
t5, 0xffffffff ^ (LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED)
or t6, t5, t4
bne t6, t5, \slow_unlock
LUI_VALUE t4, LOCK_WORD_THIN_LOCK_COUNT_ONE // Decrement the recursive lock count.
subw t4, t3, t4 2:
// Store the prepared value:
// - if simply locked, original lock word with removed thread id,
// - if recursively locked, original lock word plus decremented lock count.
sc.w.rl t3, t4, (t1) // Need to use atomic instructions for read barrier.
bnez t3, 1b // If the store failed, retry.
ret
.endm
// Macros to branch based on the value of a specific bit.
.macro BRANCH_IF_BIT_CLEAR tmp, reg, bit, dest
slli \tmp, \reg, (63 - \bit) // tested bit => sign bit
bgez \tmp, \dest
.endm
.macro BRANCH_IF_BIT_SET tmp, reg, bit, dest
slli \tmp, \reg, (63 - \bit) // tested bit => sign bit
bltz \tmp, \dest
.endm
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.