1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.ssa; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpec; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegOps; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.CstInsn; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.LocalItem; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstInteger; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.HashSet; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combine identical move-param insns, which may result from Ropper's 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * handling of synchronized methods. 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class MoveParamCombiner { 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** method to process */ 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final SsaMethod ssaMeth; 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Processes a method with this optimization step. 40de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param ssaMethod method to process 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static void process(SsaMethod ssaMethod) { 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new MoveParamCombiner(ssaMethod).run(); 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private MoveParamCombiner(SsaMethod ssaMeth) { 48de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro this.ssaMeth = ssaMeth; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Runs this optimization step. 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void run() { 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // This will contain the definition specs for each parameter 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project final RegisterSpec[] paramSpecs 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = new RegisterSpec[ssaMeth.getParamWidth()]; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Insns to delete when all done 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project final HashSet<SsaInsn> deletedInsns = new HashSet(); 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ssaMeth.forEachInsn(new SsaInsn.Visitor() { 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void visitMoveInsn (NormalSsaInsn insn) { 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void visitPhiInsn (PhiInsn phi) { 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public void visitNonMoveInsn (NormalSsaInsn insn) { 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (insn.getOpcode().getOpcode() != RegOps.MOVE_PARAM) { 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int param = getParamIndex(insn); 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (paramSpecs[param] == null) { 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project paramSpecs[param] = insn.getResult(); 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project final RegisterSpec specA = paramSpecs[param]; 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project final RegisterSpec specB = insn.getResult(); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalItem localA = specA.getLocalItem(); 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalItem localB = specB.getLocalItem(); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LocalItem newLocal; 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Is there local information to preserve? 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (localA == null) { 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newLocal = localB; 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (localB == null) { 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newLocal = localA; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (localA.equals(localB)) { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newLocal = localA; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Oddly, these two identical move-params have distinct 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * debug info. We'll just keep them distinct. 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ssaMeth.getDefinitionForRegister(specA.getReg()) 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .setResultLocal(newLocal); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Map all uses of specB to specA 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project RegisterMapper mapper = new RegisterMapper() { 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** @inheritDoc */ 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int getNewRegisterCount() { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return ssaMeth.getRegCount(); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** @inheritDoc */ 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public RegisterSpec map(RegisterSpec registerSpec) { 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (registerSpec.getReg() == specB.getReg()) { 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return specA; 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return registerSpec; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project List<SsaInsn> uses 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = ssaMeth.getUseListForRegister(specB.getReg()); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Use list is modified by mapSourceRegisters 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = uses.size() - 1; i >= 0; i--) { 129de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro SsaInsn use = uses.get(i); 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project use.mapSourceRegisters(mapper); 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project deletedInsns.add(insn); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ssaMeth.deleteInsns(deletedInsns); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the parameter index associated with a move-param insn. Does 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not verify that the insn is a move-param insn. 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 14699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param insn {@code non-null;} a move-param insn 14799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code >=0;} parameter index 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private int getParamIndex(NormalSsaInsn insn) { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CstInsn cstInsn = (CstInsn)(insn.getOriginalRopInsn()); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int param = ((CstInteger)cstInsn.getConstant()).getValue(); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return param; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 157