All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.dex2jar.ir.ts.ConstTransformer Maven / Gradle / Ivy

package com.googlecode.dex2jar.ir.ts;

import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.expr.Constant;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.Local;
import com.googlecode.dex2jar.ir.expr.PhiExpr;
import com.googlecode.dex2jar.ir.expr.Value;
import com.googlecode.dex2jar.ir.expr.Value.VT;
import com.googlecode.dex2jar.ir.stmt.AssignStmt;
import com.googlecode.dex2jar.ir.stmt.Stmt;
import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
import com.googlecode.dex2jar.ir.stmt.Stmt.ST;
import com.googlecode.dex2jar.ir.ts.Cfg.TravelCallBack;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;

/**
 * Replace must-be-constant local to constant
 * 

* Require a SSA form, usually run after {@link SSATransformer} * * @author Panxiaobo */ @SuppressWarnings({"unchecked", "rawtypes"}) public class ConstTransformer implements Transformer { @Override public void transform(IrMethod m) { // 1. init init(m); // 2. collect collect(m); // 3. mark constant markConstant(m); markReplacable(m); // 4. replace replace(m); // 5. clean clean(m); } private void clean(IrMethod m) { for (Local local : m.locals) { local.tag = null; } } private void replace(IrMethod m) { Cfg.travelMod(m.stmts, new TravelCallBack() { @Override public Value onUse(Local v) { ConstAnalyzeValue cav = (ConstAnalyzeValue) v.tag; if (cav.replacable) { return Exprs.nConstant(cav.cst); } return v; } @Override public Value onAssign(Local v, AssignStmt as) { ConstAnalyzeValue cav = (ConstAnalyzeValue) v.tag; if (cav.replacable) { if (as.op2.trim().vt != VT.CONSTANT) { as.op2 = Exprs.nConstant(cav.cst); } } return v; } }, true); } private void markReplacable(IrMethod m) { for (Local local : m.locals) { ConstAnalyzeValue cav = (ConstAnalyzeValue) local.tag; if (Boolean.TRUE.equals(cav.isConst)) { boolean allTosAreCst = true; for (ConstAnalyzeValue c : cav.assignTo) { if (!Boolean.TRUE.equals(c.isConst)) { allTosAreCst = false; break; } } if (allTosAreCst) { cav.replacable = true; } } } } private void markConstant(IrMethod m) { Queue queue = new UniqueQueue<>(); queue.addAll(m.locals); while (!queue.isEmpty()) { ConstAnalyzeValue cav = (ConstAnalyzeValue) queue.poll().tag; Object cst = cav.cst; if (cav.isConst == null) { if (cst != null) { // we have a cst boolean allCstEquals = true; for (ConstAnalyzeValue p0 : cav.assignFrom) { if (!cst.equals(p0.cst)) { allCstEquals = false; break; } } if (allCstEquals) { cav.isConst = true; } } } if (cst != null || Boolean.TRUE.equals(cav.isConst)) { for (ConstAnalyzeValue p0 : cav.assignTo) { if (p0.isConst == null) { if (p0.cst == null) { p0.cst = cst; } queue.add(p0.local); } } } if (Boolean.FALSE.equals(cav.isConst)) { cav.cst = null; for (ConstAnalyzeValue c : cav.assignTo) { if (!Boolean.FALSE.equals(c.isConst)) { c.cst = null; c.isConst = false; queue.add(c.local); } } } } } private void collect(IrMethod m) { for (Stmt p = m.stmts.getFirst(); p != null; p = p.getNext()) { if (p.st == ST.ASSIGN || p.st == ST.IDENTITY) { E2Stmt e2 = (E2Stmt) p; Value op1 = e2.op1.trim(); Value op2 = e2.op2.trim(); if (op1.vt == VT.LOCAL) { ConstAnalyzeValue cav = (ConstAnalyzeValue) op1.tag; if (op2.vt == VT.CONSTANT) { Constant c = (Constant) op2; cav.isConst = true; cav.cst = c.value; } else if (op2.vt == VT.LOCAL) { Local local2 = (Local) op2; ConstAnalyzeValue zaf2 = (ConstAnalyzeValue) local2.tag; cav.assignFrom.add(zaf2); zaf2.assignTo.add(cav); } else if (op2.vt == VT.PHI) { PhiExpr pe = (PhiExpr) op2; for (Value v : pe.ops) { ConstAnalyzeValue zaf2 = (ConstAnalyzeValue) v.trim().tag; cav.assignFrom.add(zaf2); zaf2.assignTo.add(cav); } } else { cav.isConst = Boolean.FALSE; } } } } } private void init(IrMethod m) { for (Local local : m.locals) { local.tag = new ConstAnalyzeValue(local); } } static class ConstAnalyzeValue { private static final Integer ZERO = 0; public final Local local; public Boolean isConst = null; public boolean replacable = false; public Object cst; public Set assignFrom = new HashSet(3); public Set assignTo = new HashSet(3); ConstAnalyzeValue(Local local) { super(); this.local = local; } public boolean isZero() { if (isConst == null) { return false; } return isConst && (ZERO.equals(cst)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy