InlineTransformation.cpp revision 18fba346582c08d81aa96d9508c0e935bad5f36f
17a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng/*
27a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * Copyright (C) 2010 The Android Open Source Project
37a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *
47a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * Licensed under the Apache License, Version 2.0 (the "License");
57a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * you may not use this file except in compliance with the License.
67a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * You may obtain a copy of the License at
77a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *
87a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *      http://www.apache.org/licenses/LICENSE-2.0
97a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *
107a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * Unless required by applicable law or agreed to in writing, software
117a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * distributed under the License is distributed on an "AS IS" BASIS,
127a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * See the License for the specific language governing permissions and
147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * limitations under the License.
157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng */
167a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
177a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#include "Dalvik.h"
187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#include "Dataflow.h"
19df4daaf8f41e3dcaa8221f54273338160dd43138Dan Bornstein#include "libdex/DexOpcodes.h"
207a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
217a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng/* Convert the reg id from the callee to the original id passed by the caller */
227a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic inline u4 convertRegId(const DecodedInstruction *invoke,
237a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                              const Method *calleeMethod,
247a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                              int calleeRegId, bool isRange)
257a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* The order in the original arg passing list */
277a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    int rank = calleeRegId -
287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng               (calleeMethod->registersSize - calleeMethod->insSize);
297a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    assert(rank >= 0);
307a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (!isRange) {
317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return invoke->arg[rank];
327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    } else {
337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return invoke->vC + rank;
347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
377a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic void inlineGetter(CompilationUnit *cUnit,
387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         const Method *calleeMethod,
397a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         MIR *invokeMIR,
407a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         BasicBlock *invokeBB,
417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         bool isPredicted,
427a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         bool isRange)
437a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
447a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    BasicBlock *moveResultBB = invokeBB->fallThrough;
457a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    MIR *moveResultMIR = moveResultBB->firstMIRInsn;
46fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    MIR *newGetterMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true);
477a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    DecodedInstruction getterInsn;
487a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
49543223954993a19fa96670692bc7aa55d851966bDan Bornstein    dexDecodeInstruction(calleeMethod->insns, &getterInsn);
507a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
517a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &getterInsn))
527a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
537a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
547a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /*
557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * Some getters (especially invoked through interface) are not followed
567a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * by a move result.
577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     */
587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if ((moveResultMIR == NULL) ||
599a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        (moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT &&
609a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT_OBJECT &&
619a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein         moveResultMIR->dalvikInsn.opcode != OP_MOVE_RESULT_WIDE)) {
627a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
659a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    int dfFlags = dvmCompilerDataFlowAttributes[getterInsn.opcode];
667a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
677a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Expecting vA to be the destination register */
6852d4cd28a5d6d946934704e11e1d41450c10aa05Ben Cheng    if (dfFlags & (DF_UA | DF_UA_WIDE)) {
699a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        LOGE("opcode %d has DF_UA set (not expected)", getterInsn.opcode);
707a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        dvmAbort();
717a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
727a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
737a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dfFlags & DF_UB) {
747a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        getterInsn.vB = convertRegId(&invokeMIR->dalvikInsn, calleeMethod,
757a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     getterInsn.vB, isRange);
767a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
777a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dfFlags & DF_UC) {
797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        getterInsn.vC = convertRegId(&invokeMIR->dalvikInsn, calleeMethod,
807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     getterInsn.vC, isRange);
817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    getterInsn.vA = moveResultMIR->dalvikInsn.vA;
847a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
857a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Now setup the Dalvik instruction with converted src/dst registers */
867a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newGetterMIR->dalvikInsn = getterInsn;
877a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
88e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein    newGetterMIR->width = dexGetWidthFromOpcode(getterInsn.opcode);
897a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
907a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newGetterMIR->OptimizationFlags |= MIR_CALLEE;
917a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
927a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /*
937a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * If the getter instruction is about to raise any exception, punt to the
947a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * interpreter and re-execute the invoke.
957a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     */
967a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newGetterMIR->offset = invokeMIR->offset;
977a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
987a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newGetterMIR->meta.calleeMethod = calleeMethod;
997a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1007a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, newGetterMIR);
1017a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1027a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (isPredicted) {
103fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
1047a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        *invokeMIRSlow = *invokeMIR;
1059a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
1067a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1077a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        /* Use vC to denote the first argument (ie this) */
1087a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if (!isRange) {
1097a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            invokeMIR->dalvikInsn.vC = invokeMIRSlow->dalvikInsn.arg[0];
1107a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
1117a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1127a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        moveResultMIR->OptimizationFlags |= MIR_INLINED_PRED;
1137a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        dvmCompilerInsertMIRAfter(invokeBB, newGetterMIR, invokeMIRSlow);
1157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED;
1167a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
1177a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        gDvmJit.invokePolyGetterInlined++;
1187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
1197a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    } else {
1207a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        invokeMIR->OptimizationFlags |= MIR_INLINED;
1217a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        moveResultMIR->OptimizationFlags |= MIR_INLINED;
1227a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
1237a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        gDvmJit.invokeMonoGetterInlined++;
1247a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
1257a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
1267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1277a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    return;
1287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
1297a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1307a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic void inlineSetter(CompilationUnit *cUnit,
1317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         const Method *calleeMethod,
1327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         MIR *invokeMIR,
1337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         BasicBlock *invokeBB,
1347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         bool isPredicted,
1357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                         bool isRange)
1367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
137fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    MIR *newSetterMIR = (MIR *)dvmCompilerNew(sizeof(MIR), true);
1387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    DecodedInstruction setterInsn;
1397a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
140543223954993a19fa96670692bc7aa55d851966bDan Bornstein    dexDecodeInstruction(calleeMethod->insns, &setterInsn);
1417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1427a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &setterInsn))
1437a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
1447a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    int dfFlags = dvmCompilerDataFlowAttributes[setterInsn.opcode];
1467a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
14752d4cd28a5d6d946934704e11e1d41450c10aa05Ben Cheng    if (dfFlags & (DF_UA | DF_UA_WIDE)) {
1487a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        setterInsn.vA = convertRegId(&invokeMIR->dalvikInsn, calleeMethod,
1497a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     setterInsn.vA, isRange);
1507a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1517a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
1527a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1537a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dfFlags & DF_UB) {
1547a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        setterInsn.vB = convertRegId(&invokeMIR->dalvikInsn, calleeMethod,
1557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     setterInsn.vB, isRange);
1567a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
1587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1597a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dfFlags & DF_UC) {
1607a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        setterInsn.vC = convertRegId(&invokeMIR->dalvikInsn, calleeMethod,
1617a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     setterInsn.vC, isRange);
1627a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
1637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Now setup the Dalvik instruction with converted src/dst registers */
1657a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newSetterMIR->dalvikInsn = setterInsn;
1667a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
167e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein    newSetterMIR->width = dexGetWidthFromOpcode(setterInsn.opcode);
1687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1697a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newSetterMIR->OptimizationFlags |= MIR_CALLEE;
1707a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1717a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /*
1727a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * If the setter instruction is about to raise any exception, punt to the
1737a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * interpreter and re-execute the invoke.
1747a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     */
1757a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newSetterMIR->offset = invokeMIR->offset;
1767a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1777a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    newSetterMIR->meta.calleeMethod = calleeMethod;
1787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, newSetterMIR);
1807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (isPredicted) {
182fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
1837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        *invokeMIRSlow = *invokeMIR;
1849a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
1857a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1867a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        /* Use vC to denote the first argument (ie this) */
1877a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if (!isRange) {
1887a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            invokeMIR->dalvikInsn.vC = invokeMIRSlow->dalvikInsn.arg[0];
1897a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
1907a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
1917a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        dvmCompilerInsertMIRAfter(invokeBB, newSetterMIR, invokeMIRSlow);
1927a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED;
1937a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
1947a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        gDvmJit.invokePolySetterInlined++;
1957a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
1967a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    } else {
19733c1cf94f41ee042709e3c7b83f189970a637da2Ben Cheng        /*
19833c1cf94f41ee042709e3c7b83f189970a637da2Ben Cheng         * The invoke becomes no-op so it needs an explicit branch to jump to
19933c1cf94f41ee042709e3c7b83f189970a637da2Ben Cheng         * the chaining cell.
20033c1cf94f41ee042709e3c7b83f189970a637da2Ben Cheng         */
20133c1cf94f41ee042709e3c7b83f189970a637da2Ben Cheng        invokeBB->needFallThroughBranch = true;
2027a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        invokeMIR->OptimizationFlags |= MIR_INLINED;
2037a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#if defined(WITH_JIT_TUNING)
2047a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        gDvmJit.invokeMonoSetterInlined++;
2057a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng#endif
2067a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
2077a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2087a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    return;
2097a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
2107a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2117a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic void tryInlineSingletonCallsite(CompilationUnit *cUnit,
2127a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                       const Method *calleeMethod,
2137a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                       MIR *invokeMIR,
2147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                       BasicBlock *invokeBB,
2157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                       bool isRange)
2167a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
2177a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Not a Java method */
2187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dvmIsNativeMethod(calleeMethod)) return;
2197a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2207a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    CompilerMethodStats *methodStats =
2217a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        dvmCompilerAnalyzeMethodBody(calleeMethod, true);
2227a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2237a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Empty callee - do nothing */
2247a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (methodStats->attributes & METHOD_IS_EMPTY) {
2257a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        /* The original invoke instruction is effectively turned into NOP */
2267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        invokeMIR->OptimizationFlags |= MIR_INLINED;
22723608ab40900463fc5c8461671ba3aa5d0a4260eBen Cheng        /*
22823608ab40900463fc5c8461671ba3aa5d0a4260eBen Cheng         * Need to insert an explicit branch to catch the falling knife (into
22923608ab40900463fc5c8461671ba3aa5d0a4260eBen Cheng         * the PC reconstruction or chaining cell).
23023608ab40900463fc5c8461671ba3aa5d0a4260eBen Cheng         */
23123608ab40900463fc5c8461671ba3aa5d0a4260eBen Cheng        invokeBB->needFallThroughBranch = true;
2327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
2347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (methodStats->attributes & METHOD_IS_GETTER) {
2367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, isRange);
2377a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    } else if (methodStats->attributes & METHOD_IS_SETTER) {
2397a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, isRange);
2407a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
2427a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
2437a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2447a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic void inlineEmptyVirtualCallee(CompilationUnit *cUnit,
2457a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     const Method *calleeMethod,
2467a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     MIR *invokeMIR,
2477a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     BasicBlock *invokeBB)
2487a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
249fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true);
2507a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    *invokeMIRSlow = *invokeMIR;
2519a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    invokeMIR->dalvikInsn.opcode = kMirOpCheckInlinePrediction;
2527a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2537a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, invokeMIRSlow);
2547a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED;
2557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
2567a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2577a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengstatic void tryInlineVirtualCallsite(CompilationUnit *cUnit,
2587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     const Method *calleeMethod,
2597a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     MIR *invokeMIR,
2607a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     BasicBlock *invokeBB,
2617a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     bool isRange)
2627a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
2637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Not a Java method */
2647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (dvmIsNativeMethod(calleeMethod)) return;
2657a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2667a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    CompilerMethodStats *methodStats =
2677a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        dvmCompilerAnalyzeMethodBody(calleeMethod, true);
2687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2697a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /* Empty callee - do nothing by checking the clazz pointer */
2707a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (methodStats->attributes & METHOD_IS_EMPTY) {
2717a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        inlineEmptyVirtualCallee(cUnit, calleeMethod, invokeMIR, invokeBB);
2727a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2737a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
2747a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2757a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    if (methodStats->attributes & METHOD_IS_GETTER) {
2767a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, isRange);
2777a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    } else if (methodStats->attributes & METHOD_IS_SETTER) {
2797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, isRange);
2807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        return;
2817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
2827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
2837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2847a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
2857a2697d327936e20ef5484f7819e2e4bf91c891fBen Chengvoid dvmCompilerInlineMIR(CompilationUnit *cUnit)
2867a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{
2877a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    bool isRange = false;
28800603079b8723b32c955513eae63a8f97898074dBen Cheng    GrowableListIterator iterator;
2897a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
29000603079b8723b32c955513eae63a8f97898074dBen Cheng    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
2917a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    /*
2927a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     * Analyze the basic block containing an invoke to see if it can be inlined
2937a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng     */
29400603079b8723b32c955513eae63a8f97898074dBen Cheng    while (true) {
29500603079b8723b32c955513eae63a8f97898074dBen Cheng        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
29600603079b8723b32c955513eae63a8f97898074dBen Cheng        if (bb == NULL) break;
2977a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if (bb->blockType != kDalvikByteCode)
2987a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            continue;
2997a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        MIR *lastMIRInsn = bb->lastMIRInsn;
3009a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        int opcode = lastMIRInsn->dalvikInsn.opcode;
301e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein        int flags = dexGetFlagsFromOpcode(opcode);
3027a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3037a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        /* No invoke - continue */
3047a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if ((flags & kInstrInvoke) == 0)
3057a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            continue;
3067a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
30718fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        /* Disable inlining when doing method tracing */
30818fba346582c08d81aa96d9508c0e935bad5f36fbuzbee        if (gDvmJit.methodTraceSupport)
30918fba346582c08d81aa96d9508c0e935bad5f36fbuzbee            continue;
31018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee
3117eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng        /*
3127eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng         * If the invoke itself is selected for single stepping, don't bother
3137eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng         * to inline it.
3147eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng         */
3159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        if (SINGLE_STEP_OP(opcode))
3167eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng            continue;
3177eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng
3187a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        const Method *calleeMethod;
3197a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3209a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        switch (opcode) {
3217a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_SUPER:
3227a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_DIRECT:
3237a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_STATIC:
3247a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_SUPER_QUICK:
3257a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
3267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3277a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_SUPER_RANGE:
3287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_DIRECT_RANGE:
3297a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_STATIC_RANGE:
3307a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_SUPER_QUICK_RANGE:
3317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                isRange = true;
3327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
3337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            default:
3357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                calleeMethod = NULL;
3367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3377a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
3387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3397a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if (calleeMethod) {
3407a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            tryInlineSingletonCallsite(cUnit, calleeMethod, lastMIRInsn, bb,
3417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                       isRange);
3427a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            return;
3437a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
3447a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3459a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein        switch (opcode) {
3467a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_VIRTUAL:
3477a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_VIRTUAL_QUICK:
3487a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_INTERFACE:
3497a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                isRange = false;
3507a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
3517a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3527a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_VIRTUAL_RANGE:
3537a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_VIRTUAL_QUICK_RANGE:
3547a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            case OP_INVOKE_INTERFACE_RANGE:
3557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                isRange = true;
3567a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
3577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            default:
3597a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                break;
3607a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
3617a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng
3627a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        if (calleeMethod) {
3637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            tryInlineVirtualCallsite(cUnit, calleeMethod, lastMIRInsn, bb,
3647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng                                     isRange);
3657a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng            return;
3667a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng        }
3677a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng    }
3687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng}
369