| 1 19 20 package jode.flow; 21 import jode.expr.*; 22 import jode.bytecode.Reference; 23 import jode.decompiler.MethodAnalyzer; 24 import jode.type.Type; 25 26 public class CreateNewConstructor { 27 28 public static boolean transform(InstructionContainer ic, 29 StructuredBlock last) { 30 return transformNormal(ic, last) || transformJikesString(ic, last); 31 } 32 33 static boolean transformJikesString(InstructionContainer ic, 34 StructuredBlock last) { 35 45 if (!(last.outer instanceof SequentialBlock) 46 || !(ic.getInstruction() instanceof InvokeOperator)) 47 return false; 48 49 InvokeOperator appendCall = (InvokeOperator) ic.getInstruction(); 50 if (!appendCall.getClassType().equals(Type.tStringBuffer) 51 || !appendCall.isFreeOperator(2) 52 || appendCall.isStatic() 53 || !appendCall.getMethodName().equals("append") 54 || appendCall.getMethodType().getParameterTypes().length != 1) 55 return false; 56 57 SequentialBlock sequBlock = (SequentialBlock) last.outer; 58 if (!(sequBlock.outer instanceof SequentialBlock) 59 || !(sequBlock.subBlocks[0] instanceof SpecialBlock)) 60 return false; 61 62 SpecialBlock swapBlock = (SpecialBlock) sequBlock.subBlocks[0]; 63 sequBlock = (SequentialBlock) sequBlock.outer; 64 if (swapBlock.type != SpecialBlock.SWAP 65 || !(sequBlock.subBlocks[0] instanceof InstructionBlock) 66 || !(sequBlock.outer instanceof SequentialBlock)) 67 return false; 68 69 InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0]; 70 sequBlock = (SequentialBlock) sequBlock.outer; 71 if (!(ib.getInstruction() instanceof InvokeOperator) 72 || !(sequBlock.subBlocks[0] instanceof InstructionBlock)) 73 return false; 74 75 InvokeOperator constr = (InvokeOperator) ib.getInstruction(); 76 ib = (InstructionBlock) sequBlock.subBlocks[0]; 77 78 if (!constr.isConstructor() 79 || !constr.getClassType().equals(Type.tStringBuffer) 80 || constr.isVoid() 81 || constr.getMethodType().getParameterTypes().length != 0) 82 return false; 83 84 85 MethodAnalyzer methodAna = ib.flowBlock.method; 86 Expression expr = ib.getInstruction(); 87 Type appendType = appendCall.getMethodType().getParameterTypes()[0]; 88 if (!appendType.equals(Type.tString)) { 89 InvokeOperator valueOf = new InvokeOperator 90 (methodAna, InvokeOperator.STATIC, 91 Reference.getReference("Ljava/lang/String;", "valueOf", 92 "(" + appendType.getTypeSignature() 93 + ")Ljava/lang/String;")); 94 expr = valueOf.addOperand(expr); 95 } 96 InvokeOperator newConstr = new InvokeOperator 97 (methodAna, InvokeOperator.CONSTRUCTOR, 98 Reference.getReference("Ljava/lang/StringBuffer;", "<init>", 99 "(Ljava/lang/String;)V")); 100 newConstr.makeNonVoid(); 101 newConstr.setSubExpressions(0, constr.getSubExpressions()[0]); 102 newConstr.setSubExpressions(1, expr); 103 ic.setInstruction(newConstr); 104 last.replace(sequBlock); 105 return true; 106 } 107 108 static boolean transformNormal(InstructionContainer ic, 109 StructuredBlock last) { 110 139 140 if (!(last.outer instanceof SequentialBlock)) 141 return false; 142 if (!(ic.getInstruction() instanceof InvokeOperator)) 143 return false; 144 InvokeOperator constrCall = (InvokeOperator) ic.getInstruction(); 145 if (!constrCall.isConstructor() || !constrCall.isVoid()) 146 return false; 147 148 149 150 SpecialBlock optDupX2 = null; 151 SequentialBlock sequBlock = (SequentialBlock) last.outer; 152 Expression[] subs = constrCall.getSubExpressions(); 153 int opcount = constrCall.getFreeOperandCount(); 154 if (subs != null) { 155 if (!(subs[0] instanceof NopOperator)) 156 return false; 157 if (constrCall.getFreeOperandCount() > 1) { 158 if (!(sequBlock.outer instanceof SequentialBlock) 159 || !(sequBlock.subBlocks[0] instanceof SpecialBlock)) 160 return false; 161 optDupX2 = (SpecialBlock) sequBlock.subBlocks[0]; 162 sequBlock = (SequentialBlock) sequBlock.outer; 163 if (optDupX2.type != SpecialBlock.DUP 164 || optDupX2.depth == 0) 165 return false; 166 int count = optDupX2.count; 167 do { 168 if (!(sequBlock.outer instanceof SequentialBlock) 169 || !(sequBlock.subBlocks[0] 170 instanceof InstructionBlock)) 171 return false; 172 Expression expr = 173 ((InstructionBlock) 174 sequBlock.subBlocks[0]).getInstruction(); 175 sequBlock = (SequentialBlock) sequBlock.outer; 176 177 if (expr.isVoid()) 178 continue; 179 count -= expr.getType().stackSize(); 180 opcount--; 181 } while (count > 0 && opcount > 1); 182 if (count != 0) 183 return false; 184 } 185 } 186 if (opcount != 1) 187 return false; 188 189 while (sequBlock.subBlocks[0] instanceof InstructionBlock 190 && sequBlock.outer instanceof SequentialBlock) { 191 Expression expr 192 = ((InstructionBlock)sequBlock.subBlocks[0]).getInstruction(); 193 if (!expr.isVoid() || expr.getFreeOperandCount() > 0) 194 break; 195 sequBlock = (SequentialBlock) sequBlock.outer; 196 } 197 198 SpecialBlock dup = null; 199 if (sequBlock.outer instanceof SequentialBlock 200 && sequBlock.subBlocks[0] instanceof SpecialBlock) { 201 202 dup = (SpecialBlock) sequBlock.subBlocks[0]; 203 if (dup.type != SpecialBlock.DUP 204 || dup.count != 1 || dup.depth != 0) 205 return false; 206 sequBlock = (SequentialBlock)sequBlock.outer; 207 if (optDupX2 != null && optDupX2.depth != 2) 208 return false; 209 } else if (optDupX2 != null && optDupX2.depth != 1) 210 return false; 211 212 if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) 213 return false; 214 InstructionBlock block = (InstructionBlock) sequBlock.subBlocks[0]; 215 if (!(block.getInstruction() instanceof NewOperator)) 216 return false; 217 218 NewOperator op = (NewOperator) block.getInstruction(); 219 if (constrCall.getClassType() != op.getType()) 220 return false; 221 222 block.removeBlock(); 223 if (dup != null) 224 dup.removeBlock(); 225 if (optDupX2 != null) 226 optDupX2.depth = 0; 227 228 constrCall.setSubExpressions(0, op); 229 if (dup != null) 230 constrCall.makeNonVoid(); 231 234 return true; 240 } 241 } 242 | Popular Tags |