1%default { "chaintgt" : ".LinvokeChain" }
2    /*
3     * For polymorphic callsite, check whether the cached class pointer matches
4     * the current one. If so setup the Dalvik frame and return to the
5     * Thumb code through the link register to transfer control to the callee
6     * method through a dedicated chaining cell.
7     *
8     * The predicted chaining cell is declared in ArmLIR.h with the
9     * following layout:
10     *
11     *  typedef struct PredictedChainingCell {
12     *      u4 branch;
13     *      const ClassObject *clazz;
14     *      const Method *method;
15     *      u4 counter;
16     *  } PredictedChainingCell;
17     *
18     * Upon returning to the callsite:
19     *    - lr  : to branch to the chaining cell
20     *    - lr+2: to punt to the interpreter
21     *    - lr+4: to fully resolve the callee and may rechain.
22     *            r3 <- class
23     *            r9 <- counter
24     */
25    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
26    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
27    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
28    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
29    ldr     r9, [rSELF, #offThread_icRechainCount] @ r1 <- shared rechainCount
30    cmp     r3, r8          @ predicted class == actual class?
31#if defined(WITH_JIT_TUNING)
32    ldr     r7, .LdvmICHitCount
33#if defined(WORKAROUND_CORTEX_A9_745320)
34    /* Don't use conditional loads if the HW defect exists */
35    bne     101f
36    ldr     r10, [r7, #0]
37101:
38#else
39    ldreq   r10, [r7, #0]
40#endif
41    add     r10, r10, #1
42    streq   r10, [r7, #0]
43#endif
44    ldreqh  r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
45    ldreqh  r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
46    beq     $chaintgt   @ predicted chain is valid
47    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
48    cmp     r8, #0          @ initialized class or not
49    moveq   r1, #0
50    subne   r1, r9, #1      @ count--
51    strne   r1, [rSELF, #offThread_icRechainCount]  @ write back to thread
52    add     lr, lr, #4      @ return to fully-resolve landing pad
53    /*
54     * r1 <- count
55     * r2 <- &predictedChainCell
56     * r3 <- this->class
57     * r4 <- dPC
58     * r7 <- this->class->vtable
59     */
60    bx      lr
61