package com.googlecode.dex2jar.ir.ts; import com.googlecode.dex2jar.ir.IrMethod; import com.googlecode.dex2jar.ir.LabelAndLocalMapper; import com.googlecode.dex2jar.ir.Trap; import com.googlecode.dex2jar.ir.expr.Local; import com.googlecode.dex2jar.ir.stmt.*; import com.googlecode.dex2jar.ir.stmt.Stmt.ST; import java.util.ArrayList; /** * Try to clean following between a {@link Trap} * <ol> * <li>Move {@link Stmt}s outside a {@link Trap} if {@link Stmt}s are not throw</li> * <li>Remove {@link Trap} if all {@link Stmt}s are not throw</li> * <li>...;GOTO L2; ... ; L2: ; return; => ...;return ; ... ; L2: ; return;</li> * </ol> * * @author bob * */ public class EndRemover implements Transformer { private static final LabelAndLocalMapper keepLocal = new LabelAndLocalMapper() { @Override public Local map(Local local) { return local; } }; @Override public void transform(IrMethod irMethod) { for (Trap trap : new ArrayList<Trap>(irMethod.traps)) {// copy the list and we can remove one from original list LabelStmt start = null; boolean removeTrap = true; for (Stmt p = trap.start.getNext(); p != null && p != trap.end;) { boolean notThrow = Cfg.notThrow(p); if (!notThrow) { start = null; p = p.getNext(); removeTrap = false; continue; } switch (p.st) { case LABEL: if (start != null) { move4Label(irMethod.stmts, start, p.getPre(), (LabelStmt) p); } start = (LabelStmt) p; p = p.getNext(); break; case GOTO: case RETURN: case RETURN_VOID: if (start != null) { Stmt tmp = p.getNext(); move4End(irMethod.stmts, start, p); start = null; p = tmp; } else { p = p.getNext(); } break; default: p = p.getNext(); } } if (removeTrap) { irMethod.traps.remove(trap); } } StmtList stmts = irMethod.stmts; for (Stmt p = stmts.getFirst(); p != null; p = p.getNext()) { if (p.st == ST.GOTO) { LabelStmt target = ((GotoStmt) p).target; Stmt next = target.getNext(); if (next != null && (next.st == ST.RETURN || next.st == ST.RETURN_VOID)) { Stmt nnext = next.clone(keepLocal); stmts.insertAfter(p, nnext); stmts.remove(p); p = nnext; } } } } private void move4Label(StmtList stmts, LabelStmt start, Stmt end, LabelStmt label) { move4End(stmts, start, end); stmts.insertAfter(end, Stmts.nGoto(label)); } private void move4End(StmtList stmts, LabelStmt start, Stmt end) { Stmt g1 = Stmts.nGoto(start); stmts.insertBefore(start, g1); Stmt last = stmts.getLast(); while (last.st == ST.GOTO && ((GotoStmt) last).target == start) { stmts.remove(last); last = stmts.getLast(); } stmts.move(start, end, last); } }