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