Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/runtime/arch/arm/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 15 kB image not shown  

Quelle  jni_entrypoints_arm.S

  Sprache: Sparc
 

/*
 * Copyright (C) 2012 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"

#define MANAGED_ARGS_R4_LR_SAVE_SIZE /*s0-s15*/ 16 * 4 + /*r0-r3*/ 4 * 4 + /*r4*/ 4 + /*lr*/ 4

// Note: R4 is saved for stack alignment.
.macro SAVE_MANAGED_ARGS_R4_LR_INCREASE_FRAME
    // Save GPR args r0-r3 and return address. Also save r4 for stack alignment.
    push   {r0-r4, lr}
    .cfi_adjust_cfa_offset 24
    .cfi_rel_offset lr, 20
    // Save FPR args.
    vpush  {s0-s15}
    .cfi_adjust_cfa_offset 64
.endm

.macro RESTORE_MANAGED_ARGS_R4_AND_RETURN restore_cfa
    // Restore FPR args.
    vpop   {s0-s15}
    .cfi_adjust_cfa_offset -64
    // Restore GPR args and r4 and return.
    pop    {r0-r4, pc}
    .if \restore_cfa
        .cfi_adjust_cfa_offset 64
    .endif
.endm

.macro JNI_SAVE_MANAGED_ARGS_TRAMPOLINE name, cxx_name, arg1 = "none"
    .extern \cxx_name
ENTRY \name
    // Note: Managed callee-save registers have been saved by the JNI stub.
    // Save managed args, r4 (for stack alignment) and LR.
    SAVE_MANAGED_ARGS_R4_LR_INCREASE_FRAME
    // Call `cxx_name()`.
    .ifnc \arg1, none
        mov r0, \arg1                     @ Pass arg1.
    .endif
    bl     \cxx_name                      @ Call cxx_name(...).
    // Restore args and R4 and return.
    RESTORE_MANAGED_ARGS_R4_AND_RETURN /*restore_cfa*/ 0
END \name
.endm

.macro JNI_SAVE_RETURN_VALUE_TRAMPOLINE name, cxx_name, arg1, arg2 = "none", label = "none"
    .extern \cxx_name
ENTRY \name
    .ifnc \label, none
        \label:
    .endif
    // Save GPR return registers and return address. Also save r4 for stack alignment.
    push   {r0-r1, r4, lr}
    .cfi_adjust_cfa_offset 16
    .cfi_rel_offset lr, 12
    // Save FPR return registers.
    vpush  {s0-s1}
    .cfi_adjust_cfa_offset 8
    // Call `cxx_name()`.
    mov r0, \arg1                         @ Pass arg1.
    .ifnc \arg2, none
        mov r1, \arg2                     @ Pass arg2.
    .endif
    bl     \cxx_name                      @ Call cxx_name(...).
    // Restore FPR return registers.
    vpop   {s0-s1}
    .cfi_adjust_cfa_offset -8
    // Restore GPR return registers and r4 and return.
    pop    {r0-r1, r4, pc}
END \name
.endm

    /*
     * 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 r4.
    // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub.
    tst    r4, #1
    bne art_jni_dlsym_lookup_stub

    // Reserve space for a SaveRefsAndArgs managed frame, either for the actual runtime
    // method or for a GenericJNI frame which is similar but has a native method and a tag.
    // Do this eagerly, so that we can use these registers as temps without the need to
    // save and restore them multiple times.
    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS

    // Save args, the hidden arg and caller PC. No CFI needed for args and the hidden arg.
    push   {r0, r1, r2, r3, r4, lr}
    .cfi_adjust_cfa_offset 24
    .cfi_rel_offset lr, 20

    // Call artCriticalNativeFrameSize(method, caller_pc)
    mov    r0, r4  // r0 := method (from hidden arg)
    mov    r1, lr  // r1 := caller_pc
    bl     artCriticalNativeFrameSize

    // Prepare the return address for managed stack walk of the SaveRefsAndArgs frame.
    // If we're coming from JNI stub with tail call, it is LR. If we're coming from
    // JNI stub that saved the return address, it will be the last value we copy below.
    // If we're coming directly from compiled code, it is LR, set further down.
    ldr    lr, [sp, #20]

    // Move the stack args if any.
    add    r4, sp, #24
    cbz    r0, .Lcritical_skip_copy_args
.Lcritical_copy_args_loop:
    ldrd   ip, lr, [r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
    subs   r0, r0, #8
    strd   ip, lr, [r4], #8
    bne    .Lcritical_copy_args_loop
.Lcritical_skip_copy_args:
    // The managed frame address is now in R4. This is conveniently a callee-save in native ABI.

    // Restore args.
    pop    {r0, r1, r2, r3}
    .cfi_adjust_cfa_offset -16

    // Spill registers for the SaveRefsAndArgs frame above the stack args.
    // Note that the runtime shall not examine the args here, otherwise we would have to
    // move them in registers and stack to account for the difference between managed and
    // native ABIs.
    add    ip, r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS - 40
    stmia  ip, {r1-r3, r5-r8, r10-r11, lr}  // LR: Save return address for tail call from JNI stub.
    // (If there were any stack args, we're storing the value that's already there.
    // For direct calls from compiled managed code, we shall overwrite this below.)
    // Skip args r1-r3.
    CFI_EXPRESSION_BREG 54, FRAME_SIZE_SAVE_REFS_AND_ARGS - 28
    CFI_EXPRESSION_BREG 64, FRAME_SIZE_SAVE_REFS_AND_ARGS - 24
    CFI_EXPRESSION_BREG 74, FRAME_SIZE_SAVE_REFS_AND_ARGS - 20
    CFI_EXPRESSION_BREG 84, FRAME_SIZE_SAVE_REFS_AND_ARGS - 16
    CFI_EXPRESSION_BREG 104, FRAME_SIZE_SAVE_REFS_AND_ARGS - 12
    CFI_EXPRESSION_BREG 114, FRAME_SIZE_SAVE_REFS_AND_ARGS - 8
    // The saved return PC for managed stack walk is not necessarily our LR.
    // Skip managed FP args as these are native ABI caller-saves and not args.

    // Restore the hidden arg to r1 and caller PC.
    pop    {r1, lr}
    .cfi_adjust_cfa_offset -8
    .cfi_restore lr

    // Save our return PC in the padding.
    str   lr, [r4, #__SIZEOF_POINTER__]
    CFI_EXPRESSION_BREG 144, __SIZEOF_POINTER__

    ldr    ip, [r1, #ART_METHOD_ACCESS_FLAGS_OFFSET]  // Load access flags.
    add    r2, r4, #1             // Prepare managed SP tagged for a GenericJNI frame.
    tst    ip, #ACCESS_FLAGS_METHOD_IS_NATIVE
    bne    .Lcritical_skip_prepare_runtime_method

    // When coming from a compiled method, the return PC for managed stack walk is LR.
    // (When coming from a compiled stub, the correct return PC is already stored above.)
    str    lr, [r4, #(FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__)]

    // Replace the target method with the SaveRefsAndArgs runtime method.
    LOAD_RUNTIME_INSTANCE r1
    ldr    r1, [r1, #RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET]

    mov    r2, r4                 // Prepare untagged managed SP for the runtime method.

.Lcritical_skip_prepare_runtime_method:
    // Store the method on the bottom of the managed frame.
    str    r1, [r4]

    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
    str    r2, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]

    // Preserve the native arg register r0 in callee-save register r10 which was saved above.
    mov    r10, r0

    // Call artFindNativeMethodRunnable()
    mov    r0, rSELF   // pass Thread::Current()
    bl     artFindNativeMethodRunnable

    // Store result in scratch reg.
    mov    ip, r0

    // Restore the native arg register r0.
    mov    r0, r10

    // Restore the frame. We shall not need the method anymore.
    add    r1, r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS - 40
    ldmia  r1, {r1-r3, r5-r8, r10-r11}
    .cfi_restore r5
    .cfi_restore r6
    .cfi_restore r7
    .cfi_restore r8
    .cfi_restore r10
    .cfi_restore r11

    REFRESH_MARKING_REGISTER

    // Check for exception before moving args back to keep the return PC for managed stack walk.
    cmp    ip, #0
    CFI_REMEMBER_STATE
    beq    .Lcritical_deliver_exception

    // Restore our return PC.
    ldr    lr, [r4, #__SIZEOF_POINTER__]
    .cfi_restore lr

    // Move stack args to their original place.
    cmp    sp, r4
    beq    .Lcritical_skip_copy_args_back
    push   {r0, r1, r2, r3}
    .cfi_adjust_cfa_offset 16
    add    r0, sp, #16
    sub    r0, r4, r0
.Lcritical_copy_args_loop_back:
    ldrd   r2, r3, [r4, #-8]!
    subs   r0, r0, #8
    strd   r2, r3, [r4, #FRAME_SIZE_SAVE_REFS_AND_ARGS]
    bne    .Lcritical_copy_args_loop_back
    pop    {r0, r1, r2, r3}
    .cfi_adjust_cfa_offset -16
.Lcritical_skip_copy_args_back:

    // Remove the frame reservation.
    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS

    // Do the tail call.
    bx     ip

.Lcritical_deliver_exception:
    CFI_RESTORE_STATE_AND_DEF_CFA sp, FRAME_SIZE_SAVE_REFS_AND_ARGS
    // The exception delivery checks that rSELF was saved but the SaveRefsAndArgs
    // frame does not save it, so we cannot use the existing SaveRefsAndArgs frame.
    // That's why we checked for exception after restoring registers from it.
    // We need to build a SaveAllCalleeSaves frame instead. Args are irrelevant at this
    // point but keep the area allocated for stack args to keep CFA definition simple.
#if FRAME_SIZE_SAVE_REFS_AND_ARGS != FRAME_SIZE_SAVE_ALL_CALLEE_SAVES
#  error "Expected FRAME_SIZE_SAVE_REFS_AND_ARGS == FRAME_SIZE_SAVE_ALL_CALLEE_SAVES"
    // Otherwise we would need to adjust SP and R4 and move our return PC which is at [R4, #4].
    // (Luckily, both SaveRefsAndArgs and SaveAllCalleeSaves frames have padding there.)
#endif

    // Spill registers for the SaveAllCalleeSaves frame above the stack args area.
    add    ip, r4, #FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 32
    stmia  ip, {r5-r11}  // Keep the caller PC for managed stack walk.
    CFI_EXPRESSION_BREG 54, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 32
    CFI_EXPRESSION_BREG 64, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 28
    CFI_EXPRESSION_BREG 74, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 24
    CFI_EXPRESSION_BREG 84, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 20
    CFI_EXPRESSION_BREG 94, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 16
    CFI_EXPRESSION_BREG 104, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 12
    CFI_EXPRESSION_BREG 114, FRAME_SIZE_SAVE_ALL_CALLEE_SAVES - 8
    // Skip R4, it is callee-save in managed ABI.
    add    ip, r4, #12
    vstmia ip, {s16-s31}

    // Store ArtMethod* Runtime::callee_save_methods_[kSaveAllCalleeSaves] to the managed frame.
    LOAD_RUNTIME_INSTANCE ip
    ldr   ip, [ip, #RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET]
    str   ip, [r4]

    // Place the managed frame SP in Thread::Current()->top_quick_frame.
    str   r4, [rSELF, #THREAD_TOP_QUICK_FRAME_OFFSET]

    DELIVER_PENDING_EXCEPTION_FRAME_READY
END art_jni_dlsym_lookup_critical_stub

    /*
     * Read barrier for the method's declaring class needed by JNI stub for static methods.
     * (We're using a pointer to the declaring class in `ArtMethod` as `jclass`.)
     */

// The method argument is already in r0 for call to `artJniReadBarrier(ArtMethod*)`.
JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_read_barrier, artJniReadBarrier

    /*
     * Trampoline to `artJniMethodStart()` that preserves all managed arguments.
     */

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_method_start, artJniMethodStart, rSELF

    /*
     * Trampoline to `artJniMethodEntryHook()` that preserves all managed arguments.
     */

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_method_entry_hook, artJniMethodEntryHook, rSELF

    /*
     * Trampoline to `artJniMonitoredMethodStart()` that preserves all managed arguments.
     */

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_monitored_method_start, artJniMonitoredMethodStart, rSELF

    /*
     * Trampoline to `artJniMethodEnd()` that preserves all return registers.
     */

JNI_SAVE_RETURN_VALUE_TRAMPOLINE art_jni_method_end, artJniMethodEnd, rSELF

    /*
     * Trampoline to `artJniMonitoredMethodEnd()` that preserves all return registers.
     */

JNI_SAVE_RETURN_VALUE_TRAMPOLINE art_jni_monitored_method_end, artJniMonitoredMethodEnd, rSELF

    /*
     * Entry from JNI stub that tries to lock the object in a fast path and
     * calls `artLockObjectFromCode()` (the same as for managed code) for the
     * difficult cases, may block for GC.
     * Custom calling convention:
     *     r4 holds the non-null object to lock.
     *     Callee-save registers have been saved and can be used as temporaries.
     *     All argument registers need to be preserved.
     */

ENTRY art_jni_lock_object
    // Note: the slow path is actually the art_jni_lock_object_no_inline (tail call).
    LOCK_OBJECT_FAST_PATH r4, r5, r6, r7, .Llock_object_jni_slow, /*can_be_null*/ 0
END art_jni_lock_object

    /*
     * Entry from JNI stub that calls `artLockObjectFromCode()`
     * (the same as for managed code), may block for GC.
     * Custom calling convention:
     *     r4 holds the non-null object to lock.
     *     Callee-save registers have been saved and can be used as temporaries.
     *     All argument registers need to be preserved.
     */

    .extern artLockObjectFromCode
ENTRY art_jni_lock_object_no_inline
    // This is also the slow path for art_jni_lock_object.
    // Note that we need a local label as the assembler emits bad instructions
    // for CBZ/CBNZ if we try to jump to `art_jni_lock_object_no_inline`.
.Llock_object_jni_slow:
    // Save managed args, r4 (for stack alignment) and LR.
    SAVE_MANAGED_ARGS_R4_LR_INCREASE_FRAME
    // Call `artLockObjectFromCode()`
    mov    r0, r4                       @ Pass the object to lock.
    mov    r1, rSELF                    @ Pass Thread::Current().
    bl     artLockObjectFromCode        @ (Object* obj, Thread*)
    // Check result.
    cbnz   r0, 1f
    // Restore args and r4 and return.
    RESTORE_MANAGED_ARGS_R4_AND_RETURN /*restore_cfa*/ 1
1:
    // All args are irrelevant when throwing an exception and R4 is preserved
    // by the `artLockObjectFromCode()` call. Load LR and drop saved args and R4.
    ldr    lr, [sp, #(MANAGED_ARGS_R4_LR_SAVE_SIZE - 4)]
    .cfi_restore lr
    DECREASE_FRAME MANAGED_ARGS_R4_LR_SAVE_SIZE
    // Make a call to `artDeliverPendingExceptionFromCode()`.
    // Rely on the JNI transition frame constructed in the JNI stub.
    mov    r0, rSELF                            @ Pass Thread::Current().
    bl     artDeliverPendingExceptionFromCode   @ (Thread*)
    bl     art_quick_do_long_jump               @ (Context*)
    bkpt  // Unreached
END art_jni_lock_object_no_inline

    /*
     * Entry from JNI stub that tries to unlock the object in a fast path and calls
     * `artJniUnlockObject()` for the difficult cases. Note that failure to unlock
     * is fatal, so we do not need to check for exceptions in the slow path.
     * Custom calling convention:
     *     r4 holds the non-null object to unlock.
     *     Callee-save registers have been saved and can be used as temporaries.
     *     Return registers r0-r1 and s0-s1 need to be preserved.
     */

ENTRY art_jni_unlock_object
    // Note: the slow path is actually the art_jni_unlock_object_no_inline (tail call).
    UNLOCK_OBJECT_FAST_PATH r4, r5, r6, r7, .Lunlock_object_jni_slow, /*can_be_null*/ 0
END art_jni_unlock_object

    /*
     * Entry from JNI stub that calls `artJniUnlockObject()`. Note that failure to
     * unlock is fatal, so we do not need to check for exceptions.
     * Custom calling convention:
     *     r4 holds the non-null object to unlock.
     *     Callee-save registers have been saved and can be used as temporaries.
     *     Return registers r0-r1 and s0-s1 need to be preserved.
     */

    // This is also the slow path for art_jni_unlock_object.
JNI_SAVE_RETURN_VALUE_TRAMPOLINE art_jni_unlock_object_no_inline, artJniUnlockObject, r4, rSELF, \
    /* Note that we need a local label as the assembler emits bad instructions                */ \
    /* for CBZ/CBNZ if we try to jump to `art_jni_unlock_object_no_inline`.                   */ \
    .Lunlock_object_jni_slow

Messung V0.5 in Prozent
C=90 H=93 G=91

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.