diff --git a/jode/jode/flow/CreateNewConstructor.java b/jode/jode/flow/CreateNewConstructor.java index c59d838..2726407 100644 --- a/jode/jode/flow/CreateNewConstructor.java +++ b/jode/jode/flow/CreateNewConstructor.java @@ -27,6 +27,25 @@ import jode.NewOperator; public class CreateNewConstructor implements Transformation{ public boolean transform(FlowBlock flow) { + /* Situation: + * + * new + * DUP + * PUSH load_ops + * optionally: <= used for "string1 += string2" + * DUP_X2 + * [ n non void + some void expressions ] + * stack_n.(stack_n-1,...,stack_0) + * + * transform it to + * + * PUSH load_ops + * optionally: + * DUP_X1 <= remove the depth + * [ n non void + some void expressions ] + * PUSH new (stack_n-1,...,stack_0) + */ + if (!(flow.lastModified instanceof InstructionBlock) || !(flow.lastModified.outer instanceof SequentialBlock)) return false; @@ -38,64 +57,70 @@ public class CreateNewConstructor implements Transformation{ return false; /* The rest should probably succeed */ - int params = constrCall.getOperandCount(); - Expression[] exprs = new Expression[params]; + int params = constrCall.getOperandCount() - 1; + SpecialBlock optDup = null; SequentialBlock sequBlock = (SequentialBlock) block.outer; - try { - for_loop: - for (int i = params-1; i>0; i--) { - - block = (InstructionBlock) sequBlock.subBlocks[0]; - exprs[i] = block.getInstruction(); - sequBlock = (SequentialBlock) sequBlock.outer; - - while (sequBlock.subBlocks[0] instanceof InstructionBlock) { - - Expression expr = - ((InstructionBlock) sequBlock.subBlocks[0]) - .getInstruction(); - - if (!expr.isVoid()) - continue for_loop; - if (exprs[i].canCombine(expr) <= 0) + while (params > 0) { + if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) + return false; + Expression expr + = ((InstructionBlock) sequBlock.subBlocks[0]).getInstruction(); + if (!expr.isVoid()) + params--; + if (expr.getOperandCount() > 0) { + if (params == 0 + && sequBlock.outer instanceof SequentialBlock + && sequBlock.outer.getSubBlocks()[0] + instanceof SpecialBlock) { + /* handle the optional dup */ + sequBlock = (SequentialBlock) sequBlock.outer; + optDup = (SpecialBlock) sequBlock.subBlocks[0]; + if (optDup.type != SpecialBlock.DUP + || optDup.depth != 2) return false; - - exprs[i] = exprs[i].combine(expr); - SequentialBlock subExprBlock = - (SequentialBlock) sequBlock.subBlocks[1]; - subExprBlock.moveDefinitions(sequBlock, subExprBlock); - subExprBlock.replace(sequBlock); - sequBlock = subExprBlock; - ((InstructionContainer)subExprBlock.subBlocks[0]). - setInstruction(exprs[i]); - sequBlock = (SequentialBlock)sequBlock.outer; - } + params = optDup.count; + } else + return false; } + if (!(sequBlock.outer instanceof SequentialBlock)) + return false; + sequBlock = (SequentialBlock) sequBlock.outer; + } + + while (sequBlock.subBlocks[0] instanceof InstructionBlock + && ((InstructionBlock)sequBlock.subBlocks[0]) + .getInstruction().isVoid() + && sequBlock.outer instanceof SequentialBlock) + sequBlock = (SequentialBlock) sequBlock.outer; + + if (sequBlock.outer instanceof SequentialBlock + && sequBlock.subBlocks[0] instanceof SpecialBlock) { SpecialBlock dup = (SpecialBlock) sequBlock.subBlocks[0]; if (dup.type != SpecialBlock.DUP || dup.count != 1 || dup.depth != 0) return false; + sequBlock = (SequentialBlock)sequBlock.outer; + if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) + return false; block = (InstructionBlock) sequBlock.subBlocks[0]; - exprs[0] = block.getInstruction(); - if (exprs[0].isVoid()) + if (!(block.getInstruction() instanceof NewOperator)) return false; - NewOperator op = (NewOperator) exprs[0].getOperator(); + + NewOperator op = (NewOperator) block.getInstruction(); if (constrCall.getClassType() != op.getType()) return false; - } catch (ClassCastException ex) { - return false; - } catch (NullPointerException ex) { - return false; + + block.removeBlock(); + dup.removeBlock(); + if (optDup != null) + optDup.depth = 0; + ((InstructionContainer) flow.lastModified).setInstruction + (new ConstructorOperator(constrCall.getClassType(), + constrCall.getMethodType())); + return true; } - ((InstructionContainer) flow.lastModified).setInstruction - (new ComplexExpression - (new ConstructorOperator(constrCall.getClassType(), - constrCall.getField()), - exprs)); - - flow.lastModified.moveDefinitions(sequBlock, null); - flow.lastModified.replace(sequBlock); - return true; + return false; } } +