InlineTransformation.cpp revision 5d5b94c8d14b166af580d5dd5906db4f9527d6ca
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 37cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengstatic bool 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)) 52cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return false; 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)) { 62cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return false; 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; 1055d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro invokeMIR->dalvikInsn.opcode = (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 127cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return true; 1287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 1297a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 130cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengstatic bool 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)) 143cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return false; 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; 1845d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro invokeMIR->dalvikInsn.opcode = (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 208cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return true; 2097a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 2107a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 211cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengstatic bool 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 */ 218cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmIsNativeMethod(calleeMethod)) return false; 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; 232cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return true; 2337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 2347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (methodStats->attributes & METHOD_IS_GETTER) { 236cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, 237cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng isRange); 2387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } else if (methodStats->attributes & METHOD_IS_SETTER) { 239cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, false, 240cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng isRange); 2417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 242cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return false; 2437a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 2447a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 245cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengstatic bool inlineEmptyVirtualCallee(CompilationUnit *cUnit, 2467a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng const Method *calleeMethod, 2477a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng MIR *invokeMIR, 2487a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng BasicBlock *invokeBB) 2497a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{ 250fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro MIR *invokeMIRSlow = (MIR *)dvmCompilerNew(sizeof(MIR), true); 2517a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng *invokeMIRSlow = *invokeMIR; 2525d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro invokeMIR->dalvikInsn.opcode = (Opcode)kMirOpCheckInlinePrediction; 2537a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2547a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng dvmCompilerInsertMIRAfter(invokeBB, invokeMIR, invokeMIRSlow); 2557a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng invokeMIRSlow->OptimizationFlags |= MIR_INLINED_PRED; 256cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return true; 2577a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 2587a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 259cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengstatic bool tryInlineVirtualCallsite(CompilationUnit *cUnit, 2607a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng const Method *calleeMethod, 2617a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng MIR *invokeMIR, 2627a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng BasicBlock *invokeBB, 2637a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng bool isRange) 2647a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{ 2657a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* Not a Java method */ 266cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmIsNativeMethod(calleeMethod)) return false; 2677a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng CompilerMethodStats *methodStats = 2697a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng dvmCompilerAnalyzeMethodBody(calleeMethod, true); 2707a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2717a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* Empty callee - do nothing by checking the clazz pointer */ 2727a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (methodStats->attributes & METHOD_IS_EMPTY) { 273cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return inlineEmptyVirtualCallee(cUnit, calleeMethod, invokeMIR, 274cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng invokeBB); 2757a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 2767a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2777a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (methodStats->attributes & METHOD_IS_GETTER) { 278cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return inlineGetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, 279cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng isRange); 2807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } else if (methodStats->attributes & METHOD_IS_SETTER) { 281cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return inlineSetter(cUnit, calleeMethod, invokeMIR, invokeBB, true, 282cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng isRange); 2837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 284cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng return false; 2857a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 2867a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 2877a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 288cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Chengvoid dvmCompilerInlineMIR(CompilationUnit *cUnit, JitTranslationInfo *info) 2897a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng{ 2907a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng bool isRange = false; 29100603079b8723b32c955513eae63a8f97898074dBen Cheng GrowableListIterator iterator; 2927a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 29300603079b8723b32c955513eae63a8f97898074dBen Cheng dvmGrowableListIteratorInit(&cUnit->blockList, &iterator); 2947a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* 2957a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng * Analyze the basic block containing an invoke to see if it can be inlined 2967a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng */ 29700603079b8723b32c955513eae63a8f97898074dBen Cheng while (true) { 29800603079b8723b32c955513eae63a8f97898074dBen Cheng BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator); 29900603079b8723b32c955513eae63a8f97898074dBen Cheng if (bb == NULL) break; 3007a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (bb->blockType != kDalvikByteCode) 3017a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng continue; 3027a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng MIR *lastMIRInsn = bb->lastMIRInsn; 3035d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro Opcode opcode = lastMIRInsn->dalvikInsn.opcode; 3045d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro int flags = (int)dexGetFlagsFromOpcode(opcode); 3057a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3067a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng /* No invoke - continue */ 3077a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if ((flags & kInstrInvoke) == 0) 3087a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng continue; 3097a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 31018fba346582c08d81aa96d9508c0e935bad5f36fbuzbee /* Disable inlining when doing method tracing */ 31118fba346582c08d81aa96d9508c0e935bad5f36fbuzbee if (gDvmJit.methodTraceSupport) 31218fba346582c08d81aa96d9508c0e935bad5f36fbuzbee continue; 31318fba346582c08d81aa96d9508c0e935bad5f36fbuzbee 3147eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng /* 3157eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng * If the invoke itself is selected for single stepping, don't bother 3167eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng * to inline it. 3177eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng */ 3189a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein if (SINGLE_STEP_OP(opcode)) 3197eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng continue; 3207eb3f7aaf43f07caf0de05ba4ae59e8ea6add796Ben Cheng 3217a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng const Method *calleeMethod; 3227a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3239a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein switch (opcode) { 3247a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_SUPER: 3257a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_DIRECT: 3267a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_STATIC: 3277a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_SUPER_QUICK: 3287a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng calleeMethod = lastMIRInsn->meta.callsiteInfo->method; 3297a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3307a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_SUPER_RANGE: 3317a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_DIRECT_RANGE: 3327a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_STATIC_RANGE: 3337a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_SUPER_QUICK_RANGE: 3347a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng isRange = true; 3357a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng calleeMethod = lastMIRInsn->meta.callsiteInfo->method; 3367a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3377a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng default: 3387a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng calleeMethod = NULL; 3397a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3407a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 3417a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3427a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (calleeMethod) { 343cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng bool inlined = tryInlineSingletonCallsite(cUnit, calleeMethod, 344cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn, bb, isRange); 345cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (!inlined && 346cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !(gDvmJit.disableOpt & (1 << kMethodJit)) && 347cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !dvmIsNativeMethod(calleeMethod)) { 348cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng CompilerMethodStats *methodStats = 349cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng dvmCompilerAnalyzeMethodBody(calleeMethod, true); 350cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if ((methodStats->attributes & METHOD_IS_LEAF) && 351cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !(methodStats->attributes & METHOD_CANNOT_COMPILE)) { 352cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng /* Callee has been previously compiled */ 353cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmJitGetMethodAddr(calleeMethod->insns)) { 354cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT; 355cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } else { 356cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng /* Compile the callee first */ 357cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng dvmCompileMethod(calleeMethod, info); 358cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmJitGetMethodAddr(calleeMethod->insns)) { 359cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn->OptimizationFlags |= 360cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng MIR_INVOKE_METHOD_JIT; 361cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } else { 362cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng methodStats->attributes |= METHOD_CANNOT_COMPILE; 363cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 364cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 365cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 366cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 3677a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng return; 3687a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 3697a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3709a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein switch (opcode) { 3717a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_VIRTUAL: 3727a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_VIRTUAL_QUICK: 3737a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_INTERFACE: 3747a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng isRange = false; 3757a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng calleeMethod = lastMIRInsn->meta.callsiteInfo->method; 3767a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3777a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_VIRTUAL_RANGE: 3787a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_VIRTUAL_QUICK_RANGE: 3797a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng case OP_INVOKE_INTERFACE_RANGE: 3807a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng isRange = true; 3817a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng calleeMethod = lastMIRInsn->meta.callsiteInfo->method; 3827a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3837a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng default: 3847a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng break; 3857a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 3867a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng 3877a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng if (calleeMethod) { 388cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng bool inlined = tryInlineVirtualCallsite(cUnit, calleeMethod, 389cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn, bb, isRange); 390cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (!inlined && 391cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !(gDvmJit.disableOpt & (1 << kMethodJit)) && 392cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !dvmIsNativeMethod(calleeMethod)) { 393cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng CompilerMethodStats *methodStats = 394cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng dvmCompilerAnalyzeMethodBody(calleeMethod, true); 395cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if ((methodStats->attributes & METHOD_IS_LEAF) && 396cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng !(methodStats->attributes & METHOD_CANNOT_COMPILE)) { 397cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng /* Callee has been previously compiled */ 398cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmJitGetMethodAddr(calleeMethod->insns)) { 399cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT; 400cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } else { 401cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng /* Compile the callee first */ 402cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng dvmCompileMethod(calleeMethod, info); 403cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng if (dvmJitGetMethodAddr(calleeMethod->insns)) { 404cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng lastMIRInsn->OptimizationFlags |= 405cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng MIR_INVOKE_METHOD_JIT; 406cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } else { 407cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng methodStats->attributes |= METHOD_CANNOT_COMPILE; 408cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 409cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 410cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 411cfdeca37fcaa27c37bad5077223e4d1e87f1182eBen Cheng } 4127a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng return; 4137a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 4147a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng } 4157a2697d327936e20ef5484f7819e2e4bf91c891fBen Cheng} 416