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

Quelle  jni_entrypoints_x86_64.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_x86_64.S"

#define MANAGED_ARGS_SAVE_SIZE /*xmm0-xmm7*/ 8 * 8 + /*padding*/ 8 + /* GPR args */ 6 * 8

MACRO0(SAVE_MANAGED_ARGS_INCREASE_FRAME)
    // Return address is on the stack.
    PUSH_ARG r9
    PUSH_ARG r8
    PUSH_ARG rcx
    PUSH_ARG rdx
    PUSH_ARG rsi
    PUSH_ARG rdi
    INCREASE_FRAME (/*FPRs*/ 8 * 8 + /*padding*/ 8)
    movsd %xmm0, 0(%rsp)
    movsd %xmm1, 8(%rsp)
    movsd %xmm2, 16(%rsp)
    movsd %xmm3, 24(%rsp)
    movsd %xmm4, 32(%rsp)
    movsd %xmm5, 40(%rsp)
    movsd %xmm6, 48(%rsp)
    movsd %xmm7, 56(%rsp)
END_MACRO

MACRO0(RESTORE_MANAGED_ARGS_DECREASE_FRAME)
    movsd 0(%rsp), %xmm0
    movsd 8(%rsp), %xmm1
    movsd 16(%rsp), %xmm2
    movsd 24(%rsp), %xmm3
    movsd 32(%rsp), %xmm4
    movsd 40(%rsp), %xmm5
    movsd 48(%rsp), %xmm6
    movsd 56(%rsp), %xmm7
    DECREASE_FRAME (/*FPRs*/ 8 * 8 + /*padding*/ 8)
    POP_ARG rdi
    POP_ARG rsi
    POP_ARG rdx
    POP_ARG rcx
    POP_ARG r8
    POP_ARG r9
END_MACRO

MACRO3(JNI_SAVE_MANAGED_ARGS_TRAMPOLINE, name, cxx_name, arg1)
DEFINE_FUNCTION \name
    // Note: Managed callee-save registers have been saved by the JNI stub.
    // Save register args RDI, RSI, RDX, RCX, R8, R9, mmx0-mmx7 and align stack.
    SAVE_MANAGED_ARGS_INCREASE_FRAME
    // Call `cxx_name()`.
    .ifnc \arg1, none
        mov REG_VAR(arg1), %rdi     // Pass arg1.
    .endif
    call CALLVAR(cxx_name)          // Call cxx_name(...).
    // Restore register args RDI, RSI, RDX, RCX, R8, R9, mmx0-mmx7 and return.
    RESTORE_MANAGED_ARGS_DECREASE_FRAME
    ret
END_FUNCTION \name
END_MACRO

MACRO4(JNI_SAVE_RETURN_VALUE_TRAMPOLINE, name, cxx_name, arg1, arg2)
DEFINE_FUNCTION \name
    // Save return registers and return address.
    PUSH_ARG rax
    INCREASE_FRAME /*mmx0*/ 8 + /*padding*/ 8
    movsd %xmm0, 0(%rsp)
    // Call `cxx_name()`.
    mov REG_VAR(arg1), %rdi         // Pass arg1.
    .ifnc \arg2, none
        mov REG_VAR(arg2), %rsi     // Pass arg2.
    .endif
    call CALLVAR(cxx_name)          // Call cxx_name(...).
    // Restore return registers and return.
    movsd 0(%rsp), %xmm0
    DECREASE_FRAME /*mmx0*/ 8 + /*padding*/ 8
    POP_ARG rax
    ret
END_FUNCTION \name
END_MACRO

    /*
     * Jni dlsym lookup stub for @CriticalNative.
     */

DEFINE_FUNCTION art_jni_dlsym_lookup_critical_stub
    // The hidden arg holding the tagged method (bit 0 set means GenericJNI) is RAX.
    // For Generic JNI we already have a managed frame, so we reuse the art_jni_dlsym_lookup_stub.
    testq LITERAL(1), %rax
    jnz art_jni_dlsym_lookup_stub

    // Save GPR args and method.
    PUSH_ARG r9
    PUSH_ARG r8
    PUSH_ARG rdi
    PUSH_ARG rsi
    PUSH_ARG rdx
    PUSH_ARG rcx
    PUSH_ARG rax
    // Create space for FPR args.
    INCREASE_FRAME 8 * 8
    // 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)
    // Note: It's the caller's responsibility to preserve xmm12-xmm15 as the tail call
    // to native shall always risk clobbering those.

    // Call artCriticalNativeFrameSize(method, caller_pc).
    movq %rax, %rdi       // Pass the method from hidden arg.
    movq 120(%rsp), %rsi  // Pass caller PC.
    call SYMBOL(artCriticalNativeFrameSize)

    // Restore registers.
    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 8 * 8
    POP_ARG r10  // Restore method to R10.
    POP_ARG rcx
    POP_ARG rdx
    POP_ARG rsi
    POP_ARG rdi
    POP_ARG r8
    POP_ARG r9

    // Load caller PC to R11 and redefine return PC for CFI.
    movq (%rsp), %r11
    CFI_REGISTER(%rip, %r11)

    // 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.
    INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__

    // Calculate the number of QWORDs to move.
    shrq LITERAL(3), %rax
    jz .Lcritical_skip_copy_args

    // Save RDI, RSI, RCX so that we can use them for moving stack args.
    PUSH_ARG rdi
    PUSH_ARG rsi
    PUSH_ARG rcx

    // Move the stack args.
    movq %rax, %rcx
    leaq 3 * __SIZEOF_POINTER__(%rsp), %rdi
    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS(%rdi), %rsi
    rep movsq

    // Restore RDI, RSI, RCX.
    POP_ARG rcx
    POP_ARG rsi
    POP_ARG rdi

.Lcritical_skip_copy_args:
    // Calculate the base address of the managed frame.
    leaq (%rsp, %rax, 8), %rax

    // 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. Do not update CFI while we hold the frame address in RAX and the values
    // in registers are unchanged.
    movq %r15, 192(%rax)
    movq %r14, 184(%rax)
    movq %r13, 176(%rax)
    movq %r12, 168(%rax)
    movq %r9, 160(%rax)
    movq %r8, 152(%rax)
    movq %rsi, 144(%rax)
    movq %rbp, 136(%rax)
    movq %rbx, 128(%rax)
    movq %rdx, 120(%rax)
    movq %rcx, 112(%rax)
    movq %xmm0, 16(%rax)
    movq %xmm1, 24(%rax)
    movq %xmm2, 32(%rax)
    movq %xmm3, 40(%rax)
    movq %xmm4, 48(%rax)
    movq %xmm5, 56(%rax)
    movq %xmm6, 64(%rax)
    movq %xmm7, 72(%rax)
    // Skip managed ABI callee-saves xmm12-xmm15.

    // Move the managed frame address to native callee-save register RBP and update CFI.
    movq %rax, %rbp
    CFI_EXPRESSION_BREG CFI_REG(r15), CFI_REG(rbp), 192
    CFI_EXPRESSION_BREG CFI_REG(r14), CFI_REG(rbp), 184
    CFI_EXPRESSION_BREG CFI_REG(r13), CFI_REG(rbp), 176
    CFI_EXPRESSION_BREG CFI_REG(r12), CFI_REG(rbp), 168
    // Skip args r9, r8, rsi.
    CFI_EXPRESSION_BREG CFI_REG(rbp), CFI_REG(rbp), 136
    CFI_EXPRESSION_BREG CFI_REG(rbx), CFI_REG(rbp), 128
    // Skip args rdx, rcx.
    // Skip args xmm0-xmm7.

    leaq 1(%rbp), %rax            // Prepare managed SP tagged for a GenericJNI frame.
    testl LITERAL(ACCESS_FLAGS_METHOD_IS_NATIVE), ART_METHOD_ACCESS_FLAGS_OFFSET(%r10)
    jnz .Lcritical_skip_prepare_runtime_method

    // Save the return PC for managed stack walk.
    // (When coming from a compiled stub, the correct return PC is already there.)
    movq %r11, FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%rbp)

    // Replace the target method with the SaveRefsAndArgs runtime method.
    LOAD_RUNTIME_INSTANCE r10
    movq RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET(%r10), %r10

    movq %rbp, %rax               // Prepare untagged managed SP for the runtime method.

.Lcritical_skip_prepare_runtime_method:
    // Store the method on the bottom of the managed frame.
    movq %r10, (%rbp)

    // Place (maybe tagged) managed SP in Thread::Current()->top_quick_frame.
    movq %rax, %gs:THREAD_TOP_QUICK_FRAME_OFFSET

    // Save our return PC in the padding.
    movq %r11, __SIZEOF_POINTER__(%rbp)
    CFI_EXPRESSION_BREG CFI_REG(rip), CFI_REG(rbp), __SIZEOF_POINTER__

    // Preserve the native arg register RDI in callee-save register RBX which was saved above.
    movq %rdi, %rbx

    // Call artFindNativeMethodRunnable()
    movq %gs:THREAD_SELF_OFFSET, %rdi  // pass Thread::Current()
    call SYMBOL(artFindNativeMethodRunnable)  // (Thread*)

    // Check for exception.
    test %rax, %rax
    CFI_REMEMBER_STATE
    jz .Lcritical_deliver_exception

    // Restore the native arg register RDI.
    movq %rbx, %rdi

    // Remember our return PC in R11.
    movq __SIZEOF_POINTER__(%rbp), %r11
    CFI_REGISTER(%rip, %r11)

    // Remember the frame base address in r10 but do not redefine CFI.
    movq %rbp, %r10

    // Restore the frame. We shall not need the method anymore.
    movq 16(%rbp), %xmm0
    movq 24(%rbp), %xmm1
    movq 32(%rbp), %xmm2
    movq 40(%rbp), %xmm3
    movq 48(%rbp), %xmm4
    movq 56(%rbp), %xmm5
    movq 64(%rbp), %xmm6
    movq 72(%rbp), %xmm7
    // Skip managed callee-saves xmm12-xmm15.
    movq 112(%rbp), %rcx
    movq 120(%rbp), %rdx
    RESTORE_REG_BASE rbp, rbx, 128
    // Delay restoring RBP as it's the managed frame base.
    movq 144(%rbp), %rsi
    movq 152(%rbp), %r8
    movq 160(%rbp), %r9
    RESTORE_REG_BASE rbp, r12, 168
    RESTORE_REG_BASE rbp, r13, 176
    RESTORE_REG_BASE rbp, r14, 184
    RESTORE_REG_BASE rbp, r15, 192
    // Restore RBP last.
    RESTORE_REG_BASE rbp, rbp, 136

    cmp %r10, %rsp
    je .Lcritical_skip_copy_args_back

    // Save RDI, RSI, RCX so that we can use them for moving stack args.
    PUSH_ARG rdi
    PUSH_ARG rsi
    PUSH_ARG rcx

    // Calculate the number of QWORDs to move.
    leaq -3 * __SIZEOF_POINTER__(%r10), %rcx
    subq %rsp, %rcx
    shrq LITERAL(3), %rcx

    // Move the stack args.
    leaq -__SIZEOF_POINTER__(%r10), %rsi
    leaq FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__(%r10), %rdi
    std
    rep movsq
    cld

    // Restore RDI, RSI, RCX.
    POP_ARG rcx
    POP_ARG rsi
    POP_ARG rdi

.Lcritical_skip_copy_args_back:
    // Remove the frame reservation.
    DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS - __SIZEOF_POINTER__

    // Store our return PC.
    movq %r11, (%rsp)
    CFI_REL_OFFSET(%rip, 0)

    // Do the tail call.
    jmp *%rax

.Lcritical_deliver_exception:
    CFI_RESTORE_STATE_AND_DEF_CFA %rbp, FRAME_SIZE_SAVE_REFS_AND_ARGS
    DELIVER_PENDING_EXCEPTION_FRAME_READY
END_FUNCTION 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`.)
     */

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_read_barrier, artJniReadBarrier, none

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

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE art_jni_method_start, artJniMethodStart, gs:THREAD_SELF_OFFSET

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

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE \
    art_jni_method_entry_hook, artJniMethodEntryHook, gs:THREAD_SELF_OFFSET

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

JNI_SAVE_MANAGED_ARGS_TRAMPOLINE \
    art_jni_monitored_method_start, artJniMonitoredMethodStart, gs:THREAD_SELF_OFFSET

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

JNI_SAVE_RETURN_VALUE_TRAMPOLINE art_jni_method_end, artJniMethodEnd, gs:THREAD_SELF_OFFSET, none

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

JNI_SAVE_RETURN_VALUE_TRAMPOLINE \
    art_jni_monitored_method_end, artJniMonitoredMethodEnd, gs:THREAD_SELF_OFFSET, none

    /*
     * 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:
     *     RBX holds the non-null object to lock.
     *     Callee-save registers have been saved and can be used as temporaries (except RBX).
     *     All argument registers need to be preserved.
     */

DEFINE_FUNCTION art_jni_lock_object
    LOCK_OBJECT_FAST_PATH rbx, ebp, art_jni_lock_object_no_inline
END_FUNCTION art_jni_lock_object

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

DEFINE_FUNCTION art_jni_lock_object_no_inline
    // This is also the slow path for art_jni_lock_object.
    // Save register args RDI, RSI, RDX, RCX, R8, R9, mmx0-mmx7 and align stack.
    SAVE_MANAGED_ARGS_INCREASE_FRAME
    // Call `artLockObjectFromCode()`
    movq %rbx, %rdi                       // Pass the object to lock.
    movq %gs:THREAD_SELF_OFFSET, %rsi     // Pass Thread::Current().
    call SYMBOL(artLockObjectFromCode)    // (object, Thread*)
    // Check result.
    testl %eax, %eax
    jnz   1f
    // Restore register args RDI, RSI, RDX, RCX, R8, R9, mmx0-mmx7 and return.
    RESTORE_MANAGED_ARGS_DECREASE_FRAME
    ret
    .cfi_adjust_cfa_offset MANAGED_ARGS_SAVE_SIZE
1:
    // All args are irrelevant when throwing an exception. Remove the spill area except for new
    // padding to align stack.
    DECREASE_FRAME MANAGED_ARGS_SAVE_SIZE - /*new padding*/ 8
    // Rely on the JNI transition frame constructed in the JNI stub.
    movq %gs:THREAD_SELF_OFFSET, %rdi     // Pass Thread::Current().
    call  SYMBOL(artDeliverPendingExceptionFromCode)  // (Thread*)
    movq %rax, %rdi                       // pass Context*
    call  SYMBOL(art_quick_do_long_jump)
    UNREACHABLE
END_FUNCTION 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:
     *     RBX holds the non-null object to unlock.
     *     Callee-save registers have been saved and can be used as temporaries (except RBX).
     *     Return registers RAX and mmx0 need to be preserved.
     */

DEFINE_FUNCTION art_jni_unlock_object
    movq %rax, %r12                       // Preserve RAX in a different register.
    UNLOCK_OBJECT_FAST_PATH rbx, ebp, /*saved_rax*/ r12, .Lunlock_object_jni_slow

 .Lunlock_object_jni_slow:
    movq %r12, %rax                       // Restore RAX.
    jmp  SYMBOL(art_jni_unlock_object_no_inline)
END_FUNCTION 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:
     *     RBX holds the non-null object to unlock.
     *     Callee-save registers have been saved and can be used as temporaries (except RBX).
     *     Return registers RAX and mmx0 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, rbx, gs:THREAD_SELF_OFFSET

Messung V0.5 in Prozent
C=89 H=94 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.