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