|
|
|
@ -27,6 +27,25 @@ import jode.NewOperator; |
|
|
|
|
public class CreateNewConstructor implements Transformation{ |
|
|
|
|
|
|
|
|
|
public boolean transform(FlowBlock flow) { |
|
|
|
|
/* Situation: |
|
|
|
|
* |
|
|
|
|
* new <object> |
|
|
|
|
* DUP |
|
|
|
|
* PUSH load_ops |
|
|
|
|
* optionally: <= used for "string1 += string2" |
|
|
|
|
* DUP_X2 |
|
|
|
|
* [ n non void + some void expressions ] |
|
|
|
|
* stack_n.<init>(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 <object>(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(); |
|
|
|
|
|
|
|
|
|
while (params > 0) { |
|
|
|
|
if (!(sequBlock.subBlocks[0] instanceof InstructionBlock)) |
|
|
|
|
return false; |
|
|
|
|
Expression expr |
|
|
|
|
= ((InstructionBlock) sequBlock.subBlocks[0]).getInstruction(); |
|
|
|
|
if (!expr.isVoid()) |
|
|
|
|
continue for_loop; |
|
|
|
|
if (exprs[i].canCombine(expr) <= 0) |
|
|
|
|
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; |
|
|
|
|
params = optDup.count; |
|
|
|
|
} else |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
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 ComplexExpression |
|
|
|
|
(new ConstructorOperator(constrCall.getClassType(), |
|
|
|
|
constrCall.getField()), |
|
|
|
|
exprs)); |
|
|
|
|
|
|
|
|
|
flow.lastModified.moveDefinitions(sequBlock, null); |
|
|
|
|
flow.lastModified.replace(sequBlock); |
|
|
|
|
constrCall.getMethodType())); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|