final HashMap<AbstractInsnNode, MethodInsnNode> movable= new HashMap<AbstractInsnNode, MethodInsnNode>();
Frame[] frames= a.getFrames();
for (int j= 0; j < methods.size(); j++)
{
MethodInsnNode mnode= methods.get(j);
// require to move NEW instruction
int n= instructions.indexOf(mnode);
Frame f= frames[n];
Type[] args= Type.getArgumentTypes(mnode.desc);
SourceValue v= (SourceValue) f.getStack(f.getStackSize() - args.length - 1);
Set<AbstractInsnNode> insns= v.insns;
for (final AbstractInsnNode ins : insns)
{
if (ins.getOpcode() == NEW)
{
movable.put(ins, mnode);
}
else
{
// other known patterns
int n1= instructions.indexOf(ins);
if (ins.getOpcode() == DUP)
{ // <init> with params
AbstractInsnNode ins1= instructions.get(n1 - 1);
if (ins1.getOpcode() == NEW)
{
movable.put(ins1, mnode);
}
}
else if (ins.getOpcode() == SWAP)
{ // in exception handler
AbstractInsnNode ins1= instructions.get(n1 - 1);
AbstractInsnNode ins2= instructions.get(n1 - 2);
if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW)
{
movable.put(ins2, mnode);
}
}
}
}
}
int updateMaxStack= 0;
for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet())
{
AbstractInsnNode node1= e.getKey();
int n1= instructions.indexOf(node1);
AbstractInsnNode node2= instructions.get(n1 + 1);
AbstractInsnNode node3= instructions.get(n1 + 2);
int producer= node2.getOpcode();
instructions.remove(node1); // NEW
boolean requireDup= false;
if (producer == DUP)
{
instructions.remove(node2); // DUP
requireDup= true;
}
else if (producer == DUP_X1)
{
instructions.remove(node2); // DUP_X1
instructions.remove(node3); // SWAP
requireDup= true;
}
MethodInsnNode mnode= (MethodInsnNode) e.getValue();
AbstractInsnNode nm= mnode;
int varOffset= stackRecorderVar + 1;
Type[] args= Type.getArgumentTypes(mnode.desc);