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_CODE_ITEM(rFP), %rax
    102     mov     OFF_FP_DEX_PC(rFP), %ecx
    103     leaq    CODEITEM_INSNS_OFFSET(%rax), rPC
    104     leaq    (rPC, %rcx, 2), rPC
    105     movq    rPC, OFF_FP_DEX_PC_PTR(rFP)
    106     /* Do we need to switch interpreters? */
    107     call    SYMBOL(MterpShouldSwitchInterpreters)
    108     testb   %al, %al
    109     jnz     MterpFallback
    110     /* resume execution at catch block */
    111     REFRESH_IBASE
    112     FETCH_INST
    113     GOTO_NEXT
    114     /* NOTE: no fallthrough */
    115 
    116 /*
    117  * Common handling for branches with support for Jit profiling.
    118  * On entry:
    119  *    rINST          <= signed offset
    120  *    rPROFILE       <= signed hotness countdown (expanded to 32 bits)
    121  *    condition bits <= set to establish sign of offset (use "NoFlags" entry if not)
    122  *
    123  * We have quite a few different cases for branch profiling, OSR detection and
    124  * suspend check support here.
    125  *
    126  * Taken backward branches:
    127  *    If profiling active, do hotness countdown and report if we hit zero.
    128  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    129  *    Is there a pending suspend request?  If so, suspend.
    130  *
    131  * Taken forward branches and not-taken backward branches:
    132  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    133  *
    134  * Our most common case is expected to be a taken backward branch with active jit profiling,
    135  * but no full OSR check and no pending suspend request.
    136  * Next most common case is not-taken branch with no full OSR check.
    137  *
    138  */
    139 MterpCommonTakenBranch:
    140     jg      .L_forward_branch               # don't add forward branches to hotness
    141 /*
    142  * We need to subtract 1 from positive values and we should not see 0 here,
    143  * so we may use the result of the comparison with -1.
    144  */
    145 #if JIT_CHECK_OSR != -1
    146 #  error "JIT_CHECK_OSR must be -1."
    147 #endif
    148     cmpl    $$JIT_CHECK_OSR, rPROFILE
    149     je      .L_osr_check
    150     decl    rPROFILE
    151     je      .L_add_batch                    # counted down to zero - report
    152 .L_resume_backward_branch:
    153     movq    rSELF, %rax
    154     testl   $$(THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%rax)
    155     REFRESH_IBASE
    156     leaq    (rPC, rINSTq, 2), rPC
    157     FETCH_INST
    158     jnz     .L_suspend_request_pending
    159     GOTO_NEXT
    160 
    161 .L_suspend_request_pending:
    162     EXPORT_PC
    163     movq    rSELF, OUT_ARG0
    164     call    SYMBOL(MterpSuspendCheck)       # (self)
    165     testb   %al, %al
    166     jnz     MterpFallback
    167     REFRESH_IBASE                           # might have changed during suspend
    168     GOTO_NEXT
    169 
    170 .L_no_count_backwards:
    171     cmpl    $$JIT_CHECK_OSR, rPROFILE         # possible OSR re-entry?
    172     jne     .L_resume_backward_branch
    173 .L_osr_check:
    174     EXPORT_PC
    175     movq    rSELF, OUT_ARG0
    176     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    177     movq    rINSTq, OUT_ARG2
    178     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    179     testb   %al, %al
    180     jz      .L_resume_backward_branch
    181     jmp     MterpOnStackReplacement
    182 
    183 .L_forward_branch:
    184     cmpl    $$JIT_CHECK_OSR, rPROFILE         # possible OSR re-entry?
    185     je      .L_check_osr_forward
    186 .L_resume_forward_branch:
    187     leaq    (rPC, rINSTq, 2), rPC
    188     FETCH_INST
    189     GOTO_NEXT
    190 
    191 .L_check_osr_forward:
    192     EXPORT_PC
    193     movq    rSELF, OUT_ARG0
    194     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    195     movq    rINSTq, OUT_ARG2
    196     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    197     testb   %al, %al
    198     jz      .L_resume_forward_branch
    199     jmp     MterpOnStackReplacement
    200 
    201 .L_add_batch:
    202     movl    rPROFILE, %eax
    203     movq    OFF_FP_METHOD(rFP), OUT_ARG0
    204     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    205     movw    %ax, OFF_FP_COUNTDOWN_OFFSET(rFP)
    206     movq    rSELF, OUT_ARG2
    207     call    SYMBOL(MterpAddHotnessBatch)    # (method, shadow_frame, self)
    208     movswl  %ax, rPROFILE
    209     jmp     .L_no_count_backwards
    210 
    211 /*
    212  * Entered from the conditional branch handlers when OSR check request active on
    213  * not-taken path.  All Dalvik not-taken conditional branch offsets are 2.
    214  */
    215 .L_check_not_taken_osr:
    216     EXPORT_PC
    217     movq    rSELF, OUT_ARG0
    218     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    219     movl    $$2, OUT_32_ARG2
    220     call    SYMBOL(MterpMaybeDoOnStackReplacement) # (self, shadow_frame, offset)
    221     testb   %al, %al
    222     jnz     MterpOnStackReplacement
    223     ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
    224 
    225 /*
    226  * On-stack replacement has happened, and now we've returned from the compiled method.
    227  */
    228 MterpOnStackReplacement:
    229 #if MTERP_LOGGING
    230     movq    rSELF, OUT_ARG0
    231     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    232     movl    rINST, OUT_32_ARG2
    233     call    SYMBOL(MterpLogOSR)
    234 #endif
    235     movl    $$1, %eax
    236     jmp     MterpDone
    237 
    238 /*
    239  * Bail out to reference interpreter.
    240  */
    241 MterpFallback:
    242     EXPORT_PC
    243 #if MTERP_LOGGING
    244     movq    rSELF, OUT_ARG0
    245     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    246     call    SYMBOL(MterpLogFallback)
    247 #endif
    248 MterpCommonFallback:
    249     xorl    %eax, %eax
    250     jmp     MterpDone
    251 
    252 /*
    253  * On entry:
    254  *  uint32_t* rFP  (should still be live, pointer to base of vregs)
    255  */
    256 MterpExceptionReturn:
    257     movl    $$1, %eax
    258     jmp     MterpDone
    259 MterpReturn:
    260     movq    OFF_FP_RESULT_REGISTER(rFP), %rdx
    261     movq    %rax, (%rdx)
    262     movl    $$1, %eax
    263 MterpDone:
    264 /*
    265  * At this point, we expect rPROFILE to be non-zero.  If negative, hotness is disabled or we're
    266  * checking for OSR.  If greater than zero, we might have unreported hotness to register
    267  * (the difference between the ending rPROFILE and the cached hotness counter).  rPROFILE
    268  * should only reach zero immediately after a hotness decrement, and is then reset to either
    269  * a negative special state or the new non-zero countdown value.
    270  */
    271     testl   rPROFILE, rPROFILE
    272     jle     MRestoreFrame                   # if > 0, we may have some counts to report.
    273 
    274     movl    %eax, rINST                     # stash return value
    275     /* Report cached hotness counts */
    276     movl    rPROFILE, %eax
    277     movq    OFF_FP_METHOD(rFP), OUT_ARG0
    278     leaq    OFF_FP_SHADOWFRAME(rFP), OUT_ARG1
    279     movw    %ax, OFF_FP_COUNTDOWN_OFFSET(rFP)
    280     movq    rSELF, OUT_ARG2
    281     call    SYMBOL(MterpAddHotnessBatch)    # (method, shadow_frame, self)
    282     movl    rINST, %eax                     # restore return value
    283 
    284     /* pop up frame */
    285 MRestoreFrame:
    286     addq    $$FRAME_SIZE, %rsp
    287     .cfi_adjust_cfa_offset -FRAME_SIZE
    288 
    289     /* Restore callee save register */
    290     POP %r15
    291     POP %r14
    292     POP %r13
    293     POP %r12
    294     POP %rbp
    295     POP %rbx
    296     ret
    297     .cfi_endproc
    298     SIZE(ExecuteMterpImpl,ExecuteMterpImpl)
    299