SsaDumper.java revision 99409883d9c4c0ffb49b070ce307bb33a9dfe9f1
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.command.dump; 18 19import com.android.dx.cf.code.ConcreteMethod; 20import com.android.dx.cf.code.Ropper; 21import com.android.dx.cf.iface.Member; 22import com.android.dx.cf.iface.Method; 23import com.android.dx.rop.code.RopMethod; 24import com.android.dx.rop.code.TranslationAdvice; 25import com.android.dx.rop.code.DexTranslationAdvice; 26import com.android.dx.rop.code.AccessFlags; 27import com.android.dx.ssa.DeadCodeRemover; 28import com.android.dx.ssa.PhiTypeResolver; 29import com.android.dx.ssa.SsaBasicBlock; 30import com.android.dx.ssa.SsaConverter; 31import com.android.dx.ssa.SsaInsn; 32import com.android.dx.ssa.SsaMethod; 33import com.android.dx.ssa.Optimizer; 34import com.android.dx.ssa.ConstCollector; 35import com.android.dx.ssa.SCCP; 36import com.android.dx.ssa.LiteralOpUpgrader; 37import com.android.dx.ssa.back.SsaToRop; 38import com.android.dx.util.ByteArray; 39import com.android.dx.util.Hex; 40import com.android.dx.util.IntList; 41 42import java.io.PrintStream; 43import java.util.ArrayList; 44import java.util.BitSet; 45import java.util.Collections; 46import java.util.EnumSet; 47 48/** 49 * Dumper for the SSA-translated blocks of a method. 50 */ 51public class SsaDumper extends BlockDumper { 52 /** 53 * Does the dump. 54 * 55 * @param bytes {@code non-null;} bytes of the original class file 56 * @param out {@code non-null;} where to dump to 57 * @param filePath the file path for the class, excluding any base 58 * directory specification 59 * @param args commandline parsedArgs 60 */ 61 public static void dump(byte[] bytes, PrintStream out, 62 String filePath, Args args) { 63 SsaDumper sd = new SsaDumper(bytes, out, filePath, args); 64 sd.dump(); 65 } 66 67 /** 68 * Constructs an instance. 69 * 70 * @param bytes {@code non-null;} bytes of the original class file 71 * @param out {@code non-null;} where to dump to 72 * @param filePath the file path for the class, excluding any base 73 * directory specification 74 * @param args commandline parsedArgs 75 */ 76 private SsaDumper(byte[] bytes, PrintStream out, String filePath, 77 Args args) { 78 super(bytes, out, filePath, true, args); 79 } 80 81 /** {@inheritDoc} */ 82 @Override 83 public void endParsingMember(ByteArray bytes, int offset, String name, 84 String descriptor, Member member) { 85 if (!(member instanceof Method)) { 86 return; 87 } 88 89 if (!shouldDumpMethod(name)) { 90 return; 91 } 92 93 ConcreteMethod meth = 94 new ConcreteMethod((Method) member, classFile, true, true); 95 TranslationAdvice advice = DexTranslationAdvice.THE_ONE; 96 RopMethod rmeth = Ropper.convert(meth, advice); 97 SsaMethod ssaMeth = null; 98 boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags()); 99 int paramWidth = computeParamWidth(meth, isStatic); 100 101 if (args.ssaStep == null) { 102 ssaMeth = Optimizer.debugNoRegisterAllocation(rmeth, 103 paramWidth, isStatic, true, advice, 104 EnumSet.allOf(Optimizer.OptionalStep.class)); 105 } else if ("edge-split".equals(args.ssaStep)) { 106 ssaMeth = Optimizer.debugEdgeSplit(rmeth, paramWidth, 107 isStatic, true, advice); 108 } else if ("phi-placement".equals(args.ssaStep)) { 109 ssaMeth = Optimizer.debugPhiPlacement( 110 rmeth, paramWidth, isStatic, true, advice); 111 } else if ("renaming".equals(args.ssaStep)) { 112 ssaMeth = Optimizer.debugRenaming( 113 rmeth, paramWidth, isStatic, true, advice); 114 } else if ("dead-code".equals(args.ssaStep)) { 115 ssaMeth = Optimizer.debugDeadCodeRemover( 116 rmeth, paramWidth, isStatic,true, advice); 117 } 118 119 StringBuffer sb = new StringBuffer(2000); 120 121 sb.append("first "); 122 sb.append(Hex.u2( 123 ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex()))); 124 sb.append('\n'); 125 126 ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks(); 127 ArrayList<SsaBasicBlock> sortedBlocks = 128 (ArrayList<SsaBasicBlock>) blocks.clone(); 129 Collections.sort(sortedBlocks, SsaBasicBlock.LABEL_COMPARATOR); 130 131 for (SsaBasicBlock block : sortedBlocks) { 132 sb.append("block ") 133 .append(Hex.u2(block.getRopLabel())).append('\n'); 134 135 BitSet preds = block.getPredecessors(); 136 137 for(int i=preds.nextSetBit(0); i>=0; i=preds.nextSetBit(i+1)) { 138 sb.append(" pred "); 139 sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(i))); 140 sb.append('\n'); 141 } 142 143 sb.append(" live in:" + block.getLiveInRegs()); 144 sb.append("\n"); 145 146 for (SsaInsn insn: block.getInsns()) { 147 sb.append(" "); 148 sb.append(insn.toHuman()); 149 sb.append('\n'); 150 } 151 152 if (block.getSuccessors().cardinality() == 0) { 153 sb.append(" returns\n"); 154 } else { 155 int primary = block.getPrimarySuccessorRopLabel(); 156 157 IntList succLabelList = block.getRopLabelSuccessorList(); 158 159 int szSuccLabels = succLabelList.size(); 160 161 for (int i = 0; i < szSuccLabels; i++) { 162 sb.append(" next "); 163 sb.append(Hex.u2(succLabelList.get(i))); 164 165 if (szSuccLabels != 1 && primary == succLabelList.get(i)) { 166 sb.append(" *"); 167 } 168 sb.append('\n'); 169 } 170 } 171 172 sb.append(" live out:" + block.getLiveOutRegs()); 173 sb.append("\n"); 174 } 175 176 suppressDump = false; 177 setAt(bytes, 0); 178 parsed(bytes, 0, bytes.size(), sb.toString()); 179 suppressDump = true; 180 } 181} 182