diff options
-rw-r--r-- | runtime/Android.bp | 5 | ||||
-rw-r--r-- | runtime/arch/arm/jni_entrypoints_arm.S | 41 | ||||
-rw-r--r-- | runtime/arch/arm/native_entrypoints_arm.S | 87 | ||||
-rw-r--r-- | runtime/arch/arm/quick_entrypoints_arm.S | 15 | ||||
-rw-r--r-- | runtime/arch/arm64/asm_support_arm64.S | 41 | ||||
-rw-r--r-- | runtime/arch/arm64/jni_entrypoints_arm64.S | 76 | ||||
-rw-r--r-- | runtime/arch/arm64/native_entrypoints_arm64.S | 86 | ||||
-rw-r--r-- | runtime/arch/arm64/quick_entrypoints_arm64.S | 27 | ||||
-rw-r--r-- | runtime/arch/riscv64/asm_support_riscv64.S | 55 | ||||
-rw-r--r-- | runtime/arch/riscv64/jni_entrypoints_riscv64.S | 94 | ||||
-rw-r--r-- | runtime/arch/riscv64/native_entrypoints_riscv64.S | 87 | ||||
-rw-r--r-- | runtime/arch/riscv64/quick_entrypoints_riscv64.S | 20 | ||||
-rw-r--r-- | runtime/arch/x86/jni_entrypoints_x86.S | 29 | ||||
-rw-r--r-- | runtime/arch/x86/native_entrypoints_x86.S | 82 | ||||
-rw-r--r-- | runtime/arch/x86/quick_entrypoints_x86.S | 23 | ||||
-rw-r--r-- | runtime/arch/x86_64/jni_entrypoints_x86_64.S | 60 | ||||
-rw-r--r-- | runtime/arch/x86_64/native_entrypoints_x86_64.S | 105 | ||||
-rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 15 |
18 files changed, 553 insertions, 395 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index ff9870e908..cf5e363877 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -479,6 +479,7 @@ cc_defaults { "arch/arm/jni_entrypoints_arm.S", "arch/arm/memcmp16_arm.S", "arch/arm/quick_entrypoints_arm.S", + "arch/arm/native_entrypoints_arm.S", "arch/arm/quick_entrypoints_cc_arm.cc", "arch/arm/thread_arm.cc", "arch/arm/fault_handler_arm.cc", @@ -493,6 +494,7 @@ cc_defaults { "arch/arm64/jni_entrypoints_arm64.S", "arch/arm64/memcmp16_arm64.S", "arch/arm64/quick_entrypoints_arm64.S", + "arch/arm64/native_entrypoints_arm64.S", "arch/arm64/thread_arm64.cc", "monitor_pool.cc", "arch/arm64/fault_handler_arm64.cc", @@ -506,6 +508,7 @@ cc_defaults { "arch/riscv64/fault_handler_riscv64.cc", "arch/riscv64/jni_entrypoints_riscv64.S", "arch/riscv64/quick_entrypoints_riscv64.S", + "arch/riscv64/native_entrypoints_riscv64.S", "arch/riscv64/thread_riscv64.cc", "interpreter/mterp/nterp.cc", "monitor_pool.cc", @@ -520,6 +523,7 @@ cc_defaults { "arch/x86/jni_entrypoints_x86.S", "arch/x86/memcmp16_x86.S", "arch/x86/quick_entrypoints_x86.S", + "arch/x86/native_entrypoints_x86.S", "arch/x86/thread_x86.cc", "arch/x86/fault_handler_x86.cc", ], @@ -541,6 +545,7 @@ cc_defaults { "arch/x86_64/jni_entrypoints_x86_64.S", "arch/x86_64/memcmp16_x86_64.S", "arch/x86_64/quick_entrypoints_x86_64.S", + "arch/x86_64/native_entrypoints_x86_64.S", "arch/x86_64/thread_x86_64.cc", "monitor_pool.cc", "arch/x86/fault_handler_x86.cc", diff --git a/runtime/arch/arm/jni_entrypoints_arm.S b/runtime/arch/arm/jni_entrypoints_arm.S index 8c80c338dd..8b57983832 100644 --- a/runtime/arch/arm/jni_entrypoints_arm.S +++ b/runtime/arch/arm/jni_entrypoints_arm.S @@ -84,47 +84,6 @@ END \name .endm /* - * Jni dlsym lookup stub. - */ - .extern artFindNativeMethod - .extern artFindNativeMethodRunnable -ENTRY art_jni_dlsym_lookup_stub - push {r0, r1, r2, r3, lr} @ spill regs - .cfi_adjust_cfa_offset 20 - .cfi_rel_offset lr, 16 - sub sp, #12 @ pad stack pointer to align frame - .cfi_adjust_cfa_offset 12 - - mov r0, rSELF @ pass Thread::Current() - // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() - // for @FastNative or @CriticalNative. - ldr ip, [r0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame - bic ip, #TAGGED_JNI_SP_MASK // ArtMethod** sp - ldr ip, [ip] // ArtMethod* method - ldr ip, [ip, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags - tst ip, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) - bne .Llookup_stub_fast_or_critical_native - blx artFindNativeMethod - b .Llookup_stub_continue -.Llookup_stub_fast_or_critical_native: - blx artFindNativeMethodRunnable -.Llookup_stub_continue: - mov r12, r0 @ save result in r12 - - add sp, #12 @ restore stack pointer - .cfi_adjust_cfa_offset -12 - CFI_REMEMBER_STATE - cbz r0, 1f @ is method code null? - pop {r0, r1, r2, r3, lr} @ restore regs - .cfi_adjust_cfa_offset -20 - .cfi_restore lr - bx r12 @ if non-null, tail call to method's code -1: - CFI_RESTORE_STATE_AND_DEF_CFA sp, 20 - pop {r0, r1, r2, r3, pc} @ restore regs and return to caller to handle exception -END art_jni_dlsym_lookup_stub - - /* * Jni dlsym lookup stub for @CriticalNative. */ ENTRY art_jni_dlsym_lookup_critical_stub diff --git a/runtime/arch/arm/native_entrypoints_arm.S b/runtime/arch/arm/native_entrypoints_arm.S new file mode 100644 index 0000000000..1666dc8d4b --- /dev/null +++ b/runtime/arch/arm/native_entrypoints_arm.S @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm_support_arm.S" +#include "interpreter/cfi_asm_support.h" + +/* + * This file contains all native entrypoints that are called using the native ABI and do not + * transition to the quick ABI. For example: the switch interpreter (using the native ABI) directly + * calls ExecuteSwitchImplAsm and this code will always return back to the switch interpreter, + * again using the native ABI. Because of this behaviour ExecuteSwitchImplAsm should be included in + * this file. This is done so these native entrypoints can be compiled independently to quick + * entrypoints for cases when the kRuntimeISA and kRuntimeQuickCodeISA do not match. + * + * See comment on StackType (thread.h) for definitions and examples of quick ABI/code and + * native ABI/code. + */ + +// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. +// Argument 0: r0: The context pointer for ExecuteSwitchImpl. +// Argument 1: r1: Pointer to the templated ExecuteSwitchImpl to call. +// Argument 2: r2: The value of DEX PC (memory address of the methods bytecode). +ENTRY ExecuteSwitchImplAsm + push {r4, lr} // 2 words of callee saves. + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset r4, 0 + .cfi_rel_offset lr, 4 + mov r4, r2 // r4 = DEX PC + CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* r0 */, 4 /* r4 */, 0) + blx r1 // Call the wrapped method. + pop {r4, pc} +END ExecuteSwitchImplAsm + + /* + * Jni dlsym lookup stub. + */ + .extern artFindNativeMethod + .extern artFindNativeMethodRunnable +ENTRY art_jni_dlsym_lookup_stub + push {r0, r1, r2, r3, lr} @ spill regs + .cfi_adjust_cfa_offset 20 + .cfi_rel_offset lr, 16 + sub sp, #12 @ pad stack pointer to align frame + .cfi_adjust_cfa_offset 12 + + mov r0, rSELF @ pass Thread::Current() + // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() + // for @FastNative or @CriticalNative. + ldr ip, [r0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame + bic ip, #TAGGED_JNI_SP_MASK // ArtMethod** sp + ldr ip, [ip] // ArtMethod* method + ldr ip, [ip, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags + tst ip, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) + bne .Llookup_stub_fast_or_critical_native + blx artFindNativeMethod + b .Llookup_stub_continue +.Llookup_stub_fast_or_critical_native: + blx artFindNativeMethodRunnable +.Llookup_stub_continue: + mov r12, r0 @ save result in r12 + + add sp, #12 @ restore stack pointer + .cfi_adjust_cfa_offset -12 + CFI_REMEMBER_STATE + cbz r0, 1f @ is method code null? + pop {r0, r1, r2, r3, lr} @ restore regs + .cfi_adjust_cfa_offset -20 + .cfi_restore lr + bx r12 @ if non-null, tail call to method's code +1: + CFI_RESTORE_STATE_AND_DEF_CFA sp, 20 + pop {r0, r1, r2, r3, pc} @ restore regs and return to caller to handle exception +END art_jni_dlsym_lookup_stub + diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S index 2621918d09..ddfe70dc51 100644 --- a/runtime/arch/arm/quick_entrypoints_arm.S +++ b/runtime/arch/arm/quick_entrypoints_arm.S @@ -2354,21 +2354,6 @@ ENTRY art_quick_invoke_custom RETURN_OR_DELIVER_PENDING_EXCEPTION_REG r2 END art_quick_invoke_custom -// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. -// Argument 0: r0: The context pointer for ExecuteSwitchImpl. -// Argument 1: r1: Pointer to the templated ExecuteSwitchImpl to call. -// Argument 2: r2: The value of DEX PC (memory address of the methods bytecode). -ENTRY ExecuteSwitchImplAsm - push {r4, lr} // 2 words of callee saves. - .cfi_adjust_cfa_offset 8 - .cfi_rel_offset r4, 0 - .cfi_rel_offset lr, 4 - mov r4, r2 // r4 = DEX PC - CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* r0 */, 4 /* r4 */, 0) - blx r1 // Call the wrapped method. - pop {r4, pc} -END ExecuteSwitchImplAsm - // r0 contains the class, r4 contains the inline cache. We can use ip as temporary. ENTRY art_quick_update_inline_cache #if (INLINE_CACHE_SIZE != 5) diff --git a/runtime/arch/arm64/asm_support_arm64.S b/runtime/arch/arm64/asm_support_arm64.S index 56ce037b1a..ae965303b9 100644 --- a/runtime/arch/arm64/asm_support_arm64.S +++ b/runtime/arch/arm64/asm_support_arm64.S @@ -152,6 +152,13 @@ SAVE_TWO_REGS_BASE sp, \reg1, \reg2, \offset .endm +.macro SAVE_TWO_REGS_INCREASE_FRAME reg1, reg2, frame_adjustment + stp \reg1, \reg2, [sp, #-(\frame_adjustment)]! + .cfi_adjust_cfa_offset (\frame_adjustment) + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 +.endm + .macro RESTORE_TWO_REGS_BASE base, reg1, reg2, offset ldp \reg1, \reg2, [\base, #(\offset)] .cfi_restore \reg1 @@ -162,6 +169,40 @@ RESTORE_TWO_REGS_BASE sp, \reg1, \reg2, \offset .endm +.macro RESTORE_TWO_REGS_DECREASE_FRAME reg1, reg2, frame_adjustment + ldp \reg1, \reg2, [sp], #(\frame_adjustment) + .cfi_restore \reg1 + .cfi_restore \reg2 + .cfi_adjust_cfa_offset -(\frame_adjustment) +.endm + +#define ALL_ARGS_SIZE (/*x0-x7*/ 8 * 8 + /*d0-d7*/ 8 * 8) + +.macro SAVE_ALL_ARGS_INCREASE_FRAME extra_space + // Save register args x0-x7, d0-d7 and return address. + stp x0, x1, [sp, #-(ALL_ARGS_SIZE + \extra_space)]! + .cfi_adjust_cfa_offset (ALL_ARGS_SIZE + \extra_space) + stp x2, x3, [sp, #16] + stp x4, x5, [sp, #32] + stp x6, x7, [sp, #48] + stp d0, d1, [sp, #64] + stp d2, d3, [sp, #80] + stp d4, d5, [sp, #96] + stp d6, d7, [sp, #112] +.endm + +.macro RESTORE_ALL_ARGS_DECREASE_FRAME extra_space + ldp x2, x3, [sp, #16] + ldp x4, x5, [sp, #32] + ldp x6, x7, [sp, #48] + ldp d0, d1, [sp, #64] + ldp d2, d3, [sp, #80] + ldp d4, d5, [sp, #96] + ldp d6, d7, [sp, #112] + ldp x0, x1, [sp], #(ALL_ARGS_SIZE + \extra_space) + .cfi_adjust_cfa_offset -(ALL_ARGS_SIZE + \extra_space) +.endm + .macro LOAD_RUNTIME_INSTANCE reg #if __has_feature(hwaddress_sanitizer) adrp \reg, :pg_hi21_nc:_ZN3art7Runtime9instance_E diff --git a/runtime/arch/arm64/jni_entrypoints_arm64.S b/runtime/arch/arm64/jni_entrypoints_arm64.S index 2bfb02d062..a25cbc5a45 100644 --- a/runtime/arch/arm64/jni_entrypoints_arm64.S +++ b/runtime/arch/arm64/jni_entrypoints_arm64.S @@ -16,33 +16,6 @@ #include "asm_support_arm64.S" -#define ALL_ARGS_SIZE (/*x0-x7*/ 8 * 8 + /*d0-d7*/ 8 * 8) - -.macro SAVE_ALL_ARGS_INCREASE_FRAME extra_space - // Save register args x0-x7, d0-d7 and return address. - stp x0, x1, [sp, #-(ALL_ARGS_SIZE + \extra_space)]! - .cfi_adjust_cfa_offset (ALL_ARGS_SIZE + \extra_space) - stp x2, x3, [sp, #16] - stp x4, x5, [sp, #32] - stp x6, x7, [sp, #48] - stp d0, d1, [sp, #64] - stp d2, d3, [sp, #80] - stp d4, d5, [sp, #96] - stp d6, d7, [sp, #112] -.endm - -.macro RESTORE_ALL_ARGS_DECREASE_FRAME extra_space - ldp x2, x3, [sp, #16] - ldp x4, x5, [sp, #32] - ldp x6, x7, [sp, #48] - ldp d0, d1, [sp, #64] - ldp d2, d3, [sp, #80] - ldp d4, d5, [sp, #96] - ldp d6, d7, [sp, #112] - ldp x0, x1, [sp], #(ALL_ARGS_SIZE + \extra_space) - .cfi_adjust_cfa_offset -(ALL_ARGS_SIZE + \extra_space) -.endm - .macro JNI_SAVE_MANAGED_ARGS_TRAMPOLINE name, cxx_name, arg1 = "none" .extern \cxx_name ENTRY \name @@ -87,56 +60,17 @@ END \name .endm /* - * Jni dlsym lookup stub. - */ - .extern artFindNativeMethod - .extern artFindNativeMethodRunnable -ENTRY art_jni_dlsym_lookup_stub - // spill regs. - SAVE_ALL_ARGS_INCREASE_FRAME 2 * 8 - stp x29, x30, [sp, ALL_ARGS_SIZE] - .cfi_rel_offset x29, ALL_ARGS_SIZE - .cfi_rel_offset x30, ALL_ARGS_SIZE + 8 - add x29, sp, ALL_ARGS_SIZE - - mov x0, xSELF // pass Thread::Current() - // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() - // for @FastNative or @CriticalNative. - ldr xIP0, [x0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame - bic xIP0, xIP0, #TAGGED_JNI_SP_MASK // ArtMethod** sp - ldr xIP0, [xIP0] // ArtMethod* method - ldr xIP0, [xIP0, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags - mov xIP1, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) - tst xIP0, xIP1 - b.ne .Llookup_stub_fast_or_critical_native - bl artFindNativeMethod - b .Llookup_stub_continue - .Llookup_stub_fast_or_critical_native: - bl artFindNativeMethodRunnable -.Llookup_stub_continue: - mov x17, x0 // store result in scratch reg. - - // load spill regs. - ldp x29, x30, [sp, #ALL_ARGS_SIZE] - .cfi_restore x29 - .cfi_restore x30 - RESTORE_ALL_ARGS_DECREASE_FRAME 2 * 8 - - cbz x17, 1f // is method code null ? - br x17 // if non-null, tail call to method's code. - -1: - ret // restore regs and return to caller to handle exception. -END art_jni_dlsym_lookup_stub - - /* * Jni dlsym lookup stub for @CriticalNative. */ ENTRY art_jni_dlsym_lookup_critical_stub // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is x15. // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub. - tbnz x15, #0, art_jni_dlsym_lookup_stub + // Note: 'tbnz' doesn't have enough range (+/-32KB) to reach art_jni_dlsym_lookup_stub so 'b' + // (+/-128MB) is used instead. + tbz x15, #0, .Lcritical_not_generic_jni + b art_jni_dlsym_lookup_stub +.Lcritical_not_generic_jni: // Save args, the hidden arg and caller PC. No CFI needed for args and the hidden arg. SAVE_ALL_ARGS_INCREASE_FRAME 2 * 8 stp x15, lr, [sp, #ALL_ARGS_SIZE] diff --git a/runtime/arch/arm64/native_entrypoints_arm64.S b/runtime/arch/arm64/native_entrypoints_arm64.S new file mode 100644 index 0000000000..747e572c97 --- /dev/null +++ b/runtime/arch/arm64/native_entrypoints_arm64.S @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm_support_arm64.S" +#include "interpreter/cfi_asm_support.h" + +/* + * This file contains all native entrypoints that are called using the native ABI and do not + * transition to the quick ABI. For example: the switch interpreter (using the native ABI) directly + * calls ExecuteSwitchImplAsm and this code will always return back to the switch interpreter, + * again using the native ABI. Because of this behaviour ExecuteSwitchImplAsm should be included in + * this file. This is done so these native entrypoints can be compiled independently to quick + * entrypoints for cases when the kRuntimeISA and kRuntimeQuickCodeISA do not match. + * + * See comment on StackType (thread.h) for definitions and examples of quick ABI/code and + * native ABI/code. + */ + +// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. +// Argument 0: x0: The context pointer for ExecuteSwitchImpl. +// Argument 1: x1: Pointer to the templated ExecuteSwitchImpl to call. +// Argument 2: x2: The value of DEX PC (memory address of the methods bytecode). +ENTRY ExecuteSwitchImplAsm + SAVE_TWO_REGS_INCREASE_FRAME x19, xLR, 16 + mov x19, x2 // x19 = DEX PC + CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* x0 */, 19 /* x19 */, 0) + blr x1 // Call the wrapped method. + RESTORE_TWO_REGS_DECREASE_FRAME x19, xLR, 16 + ret +END ExecuteSwitchImplAsm + + /* + * Jni dlsym lookup stub. + */ + .extern artFindNativeMethod + .extern artFindNativeMethodRunnable +ENTRY art_jni_dlsym_lookup_stub + // spill regs. + SAVE_ALL_ARGS_INCREASE_FRAME 2 * 8 + stp x29, x30, [sp, ALL_ARGS_SIZE] + .cfi_rel_offset x29, ALL_ARGS_SIZE + .cfi_rel_offset x30, ALL_ARGS_SIZE + 8 + add x29, sp, ALL_ARGS_SIZE + + mov x0, xSELF // pass Thread::Current() + // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() + // for @FastNative or @CriticalNative. + ldr xIP0, [x0, #THREAD_TOP_QUICK_FRAME_OFFSET] // uintptr_t tagged_quick_frame + bic xIP0, xIP0, #TAGGED_JNI_SP_MASK // ArtMethod** sp + ldr xIP0, [xIP0] // ArtMethod* method + ldr xIP0, [xIP0, #ART_METHOD_ACCESS_FLAGS_OFFSET] // uint32_t access_flags + mov xIP1, #(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) + tst xIP0, xIP1 + b.ne .Llookup_stub_fast_or_critical_native + bl artFindNativeMethod + b .Llookup_stub_continue + .Llookup_stub_fast_or_critical_native: + bl artFindNativeMethodRunnable +.Llookup_stub_continue: + mov x17, x0 // store result in scratch reg. + + // load spill regs. + ldp x29, x30, [sp, #ALL_ARGS_SIZE] + .cfi_restore x29 + .cfi_restore x30 + RESTORE_ALL_ARGS_DECREASE_FRAME 2 * 8 + + cbz x17, 1f // is method code null ? + br x17 // if non-null, tail call to method's code. + +1: + ret // restore regs and return to caller to handle exception. +END art_jni_dlsym_lookup_stub diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index 3bb3b693d9..90ea19e988 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -32,20 +32,6 @@ .cfi_adjust_cfa_offset -(\frame_adjustment) .endm -.macro SAVE_TWO_REGS_INCREASE_FRAME reg1, reg2, frame_adjustment - stp \reg1, \reg2, [sp, #-(\frame_adjustment)]! - .cfi_adjust_cfa_offset (\frame_adjustment) - .cfi_rel_offset \reg1, 0 - .cfi_rel_offset \reg2, 8 -.endm - -.macro RESTORE_TWO_REGS_DECREASE_FRAME reg1, reg2, frame_adjustment - ldp \reg1, \reg2, [sp], #(\frame_adjustment) - .cfi_restore \reg1 - .cfi_restore \reg2 - .cfi_adjust_cfa_offset -(\frame_adjustment) -.endm - .macro POP_SAVE_REFS_ONLY_FRAME DECREASE_FRAME 96 .endm @@ -2467,19 +2453,6 @@ ENTRY art_quick_invoke_custom RETURN_OR_DELIVER_PENDING_EXCEPTION END art_quick_invoke_custom -// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. -// Argument 0: x0: The context pointer for ExecuteSwitchImpl. -// Argument 1: x1: Pointer to the templated ExecuteSwitchImpl to call. -// Argument 2: x2: The value of DEX PC (memory address of the methods bytecode). -ENTRY ExecuteSwitchImplAsm - SAVE_TWO_REGS_INCREASE_FRAME x19, xLR, 16 - mov x19, x2 // x19 = DEX PC - CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* x0 */, 19 /* x19 */, 0) - blr x1 // Call the wrapped method. - RESTORE_TWO_REGS_DECREASE_FRAME x19, xLR, 16 - ret -END ExecuteSwitchImplAsm - // x0 contains the class, x8 contains the inline cache. x9-x15 can be used. ENTRY art_quick_update_inline_cache #if (INLINE_CACHE_SIZE != 5) diff --git a/runtime/arch/riscv64/asm_support_riscv64.S b/runtime/arch/riscv64/asm_support_riscv64.S index f8e3b488b5..accdb0510a 100644 --- a/runtime/arch/riscv64/asm_support_riscv64.S +++ b/runtime/arch/riscv64/asm_support_riscv64.S @@ -161,6 +161,61 @@ .endm +// 8 argument GPRS: a0 - a7 and 8 argument FPRs: fa0 - fa7 +#define ALL_ARGS_SIZE (8 * (8 + 8)) + + +.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) + + // Argument GPRs a0 - a7. + 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) + + // Argument FPRs fa0 - fa7. + 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 RESTORE_ALL_ARGS_DECREASE_FRAME extra_space + // Argument GPRs a0 - a7. + ld a0, (8*0)(sp) + ld a1, (8*1)(sp) + ld a2, (8*2)(sp) + ld a3, (8*3)(sp) + ld a4, (8*4)(sp) + ld a5, (8*5)(sp) + ld a6, (8*6)(sp) + ld a7, (8*7)(sp) + + // Argument FPRs fa0 - fa7. + fld fa0, (8*8)(sp) + fld fa1, (8*9)(sp) + fld fa2, (8*10)(sp) + fld fa3, (8*11)(sp) + fld fa4, (8*12)(sp) + fld fa5, (8*13)(sp) + fld fa6, (8*14)(sp) + fld fa7, (8*15)(sp) + + DECREASE_FRAME (ALL_ARGS_SIZE + \extra_space) +.endm + + .macro LOAD_RUNTIME_INSTANCE reg #if __has_feature(hwaddress_sanitizer) #error "ART does not support HWASAN on RISC-V yet" diff --git a/runtime/arch/riscv64/jni_entrypoints_riscv64.S b/runtime/arch/riscv64/jni_entrypoints_riscv64.S index c1f855b4bf..017ce8c3f0 100644 --- a/runtime/arch/riscv64/jni_entrypoints_riscv64.S +++ b/runtime/arch/riscv64/jni_entrypoints_riscv64.S @@ -17,61 +17,6 @@ #include "asm_support_riscv64.S" -// 8 argument GPRS: a0 - a7 and 8 argument FPRs: fa0 - fa7 -#define ALL_ARGS_SIZE (8 * (8 + 8)) - - -.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) - - // Argument GPRs a0 - a7. - 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) - - // Argument FPRs fa0 - fa7. - 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 RESTORE_ALL_ARGS_DECREASE_FRAME extra_space - // Argument GPRs a0 - a7. - ld a0, (8*0)(sp) - ld a1, (8*1)(sp) - ld a2, (8*2)(sp) - ld a3, (8*3)(sp) - ld a4, (8*4)(sp) - ld a5, (8*5)(sp) - ld a6, (8*6)(sp) - ld a7, (8*7)(sp) - - // Argument FPRs fa0 - fa7. - fld fa0, (8*8)(sp) - fld fa1, (8*9)(sp) - fld fa2, (8*10)(sp) - fld fa3, (8*11)(sp) - fld fa4, (8*12)(sp) - fld fa5, (8*13)(sp) - fld fa6, (8*14)(sp) - fld fa7, (8*15)(sp) - - DECREASE_FRAME (ALL_ARGS_SIZE + \extra_space) -.endm - - .macro JNI_SAVE_MANAGED_ARGS_TRAMPOLINE name, cxx_name, arg1 = "none" .extern \cxx_name ENTRY \name @@ -115,45 +60,6 @@ END \name .endm -// JNI dlsym lookup stub. -.extern artFindNativeMethod -.extern artFindNativeMethodRunnable -ENTRY art_jni_dlsym_lookup_stub - SAVE_ALL_ARGS_INCREASE_FRAME 2*8 - SAVE_GPR fp, (ALL_ARGS_SIZE + 0) - SAVE_GPR ra, (ALL_ARGS_SIZE + 8) - add fp, sp, ALL_ARGS_SIZE - - // Call artFindNativeMethod for normal native. - // Call artFindNativeMethodRunnable for @FastNative or @CriticalNative. - // Both functions have a single argument: Thread::Current() in a0. - mv a0, xSELF - ld t0, THREAD_TOP_QUICK_FRAME_OFFSET(a0) // uintptr_t tagged_quick_frame - andi t0, t0, ~TAGGED_JNI_SP_MASK // ArtMethod** sp - ld t0, (t0) // ArtMethod* method - lw t0, ART_METHOD_ACCESS_FLAGS_OFFSET(t0) // uint32_t access_flags - li t1, (ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) - and t0, t0, t1 - bnez t0, .Llookup_stub_fast_or_critical_native - call artFindNativeMethod - j .Llookup_stub_continue - -.Llookup_stub_fast_or_critical_native: - call artFindNativeMethodRunnable - -.Llookup_stub_continue: - mv t0, a0 // store result in a temp reg. - RESTORE_GPR fp, (ALL_ARGS_SIZE + 0) - RESTORE_GPR ra, (ALL_ARGS_SIZE + 8) - RESTORE_ALL_ARGS_DECREASE_FRAME 2*8 - - beqz t0, 1f // is method code null? - jr t0 // if non-null, tail call to method code. -1: - ret // restore regs and return to caller to handle exception. -END art_jni_dlsym_lookup_stub - - // JNI dlsym lookup stub for @CriticalNative. ENTRY art_jni_dlsym_lookup_critical_stub // The hidden arg holding the tagged method is t0 (loaded by compiled JNI stub, compiled diff --git a/runtime/arch/riscv64/native_entrypoints_riscv64.S b/runtime/arch/riscv64/native_entrypoints_riscv64.S new file mode 100644 index 0000000000..24c8205c0f --- /dev/null +++ b/runtime/arch/riscv64/native_entrypoints_riscv64.S @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm_support_riscv64.S" +#include "interpreter/cfi_asm_support.h" + +/* + * This file contains all native entrypoints that are called using the native ABI and do not + * transition to the quick ABI. For example: the switch interpreter (using the native ABI) directly + * calls ExecuteSwitchImplAsm and this code will always return back to the switch interpreter, + * again using the native ABI. Because of this behaviour ExecuteSwitchImplAsm should be included in + * this file. This is done so these native entrypoints can be compiled independently to quick + * entrypoints for cases when the kRuntimeISA and kRuntimeQuickCodeISA do not match. + * + * See comment on StackType (thread.h) for definitions and examples of quick ABI/code and + * native ABI/code. + */ + +// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. +// Argument 0: a0: The context pointer for ExecuteSwitchImpl. +// Argument 1: a1: Pointer to the templated ExecuteSwitchImpl to call. +// Argument 2: a2: The value of DEX PC (memory address of the methods bytecode). +ENTRY ExecuteSwitchImplAsm + INCREASE_FRAME 16 + SAVE_GPR s1, 0 + SAVE_GPR ra, 8 + + mv s1, a2 // s1 = DEX PC + CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* a0 */, 9 /* s1, a.k.a. x9 */, 0) + jalr a1 // Call the wrapped method. + + RESTORE_GPR s1, 0 + RESTORE_GPR ra, 8 + DECREASE_FRAME 16 + ret +END ExecuteSwitchImplAsm + +// JNI dlsym lookup stub. +.extern artFindNativeMethod +.extern artFindNativeMethodRunnable +ENTRY art_jni_dlsym_lookup_stub + SAVE_ALL_ARGS_INCREASE_FRAME 2*8 + SAVE_GPR fp, (ALL_ARGS_SIZE + 0) + SAVE_GPR ra, (ALL_ARGS_SIZE + 8) + add fp, sp, ALL_ARGS_SIZE + + // Call artFindNativeMethod for normal native. + // Call artFindNativeMethodRunnable for @FastNative or @CriticalNative. + // Both functions have a single argument: Thread::Current() in a0. + mv a0, xSELF + ld t0, THREAD_TOP_QUICK_FRAME_OFFSET(a0) // uintptr_t tagged_quick_frame + andi t0, t0, ~TAGGED_JNI_SP_MASK // ArtMethod** sp + ld t0, (t0) // ArtMethod* method + lw t0, ART_METHOD_ACCESS_FLAGS_OFFSET(t0) // uint32_t access_flags + li t1, (ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE) + and t0, t0, t1 + bnez t0, .Llookup_stub_fast_or_critical_native + call artFindNativeMethod + j .Llookup_stub_continue + +.Llookup_stub_fast_or_critical_native: + call artFindNativeMethodRunnable + +.Llookup_stub_continue: + mv t0, a0 // store result in a temp reg. + RESTORE_GPR fp, (ALL_ARGS_SIZE + 0) + RESTORE_GPR ra, (ALL_ARGS_SIZE + 8) + RESTORE_ALL_ARGS_DECREASE_FRAME 2*8 + + beqz t0, 1f // is method code null? + jr t0 // if non-null, tail call to method code. +1: + ret // restore regs and return to caller to handle exception. +END art_jni_dlsym_lookup_stub diff --git a/runtime/arch/riscv64/quick_entrypoints_riscv64.S b/runtime/arch/riscv64/quick_entrypoints_riscv64.S index 06b9e9b7bb..49de49fa8c 100644 --- a/runtime/arch/riscv64/quick_entrypoints_riscv64.S +++ b/runtime/arch/riscv64/quick_entrypoints_riscv64.S @@ -21,26 +21,6 @@ #include "arch/quick_field_entrypoints.S" -// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. -// Argument 0: a0: The context pointer for ExecuteSwitchImpl. -// Argument 1: a1: Pointer to the templated ExecuteSwitchImpl to call. -// Argument 2: a2: The value of DEX PC (memory address of the methods bytecode). -ENTRY ExecuteSwitchImplAsm - INCREASE_FRAME 16 - SAVE_GPR s1, 0 - SAVE_GPR ra, 8 - - mv s1, a2 // s1 = DEX PC - CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* a0 */, 9 /* s1, a.k.a. x9 */, 0) - jalr a1 // Call the wrapped method. - - RESTORE_GPR s1, 0 - RESTORE_GPR ra, 8 - DECREASE_FRAME 16 - ret -END ExecuteSwitchImplAsm - - .macro INVOKE_STUB_CREATE_FRAME // Save RA, FP, xSELF (current thread), A4, A5 (they will be needed in the invoke stub return). INCREASE_FRAME 48 diff --git a/runtime/arch/x86/jni_entrypoints_x86.S b/runtime/arch/x86/jni_entrypoints_x86.S index 09b4d5a0f5..531f3c7d97 100644 --- a/runtime/arch/x86/jni_entrypoints_x86.S +++ b/runtime/arch/x86/jni_entrypoints_x86.S @@ -88,35 +88,6 @@ END_FUNCTION \name END_MACRO /* - * Jni dlsym lookup stub. - */ -DEFINE_FUNCTION art_jni_dlsym_lookup_stub - INCREASE_FRAME 8 // Align stack. - pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). - CFI_ADJUST_CFA_OFFSET(4) - // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() - // for @FastNative or @CriticalNative. - movl (%esp), %eax // Thread* self - movl THREAD_TOP_QUICK_FRAME_OFFSET(%eax), %eax // uintptr_t tagged_quick_frame - andl LITERAL(TAGGED_JNI_SP_MASK_TOGGLED32), %eax // ArtMethod** sp - movl (%eax), %eax // ArtMethod* method - testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ - ART_METHOD_ACCESS_FLAGS_OFFSET(%eax) - jne .Llookup_stub_fast_or_critical_native - call SYMBOL(artFindNativeMethod) // (Thread*) - jmp .Llookup_stub_continue -.Llookup_stub_fast_or_critical_native: - call SYMBOL(artFindNativeMethodRunnable) // (Thread*) -.Llookup_stub_continue: - DECREASE_FRAME 12 // Remove argument & padding. - testl %eax, %eax // Check if returned method code is null. - jz .Lno_native_code_found // If null, jump to return to handle. - jmp *%eax // Otherwise, tail call to intended method. -.Lno_native_code_found: - ret -END_FUNCTION art_jni_dlsym_lookup_stub - - /* * Jni dlsym lookup stub for @CriticalNative. */ DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub diff --git a/runtime/arch/x86/native_entrypoints_x86.S b/runtime/arch/x86/native_entrypoints_x86.S new file mode 100644 index 0000000000..9d1c41a069 --- /dev/null +++ b/runtime/arch/x86/native_entrypoints_x86.S @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm_support_x86.S" +#include "interpreter/cfi_asm_support.h" + +/* + * This file contains all native entrypoints that are called using the native ABI and do not + * transition to the quick ABI. For example: the switch interpreter (using the native ABI) directly + * calls ExecuteSwitchImplAsm and this code will always return back to the switch interpreter, + * again using the native ABI. Because of this behaviour ExecuteSwitchImplAsm should be included in + * this file. This is done so these native entrypoints can be compiled independently to quick + * entrypoints for cases when the kRuntimeISA and kRuntimeQuickCodeISA do not match. + * + * See comment on StackType (thread.h) for definitions and examples of quick ABI/code and + * native ABI/code. + */ + +// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. +// Argument 0: ESP+4: The context pointer for ExecuteSwitchImpl. +// Argument 1: ESP+8: Pointer to the templated ExecuteSwitchImpl to call. +// Argument 2: ESP+12: The value of DEX PC (memory address of the methods bytecode). +DEFINE_FUNCTION ExecuteSwitchImplAsm + PUSH ebx // Spill EBX; Increments ESP, so arg0 is at ESP+8 now. + mov 12(%esp), %eax // EAX = C++ templated interpreter function + mov 16(%esp), %ebx // EBX = DEX PC (callee save register) + mov 8(%esp), %ecx // ECX = Context argument for the function + CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* EAX */, 3 /* EBX */, 0) + + sub LITERAL(4), %esp // Alignment padding + CFI_ADJUST_CFA_OFFSET(4) + push %ecx // Push argument + CFI_ADJUST_CFA_OFFSET(4) + call *%eax // Call the wrapped function + addl LITERAL(8), %esp + CFI_ADJUST_CFA_OFFSET(-8) + + POP ebx // Restore EBX + ret +END_FUNCTION ExecuteSwitchImplAsm + + /* + * Jni dlsym lookup stub. + */ +DEFINE_FUNCTION art_jni_dlsym_lookup_stub + INCREASE_FRAME 8 // Align stack. + pushl %fs:THREAD_SELF_OFFSET // Pass Thread::Current(). + CFI_ADJUST_CFA_OFFSET(4) + // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() + // for @FastNative or @CriticalNative. + movl (%esp), %eax // Thread* self + movl THREAD_TOP_QUICK_FRAME_OFFSET(%eax), %eax // uintptr_t tagged_quick_frame + andl LITERAL(TAGGED_JNI_SP_MASK_TOGGLED32), %eax // ArtMethod** sp + movl (%eax), %eax // ArtMethod* method + testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ + ART_METHOD_ACCESS_FLAGS_OFFSET(%eax) + jne .Llookup_stub_fast_or_critical_native + call SYMBOL(artFindNativeMethod) // (Thread*) + jmp .Llookup_stub_continue +.Llookup_stub_fast_or_critical_native: + call SYMBOL(artFindNativeMethodRunnable) // (Thread*) +.Llookup_stub_continue: + DECREASE_FRAME 12 // Remove argument & padding. + testl %eax, %eax // Check if returned method code is null. + jz .Lno_native_code_found // If null, jump to return to handle. + jmp *%eax // Otherwise, tail call to intended method. +.Lno_native_code_found: + ret +END_FUNCTION art_jni_dlsym_lookup_stub diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S index d5c186e1ad..1078480c8c 100644 --- a/runtime/arch/x86/quick_entrypoints_x86.S +++ b/runtime/arch/x86/quick_entrypoints_x86.S @@ -2132,29 +2132,6 @@ DEFINE_FUNCTION art_quick_invoke_custom RETURN_OR_DELIVER_PENDING_EXCEPTION END_FUNCTION art_quick_invoke_custom -// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. -// Argument 0: ESP+4: The context pointer for ExecuteSwitchImpl. -// Argument 1: ESP+8: Pointer to the templated ExecuteSwitchImpl to call. -// Argument 2: ESP+12: The value of DEX PC (memory address of the methods bytecode). -DEFINE_FUNCTION ExecuteSwitchImplAsm - PUSH ebx // Spill EBX; Increments ESP, so arg0 is at ESP+8 now. - mov 12(%esp), %eax // EAX = C++ templated interpreter function - mov 16(%esp), %ebx // EBX = DEX PC (callee save register) - mov 8(%esp), %ecx // ECX = Context argument for the function - CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* EAX */, 3 /* EBX */, 0) - - sub LITERAL(4), %esp // Alignment padding - CFI_ADJUST_CFA_OFFSET(4) - push %ecx // Push argument - CFI_ADJUST_CFA_OFFSET(4) - call *%eax // Call the wrapped function - addl LITERAL(8), %esp - CFI_ADJUST_CFA_OFFSET(-8) - - POP ebx // Restore EBX - ret -END_FUNCTION ExecuteSwitchImplAsm - // On entry: eax is the class, ebp is the inline cache. DEFINE_FUNCTION art_quick_update_inline_cache #if (INLINE_CACHE_SIZE != 5) diff --git a/runtime/arch/x86_64/jni_entrypoints_x86_64.S b/runtime/arch/x86_64/jni_entrypoints_x86_64.S index a635de8c28..49b59bfa80 100644 --- a/runtime/arch/x86_64/jni_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/jni_entrypoints_x86_64.S @@ -92,66 +92,6 @@ END_FUNCTION \name END_MACRO /* - * Jni dlsym lookup stub. - */ -DEFINE_FUNCTION art_jni_dlsym_lookup_stub - // Save callee and GPR args. - PUSH_ARG r9 // Arg. - PUSH_ARG r8 // Arg. - PUSH_ARG rdi // Arg. (JniEnv for normal and @FastNative) - PUSH_ARG rsi // Arg. - PUSH_ARG rdx // Arg. - PUSH_ARG rcx // Arg. - // Create space for FPR args, plus padding for alignment - INCREASE_FRAME 72 - // Save FPRs. - movq %xmm0, 0(%rsp) - movq %xmm1, 8(%rsp) - movq %xmm2, 16(%rsp) - movq %xmm3, 24(%rsp) - movq %xmm4, 32(%rsp) - movq %xmm5, 40(%rsp) - movq %xmm6, 48(%rsp) - movq %xmm7, 56(%rsp) - // prepare call - movq %gs:THREAD_SELF_OFFSET, %rdi // RDI := Thread::Current() - // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() - // for @FastNative or @CriticalNative. - movq THREAD_TOP_QUICK_FRAME_OFFSET(%rdi), %rax // uintptr_t tagged_quick_frame - andq LITERAL(TAGGED_JNI_SP_MASK_TOGGLED64), %rax // ArtMethod** sp - movq (%rax), %rax // ArtMethod* method - testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ - ART_METHOD_ACCESS_FLAGS_OFFSET(%rax) - jne .Llookup_stub_fast_or_critical_native - call SYMBOL(artFindNativeMethod) // (Thread*) - jmp .Llookup_stub_continue -.Llookup_stub_fast_or_critical_native: - call SYMBOL(artFindNativeMethodRunnable) // (Thread*) -.Llookup_stub_continue: - // restore arguments - movq 0(%rsp), %xmm0 - movq 8(%rsp), %xmm1 - movq 16(%rsp), %xmm2 - movq 24(%rsp), %xmm3 - movq 32(%rsp), %xmm4 - movq 40(%rsp), %xmm5 - movq 48(%rsp), %xmm6 - movq 56(%rsp), %xmm7 - DECREASE_FRAME 72 - POP_ARG rcx // Arg. - POP_ARG rdx // Arg. - POP_ARG rsi // Arg. - POP_ARG rdi // Arg. (JniEnv for normal and @FastNative) - POP_ARG r8 // Arg. - POP_ARG r9 // Arg. - testq %rax, %rax // check if returned method code is null - jz .Lno_native_code_found // if null, jump to return to handle - jmp *%rax // otherwise, tail call to intended method -.Lno_native_code_found: - ret -END_FUNCTION art_jni_dlsym_lookup_stub - - /* * Jni dlsym lookup stub for @CriticalNative. */ DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub diff --git a/runtime/arch/x86_64/native_entrypoints_x86_64.S b/runtime/arch/x86_64/native_entrypoints_x86_64.S new file mode 100644 index 0000000000..12194ef97c --- /dev/null +++ b/runtime/arch/x86_64/native_entrypoints_x86_64.S @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "asm_support_x86_64.S" +#include "interpreter/cfi_asm_support.h" + +/* + * This file contains all native entrypoints that are called using the native ABI and do not + * transition to the quick ABI. For example: the switch interpreter (using the native ABI) directly + * calls ExecuteSwitchImplAsm and this code will always return back to the switch interpreter, + * again using the native ABI. Because of this behaviour ExecuteSwitchImplAsm should be included in + * this file. This is done so these native entrypoints can be compiled independently to quick + * entrypoints for cases when the kRuntimeISA and kRuntimeQuickCodeISA do not match. + * + * See comment on StackType (thread.h) for definitions and examples of quick ABI/code and + * native ABI/code. + */ + +// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. +// Argument 0: RDI: The context pointer for ExecuteSwitchImpl. +// Argument 1: RSI: Pointer to the templated ExecuteSwitchImpl to call. +// Argument 2: RDX: The value of DEX PC (memory address of the methods bytecode). +DEFINE_FUNCTION ExecuteSwitchImplAsm + PUSH rbx // Spill RBX + movq %rdx, %rbx // RBX = DEX PC (callee save register) + CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* RAX */, 3 /* RBX */, 0) + + call *%rsi // Call the wrapped function + + POP rbx // Restore RBX + ret +END_FUNCTION ExecuteSwitchImplAsm + + /* + * Jni dlsym lookup stub. + */ +DEFINE_FUNCTION art_jni_dlsym_lookup_stub + // Save callee and GPR args. + PUSH_ARG r9 // Arg. + PUSH_ARG r8 // Arg. + PUSH_ARG rdi // Arg. (JniEnv for normal and @FastNative) + PUSH_ARG rsi // Arg. + PUSH_ARG rdx // Arg. + PUSH_ARG rcx // Arg. + // Create space for FPR args, plus padding for alignment + INCREASE_FRAME 72 + // Save FPRs. + movq %xmm0, 0(%rsp) + movq %xmm1, 8(%rsp) + movq %xmm2, 16(%rsp) + movq %xmm3, 24(%rsp) + movq %xmm4, 32(%rsp) + movq %xmm5, 40(%rsp) + movq %xmm6, 48(%rsp) + movq %xmm7, 56(%rsp) + // prepare call + movq %gs:THREAD_SELF_OFFSET, %rdi // RDI := Thread::Current() + // Call artFindNativeMethod() for normal native and artFindNativeMethodRunnable() + // for @FastNative or @CriticalNative. + movq THREAD_TOP_QUICK_FRAME_OFFSET(%rdi), %rax // uintptr_t tagged_quick_frame + andq LITERAL(TAGGED_JNI_SP_MASK_TOGGLED64), %rax // ArtMethod** sp + movq (%rax), %rax // ArtMethod* method + testl LITERAL(ACCESS_FLAGS_METHOD_IS_FAST_NATIVE | ACCESS_FLAGS_METHOD_IS_CRITICAL_NATIVE), \ + ART_METHOD_ACCESS_FLAGS_OFFSET(%rax) + jne .Llookup_stub_fast_or_critical_native + call SYMBOL(artFindNativeMethod) // (Thread*) + jmp .Llookup_stub_continue +.Llookup_stub_fast_or_critical_native: + call SYMBOL(artFindNativeMethodRunnable) // (Thread*) +.Llookup_stub_continue: + // restore arguments + movq 0(%rsp), %xmm0 + movq 8(%rsp), %xmm1 + movq 16(%rsp), %xmm2 + movq 24(%rsp), %xmm3 + movq 32(%rsp), %xmm4 + movq 40(%rsp), %xmm5 + movq 48(%rsp), %xmm6 + movq 56(%rsp), %xmm7 + DECREASE_FRAME 72 + POP_ARG rcx // Arg. + POP_ARG rdx // Arg. + POP_ARG rsi // Arg. + POP_ARG rdi // Arg. (JniEnv for normal and @FastNative) + POP_ARG r8 // Arg. + POP_ARG r9 // Arg. + testq %rax, %rax // check if returned method code is null + jz .Lno_native_code_found // if null, jump to return to handle + jmp *%rax // otherwise, tail call to intended method +.Lno_native_code_found: + ret +END_FUNCTION art_jni_dlsym_lookup_stub diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index b72890d444..4d00022ff8 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -2000,21 +2000,6 @@ DEFINE_FUNCTION art_quick_invoke_custom RETURN_OR_DELIVER_PENDING_EXCEPTION END_FUNCTION art_quick_invoke_custom -// Wrap ExecuteSwitchImpl in assembly method which specifies DEX PC for unwinding. -// Argument 0: RDI: The context pointer for ExecuteSwitchImpl. -// Argument 1: RSI: Pointer to the templated ExecuteSwitchImpl to call. -// Argument 2: RDX: The value of DEX PC (memory address of the methods bytecode). -DEFINE_FUNCTION ExecuteSwitchImplAsm - PUSH rbx // Spill RBX - movq %rdx, %rbx // RBX = DEX PC (callee save register) - CFI_DEFINE_DEX_PC_WITH_OFFSET(0 /* RAX */, 3 /* RBX */, 0) - - call *%rsi // Call the wrapped function - - POP rbx // Restore RBX - ret -END_FUNCTION ExecuteSwitchImplAsm - // On entry: edi is the class, r11 is the inline cache. r10 and rax are available. DEFINE_FUNCTION art_quick_update_inline_cache #if (INLINE_CACHE_SIZE != 5) |