Home | History | Annotate | Download | only in arm64
      1 /*
      2  * ===========================================================================
      3  *  Common subroutines and data
      4  * ===========================================================================
      5  */
      6 
      7 
      8 /*
      9  * We've detected a condition that will result in an exception, but the exception
     10  * has not yet been thrown.  Just bail out to the reference interpreter to deal with it.
     11  * TUNING: for consistency, we may want to just go ahead and handle these here.
     12  */
     13 common_errDivideByZero:
     14     EXPORT_PC
     15 #if MTERP_LOGGING
     16     mov  x0, xSELF
     17     add  x1, xFP, #OFF_FP_SHADOWFRAME
     18     bl MterpLogDivideByZeroException
     19 #endif
     20     b MterpCommonFallback
     21 
     22 common_errArrayIndex:
     23     EXPORT_PC
     24 #if MTERP_LOGGING
     25     mov  x0, xSELF
     26     add  x1, xFP, #OFF_FP_SHADOWFRAME
     27     bl MterpLogArrayIndexException
     28 #endif
     29     b MterpCommonFallback
     30 
     31 common_errNegativeArraySize:
     32     EXPORT_PC
     33 #if MTERP_LOGGING
     34     mov  x0, xSELF
     35     add  x1, xFP, #OFF_FP_SHADOWFRAME
     36     bl MterpLogNegativeArraySizeException
     37 #endif
     38     b MterpCommonFallback
     39 
     40 common_errNoSuchMethod:
     41     EXPORT_PC
     42 #if MTERP_LOGGING
     43     mov  x0, xSELF
     44     add  x1, xFP, #OFF_FP_SHADOWFRAME
     45     bl MterpLogNoSuchMethodException
     46 #endif
     47     b MterpCommonFallback
     48 
     49 common_errNullObject:
     50     EXPORT_PC
     51 #if MTERP_LOGGING
     52     mov  x0, xSELF
     53     add  x1, xFP, #OFF_FP_SHADOWFRAME
     54     bl MterpLogNullObjectException
     55 #endif
     56     b MterpCommonFallback
     57 
     58 common_exceptionThrown:
     59     EXPORT_PC
     60 #if MTERP_LOGGING
     61     mov  x0, xSELF
     62     add  x1, xFP, #OFF_FP_SHADOWFRAME
     63     bl MterpLogExceptionThrownException
     64 #endif
     65     b MterpCommonFallback
     66 
     67 MterpSuspendFallback:
     68     EXPORT_PC
     69 #if MTERP_LOGGING
     70     mov  x0, xSELF
     71     add  x1, xFP, #OFF_FP_SHADOWFRAME
     72     ldr  x2, [xSELF, #THREAD_FLAGS_OFFSET]
     73     bl MterpLogSuspendFallback
     74 #endif
     75     b MterpCommonFallback
     76 
     77 /*
     78  * If we're here, something is out of the ordinary.  If there is a pending
     79  * exception, handle it.  Otherwise, roll back and retry with the reference
     80  * interpreter.
     81  */
     82 MterpPossibleException:
     83     ldr     x0, [xSELF, #THREAD_EXCEPTION_OFFSET]
     84     cbz     x0, MterpFallback                       // If not, fall back to reference interpreter.
     85     /* intentional fallthrough - handle pending exception. */
     86 /*
     87  * On return from a runtime helper routine, we've found a pending exception.
     88  * Can we handle it here - or need to bail out to caller?
     89  *
     90  */
     91 MterpException:
     92     mov     x0, xSELF
     93     add     x1, xFP, #OFF_FP_SHADOWFRAME
     94     bl      MterpHandleException                    // (self, shadow_frame)
     95     cbz     w0, MterpExceptionReturn                // no local catch, back to caller.
     96     ldr     x0, [xFP, #OFF_FP_DEX_INSTRUCTIONS]
     97     ldr     w1, [xFP, #OFF_FP_DEX_PC]
     98     ldr     xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET]
     99     add     xPC, x0, x1, lsl #1                     // generate new dex_pc_ptr
    100     /* Do we need to switch interpreters? */
    101     bl      MterpShouldSwitchInterpreters
    102     cbnz    w0, MterpFallback
    103     /* resume execution at catch block */
    104     EXPORT_PC
    105     FETCH_INST
    106     GET_INST_OPCODE ip
    107     GOTO_OPCODE ip
    108     /* NOTE: no fallthrough */
    109 /*
    110  * Common handling for branches with support for Jit profiling.
    111  * On entry:
    112  *    wINST          <= signed offset
    113  *    wPROFILE       <= signed hotness countdown (expanded to 32 bits)
    114  *    condition bits <= set to establish sign of offset (use "NoFlags" entry if not)
    115  *
    116  * We have quite a few different cases for branch profiling, OSR detection and
    117  * suspend check support here.
    118  *
    119  * Taken backward branches:
    120  *    If profiling active, do hotness countdown and report if we hit zero.
    121  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    122  *    Is there a pending suspend request?  If so, suspend.
    123  *
    124  * Taken forward branches and not-taken backward branches:
    125  *    If in osr check mode, see if our target is a compiled loop header entry and do OSR if so.
    126  *
    127  * Our most common case is expected to be a taken backward branch with active jit profiling,
    128  * but no full OSR check and no pending suspend request.
    129  * Next most common case is not-taken branch with no full OSR check.
    130  *
    131  */
    132 MterpCommonTakenBranchNoFlags:
    133     cmp     wINST, #0
    134     b.gt    .L_forward_branch           // don't add forward branches to hotness
    135     tbnz    wPROFILE, #31, .L_no_count_backwards  // go if negative
    136     subs    wPROFILE, wPROFILE, #1      // countdown
    137     b.eq    .L_add_batch                // counted down to zero - report
    138 .L_resume_backward_branch:
    139     ldr     lr, [xSELF, #THREAD_FLAGS_OFFSET]
    140     add     w2, wINST, wINST            // w2<- byte offset
    141     FETCH_ADVANCE_INST_RB w2            // update rPC, load wINST
    142     REFRESH_IBASE
    143     ands    lr, lr, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
    144     b.ne    .L_suspend_request_pending
    145     GET_INST_OPCODE ip                  // extract opcode from wINST
    146     GOTO_OPCODE ip                      // jump to next instruction
    147 
    148 .L_suspend_request_pending:
    149     EXPORT_PC
    150     mov     x0, xSELF
    151     bl      MterpSuspendCheck           // (self)
    152     cbnz    x0, MterpFallback
    153     REFRESH_IBASE                       // might have changed during suspend
    154     GET_INST_OPCODE ip                  // extract opcode from wINST
    155     GOTO_OPCODE ip                      // jump to next instruction
    156 
    157 .L_no_count_backwards:
    158     cmp     wPROFILE, #JIT_CHECK_OSR    // possible OSR re-entry?
    159     b.ne    .L_resume_backward_branch
    160     mov     x0, xSELF
    161     add     x1, xFP, #OFF_FP_SHADOWFRAME
    162     mov     x2, xINST
    163     EXPORT_PC
    164     bl      MterpMaybeDoOnStackReplacement  // (self, shadow_frame, offset)
    165     cbnz    x0, MterpOnStackReplacement
    166     b       .L_resume_backward_branch
    167 
    168 .L_forward_branch:
    169     cmp     wPROFILE, #JIT_CHECK_OSR    // possible OSR re-entry?
    170     b.eq    .L_check_osr_forward
    171 .L_resume_forward_branch:
    172     add     w2, wINST, wINST            // w2<- byte offset
    173     FETCH_ADVANCE_INST_RB w2            // update rPC, load wINST
    174     GET_INST_OPCODE ip                  // extract opcode from wINST
    175     GOTO_OPCODE ip                      // jump to next instruction
    176 
    177 .L_check_osr_forward:
    178     mov     x0, xSELF
    179     add     x1, xFP, #OFF_FP_SHADOWFRAME
    180     mov     x2, xINST
    181     EXPORT_PC
    182     bl      MterpMaybeDoOnStackReplacement  // (self, shadow_frame, offset)
    183     cbnz    x0, MterpOnStackReplacement
    184     b       .L_resume_forward_branch
    185 
    186 .L_add_batch:
    187     add     x1, xFP, #OFF_FP_SHADOWFRAME
    188     strh    wPROFILE, [x1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET]
    189     ldr     x0, [xFP, #OFF_FP_METHOD]
    190     mov     x2, xSELF
    191     bl      MterpAddHotnessBatch        // (method, shadow_frame, self)
    192     mov     wPROFILE, w0                // restore new hotness countdown to wPROFILE
    193     b       .L_no_count_backwards
    194 
    195 /*
    196  * Entered from the conditional branch handlers when OSR check request active on
    197  * not-taken path.  All Dalvik not-taken conditional branch offsets are 2.
    198  */
    199 .L_check_not_taken_osr:
    200     mov     x0, xSELF
    201     add     x1, xFP, #OFF_FP_SHADOWFRAME
    202     mov     x2, #2
    203     EXPORT_PC
    204     bl      MterpMaybeDoOnStackReplacement  // (self, shadow_frame, offset)
    205     cbnz    x0, MterpOnStackReplacement
    206     FETCH_ADVANCE_INST 2
    207     GET_INST_OPCODE ip                  // extract opcode from wINST
    208     GOTO_OPCODE ip                      // jump to next instruction
    209 
    210 
    211 /*
    212  * Check for suspend check request.  Assumes wINST already loaded, xPC advanced and
    213  * still needs to get the opcode and branch to it, and flags are in lr.
    214  */
    215 MterpCheckSuspendAndContinue:
    216     ldr     xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET]  // refresh xIBASE
    217     ands    w7, w7, #THREAD_SUSPEND_OR_CHECKPOINT_REQUEST
    218     b.ne    check1
    219     GET_INST_OPCODE ip                  // extract opcode from wINST
    220     GOTO_OPCODE ip                      // jump to next instruction
    221 check1:
    222     EXPORT_PC
    223     mov     x0, xSELF
    224     bl      MterpSuspendCheck           // (self)
    225     cbnz    x0, MterpFallback           // Something in the environment changed, switch interpreters
    226     GET_INST_OPCODE ip                  // extract opcode from wINST
    227     GOTO_OPCODE ip                      // jump to next instruction
    228 
    229 /*
    230  * On-stack replacement has happened, and now we've returned from the compiled method.
    231  */
    232 MterpOnStackReplacement:
    233 #if MTERP_LOGGING
    234     mov  x0, xSELF
    235     add  x1, xFP, #OFF_FP_SHADOWFRAME
    236     sxtw x2, wINST
    237     bl MterpLogOSR
    238 #endif
    239     mov  x0, #1                         // Signal normal return
    240     b    MterpDone
    241 
    242 /*
    243  * Bail out to reference interpreter.
    244  */
    245 MterpFallback:
    246     EXPORT_PC
    247 #if MTERP_LOGGING
    248     mov  x0, xSELF
    249     add  x1, xFP, #OFF_FP_SHADOWFRAME
    250     bl MterpLogFallback
    251 #endif
    252 MterpCommonFallback:
    253     mov     x0, #0                                  // signal retry with reference interpreter.
    254     b       MterpDone
    255 
    256 /*
    257  * We pushed some registers on the stack in ExecuteMterpImpl, then saved
    258  * SP and LR.  Here we restore SP, restore the registers, and then restore
    259  * LR to PC.
    260  *
    261  * On entry:
    262  *  uint32_t* xFP  (should still be live, pointer to base of vregs)
    263  */
    264 MterpExceptionReturn:
    265     mov     x0, #1                                  // signal return to caller.
    266     b MterpDone
    267 MterpReturn:
    268     ldr     x2, [xFP, #OFF_FP_RESULT_REGISTER]
    269     str     x0, [x2]
    270     mov     x0, #1                                  // signal return to caller.
    271 MterpDone:
    272 /*
    273  * At this point, we expect wPROFILE to be non-zero.  If negative, hotness is disabled or we're
    274  * checking for OSR.  If greater than zero, we might have unreported hotness to register
    275  * (the difference between the ending wPROFILE and the cached hotness counter).  wPROFILE
    276  * should only reach zero immediately after a hotness decrement, and is then reset to either
    277  * a negative special state or the new non-zero countdown value.
    278  */
    279     cmp     wPROFILE, #0
    280     bgt     MterpProfileActive                      // if > 0, we may have some counts to report.
    281     .cfi_remember_state
    282     RESTORE_TWO_REGS                fp, lr, 64
    283     RESTORE_TWO_REGS                xPC, xFP, 48
    284     RESTORE_TWO_REGS                xSELF, xINST, 32
    285     RESTORE_TWO_REGS                xIBASE, xREFS, 16
    286     RESTORE_TWO_REGS_DECREASE_FRAME xPROFILE, x27, 80
    287     ret
    288     .cfi_restore_state                              // Reset unwind info so following code unwinds.
    289     .cfi_def_cfa_offset 80                          // workaround for clang bug: 31975598
    290 
    291 MterpProfileActive:
    292     mov     xINST, x0                               // stash return value
    293     /* Report cached hotness counts */
    294     ldr     x0, [xFP, #OFF_FP_METHOD]
    295     add     x1, xFP, #OFF_FP_SHADOWFRAME
    296     mov     x2, xSELF
    297     strh    wPROFILE, [x1, #SHADOWFRAME_HOTNESS_COUNTDOWN_OFFSET]
    298     bl      MterpAddHotnessBatch                    // (method, shadow_frame, self)
    299     mov     x0, xINST                               // restore return value
    300     RESTORE_TWO_REGS                fp, lr, 64
    301     RESTORE_TWO_REGS                xPC, xFP, 48
    302     RESTORE_TWO_REGS                xSELF, xINST, 32
    303     RESTORE_TWO_REGS                xIBASE, xREFS, 16
    304     RESTORE_TWO_REGS_DECREASE_FRAME xPROFILE, x27, 80
    305     ret
    306 
    307