Home | History | Annotate | Download | only in x86_64
      1 /*
      2  * ===========================================================================
      3  *  Common subroutines and data
      4  * ===========================================================================
      5  */
      6 
      7     .text
      8     .align  2
      9 
     10 /*
     11  * We've detected a condition that will result in an exception, but the exception
     12  * has not yet been thrown.  Just bail out to the reference interpreter to deal with it.
     13  * TUNING: for consistency, we may want to just go ahead and handle these here.
     14  */
     15 common_errDivideByZero:
     16     EXPORT_PC
     17 #if MTERP_LOGGING
     18     movq    rSELF, OUT_ARG0
     19     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     20     call    SYMBOL(MterpLogDivideByZeroException)
     21 #endif
     22     jmp     MterpCommonFallback
     23 
     24 common_errArrayIndex:
     25     EXPORT_PC
     26 #if MTERP_LOGGING
     27     movq    rSELF, OUT_ARG0
     28     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     29     call    SYMBOL(MterpLogArrayIndexException)
     30 #endif
     31     jmp     MterpCommonFallback
     32 
     33 common_errNegativeArraySize:
     34     EXPORT_PC
     35 #if MTERP_LOGGING
     36     movq    rSELF, OUT_ARG0
     37     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     38     call    SYMBOL(MterpLogNegativeArraySizeException)
     39 #endif
     40     jmp     MterpCommonFallback
     41 
     42 common_errNoSuchMethod:
     43     EXPORT_PC
     44 #if MTERP_LOGGING
     45     movq    rSELF, OUT_ARG0
     46     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     47     call    SYMBOL(MterpLogNoSuchMethodException)
     48 #endif
     49     jmp     MterpCommonFallback
     50 
     51 common_errNullObject:
     52     EXPORT_PC
     53 #if MTERP_LOGGING
     54     movq    rSELF, OUT_ARG0
     55     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     56     call    SYMBOL(MterpLogNullObjectException)
     57 #endif
     58     jmp     MterpCommonFallback
     59 
     60 common_exceptionThrown:
     61     EXPORT_PC
     62 #if MTERP_LOGGING
     63     movq    rSELF, OUT_ARG0
     64     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     65     call    SYMBOL(MterpLogExceptionThrownException)
     66 #endif
     67     jmp     MterpCommonFallback
     68 
     69 MterpSuspendFallback:
     70     EXPORT_PC
     71 #if MTERP_LOGGING
     72     movq    rSELF, OUT_ARG0
     73     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     74     movl    THREAD_FLAGS_OFFSET(OUT_ARG0), OUT_32_ARG2
     75     call    SYMBOL(MterpLogSuspendFallback)
     76 #endif
     77     jmp     MterpCommonFallback
     78 
     79 /*
     80  * If we're here, something is out of the ordinary.  If there is a pending
     81  * exception, handle it.  Otherwise, roll back and retry with the reference
     82  * interpreter.
     83  */
     84 MterpPossibleException:
     85     movq    rSELF, %rcx
     86     cmpq    $$0, THREAD_EXCEPTION_OFFSET(%rcx)
     87     jz      MterpFallback
     88     /* intentional fallthrough - handle pending exception. */
     89 
     90 /*
     91  * On return from a runtime helper routine, we've found a pending exception.
     92  * Can we handle it here - or need to bail out to caller?
     93  *
     94  */
     95 MterpException:
     96     movq    rSELF, OUT_ARG0
     97     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
     98     call    SYMBOL(MterpHandleException)
     99     testb   %al, %al
    100     jz      MterpExceptionReturn
    101     movq    OFF_FP_DEX_INSTRUCTIONS(rFP), %rax
    102     mov     OFF_FP_DEX_PC(rFP), %ecx
    103     leaq    (%rax, %rcx, 2), rPC
    104     movq    rPC, OFF_FP_DEX_PC_PTR(rFP)
    105     /* Do we need to switch interpreters? */
    106     call    SYMBOL(MterpShouldSwitchInterpreters)
    107     testb   %al, %al
    108     jnz     MterpFallback
    109     /* resume execution at catch block */
    110     REFRESH_IBASE
    111     FETCH_INST
    112     GOTO_NEXT
    113     /* NOTE: no fallthrough */
    114 
    115 /*
    116  * Common handling for branches with support for Jit profiling.
    117  * On entry:
    118  *    rINST          <= signed offset
    119  *    rPROFILE       <= signed hotness countdown (expanded to 32 bits)
    120  *    condition bits <= set to establish sign of offset (use "NoFlags" entry if not)
    121  *
    122  * We have quite a few different cases for branch profiling, OSR detection and
    123  * suspend check support here.
    124  *
    125  * Taken backward branches:
    126  *    If profiling active, do hotness countdown and report if we hit zero.
    127  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    128  *    Is there a pending suspend request?  If so, suspend.
    129  *
    130  * Taken forward branches and not-taken backward branches:
    131  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    132  *
    133  * Our most common case is expected to be a taken backward branch with active jit profiling,
    134  * but no full OSR check and no pending suspend request.
    135  * Next most common case is not-taken branch with no full OSR check.
    136  *
    137  */
    138 MterpCommonTakenBranch:
    139     jg      .L_forward_branch               # don't add forward branches to hotness
    140 /*
    141  * We need to subtract 1 from positive values and we should not see 0 here,
    142  * so we may use the result of the comparison with -1.
    143  */
    144 #if JIT_CHECK_OSR != -1
    145 #  error "JIT_CHECK_OSR must be -1."
    146 #endif
    147     cmpl    $$JIT_CHECK_OSR, rPROFILE
    148     je      .L_osr_check
    149     decl    rPROFILE
    150     je      .L_add_batch                    # counted down to zero - report
    151 .L_resume_backward_branch:
    152     movq    rSELF, %rax
    153     testl   $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%rax)
    154     REFRESH_IBASE_REG %rax
    155     leaq    (rPC, rINSTq, 2), rPC
    156     FETCH_INST
    157     jnz     .L_suspend_request_pending
    158     GOTO_NEXT
    159 
    160 .L_suspend_request_pending:
    161     EXPORT_PC
    162     movq    rSELF, OUT_ARG0
    163     call    SYMBOL(MterpSuspendCheck)       # (self)
    164     testb   %al, %al
    165     jnz     MterpFallback
    166     REFRESH_IBASE                           # might have changed during suspend
    167     GOTO_NEXT
    168 
    169 .L_no_count_backwards:
    170     cmpl    $$JIT_CHECK_OSR, rPROFILE         # possible OSR re-entry?
    171     jne     .L_resume_backward_branch
    172 .L_osr_check:
    173     EXPORT_PC
    174     movq    rSELF, OUT_ARG0
    175     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    176     movq    rINSTq, OUT_ARG2
    177     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    178     testb   %al, %al
    179     jz      .L_resume_backward_branch
    180     jmp     MterpOnStackReplacement
    181 
    182 .L_forward_branch:
    183     cmpl    $$JIT_CHECK_OSR, rPROFILE         # possible OSR re-entry?
    184     je      .L_check_osr_forward
    185 .L_resume_forward_branch:
    186     leaq    (rPC, rINSTq, 2), rPC
    187     FETCH_INST
    188     GOTO_NEXT
    189 
    190 .L_check_osr_forward:
    191     EXPORT_PC
    192     movq    rSELF, OUT_ARG0
    193     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    194     movq    rINSTq, OUT_ARG2
    195     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    196     testb   %al, %al
    197     jz      .L_resume_forward_branch
    198     jmp     MterpOnStackReplacement
    199 
    200 .L_add_batch:
    201     movl    rPROFILE, %eax
    202     movq    OFF_FP_METHOD(rFP), OUT_ARG0
    203     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    204     movw    %ax, OFF_FP_COUNTDOWN_OFFSET(rFP)
    205     movq    rSELF, OUT_ARG2
    206     call    SYMBOL(MterpAddHotnessBatch)    # (method, shadow_frame, self)
    207     movswl  %ax, rPROFILE
    208     jmp     .L_no_count_backwards
    209 
    210 /*
    211  * Entered from the conditional branch handlers when OSR check request active on
    212  * not-taken path.  All Dalvik not-taken conditional branch offsets are 2.
    213  */
    214 .L_check_not_taken_osr:
    215     EXPORT_PC
    216     movq    rSELF, OUT_ARG0
    217     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    218     movl    $$2, OUT_32_ARG2
    219     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    220     testb   %al, %al
    221     jnz     MterpOnStackReplacement
    222     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
    223 
    224 /*
    225  * On-stack replacement has happened, and now we've returned from the compiled method.
    226  */
    227 MterpOnStackReplacement:
    228 #if MTERP_LOGGING
    229     movq    rSELF, OUT_ARG0
    230     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    231     movl    rINST, OUT_32_ARG2
    232     call    SYMBOL(MterpLogOSR)
    233 #endif
    234     movl    $$1, %eax
    235     jmp     MterpDone
    236 
    237 /*
    238  * Bail out to reference interpreter.
    239  */
    240 MterpFallback:
    241     EXPORT_PC
    242 #if MTERP_LOGGING
    243     movq    rSELF, OUT_ARG0
    244     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    245     call    SYMBOL(MterpLogFallback)
    246 #endif
    247 MterpCommonFallback:
    248     xorl    %eax, %eax
    249     jmp     MterpDone
    250 
    251 /*
    252  * On entry:
    253  *  uint32_t* rFP  (should still be live, pointer to base of vregs)
    254  */
    255 MterpExceptionReturn:
    256     movl    $$1, %eax
    257     jmp     MterpDone
    258 MterpReturn:
    259     movq    OFF_FP_RESULT_REGISTER(rFP), %rdx
    260     movq    %rax, (%rdx)
    261     movl    $$1, %eax
    262 MterpDone:
    263 /*
    264  * At this point, we expect rPROFILE to be non-zero.  If negative, hotness is disabled or we're
    265  * checking for OSR.  If greater than zero, we might have unreported hotness to register
    266  * (the difference between the ending rPROFILE and the cached hotness counter).  rPROFILE
    267  * should only reach zero immediately after a hotness decrement, and is then reset to either
    268  * a negative special state or the new non-zero countdown value.
    269  */
    270     testl   rPROFILE, rPROFILE
    271     jle     MRestoreFrame                   # if > 0, we may have some counts to report.
    272 
    273     movl    %eax, rINST                     # stash return value
    274     /* Report cached hotness counts */
    275     movl    rPROFILE, %eax
    276     movq    OFF_FP_METHOD(rFP), OUT_ARG0
    277     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    278     movw    %ax, OFF_FP_COUNTDOWN_OFFSET(rFP)
    279     movq    rSELF, OUT_ARG2
    280     call    SYMBOL(MterpAddHotnessBatch)    # (method, shadow_frame, self)
    281     movl    rINST, %eax                     # restore return value
    282 
    283     /* pop up frame */
    284 MRestoreFrame:
    285     addq    $$FRAME_SIZE, %rsp
    286     .cfi_adjust_cfa_offset -FRAME_SIZE
    287 
    288     /* Restore callee save register */
    289     POP %r15
    290     POP %r14
    291     POP %r13
    292     POP %r12
    293     POP %rbp
    294     POP %rbx
    295     ret
    296     .cfi_endproc
    297     SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
    298