接上篇,我们从convertCode开始看
public void convertCode(DexMethodNode methodNode, MethodVisitor mv) {
IrMethod irMethod = dex2ir(methodNode);//主要是创建了它的stmts 把dex类型的指令转换为ir类型的指令
optimize(irMethod);//对ir类型的指令进行优化
ir2j(irMethod, mv);//把优化后的Ir指令转换为java虚拟机指令
}
主要是3步,上面注释写的比较详细了
先看dex2ir
public IrMethod dex2ir(DexMethodNode methodNode) {
return new Dex2IRConverter()
.convert(0 != (methodNode.access & DexConstants.ACC_STATIC), methodNode.method, methodNode.codeNode);
}
新建一个Dex2IRConverter并调用它的convert
public IrMethod convert(boolean isStatic, Method method, DexCodeNode dexCodeNode) {
this.dexCodeNode = dexCodeNode;//设置DexCodeNode
IrMethod irMethod = new IrMethod();//创建一个IrMethod
irMethod.args = method.getParameterTypes();
irMethod.ret = method.getReturnType();
irMethod.owner = method.getOwner();
irMethod.name = method.getName();
irMethod.isStatic = isStatic;
target = irMethod;
insnList = dexCodeNode.stmts;
for (int i = 0; i < insnList.size(); i++) {//是否有标签
DexStmtNode stmtNode = insnList.get(i);
stmtNode.__index = i;//设置 __index
if (stmtNode instanceof DexLabelStmtNode) {
DexLabelStmtNode dexLabelStmtNode = (DexLabelStmtNode) stmtNode;
labelMap.put(dexLabelStmtNode.label, dexLabelStmtNode);
}
}
fixExceptionHandlers();//异常处理指令相关
BitSet[] exBranch = new BitSet[insnList.size()];
parentCount = new int[insnList.size()];
initParentCount(parentCount);//初始化parentCount
BitSet handlers = new BitSet(insnList.size());
initExceptionHandlers(dexCodeNode, exBranch, handlers);
DvmInterpreter<DvmValue> interpreter = buildInterpreter();//创建一个DvmInterpreter
frames = new Dex2IrFrame[insnList.size()];//frames是指令的大小
emitStmts = new ArrayList[insnList.size()];//
BitSet access = new BitSet(insnList.size());//已经访问过的指令
dfs(exBranch, handlers, access, interpreter);
StmtList stmts = target.stmts;
stmts.addAll(preEmit);
for (int i = 0; i < insnList.size(); i++) {
DexStmtNode p = insnList.get(i);
if (access.get(i)) {
List<Stmt> es = emitStmts[i];
if (es != null) {
stmts.addAll(es);//添加到stmts
}
} else {
if (p instanceof DexLabelStmtNode) {
stmts.add(getLabel(((DexLabelStmtNode) p).label));
}
}
}
emitStmts = null;//emitStmts重新设置为null
Queue<DvmValue> queue = new LinkedList<>();
for (int i1 = 0; i1 < frames.length; i1++) {
Dex2IrFrame frame = frames[i1];
if (parentCount[i1] > 1 && frame != null && access.get(i1)) {
for (int j = 0; j < frame.getTotalRegisters(); j++) {
DvmValue v = frame.getReg(j);
addToQueue(queue, v);
}
}
}
while (!queue.isEmpty()) {
DvmValue v = queue.poll();
getLocal(v);
if (v.parent != null) {
if (v.parent.local == null) {
queue.add(v.parent);
}
}
if (v.otherParent != null) {
for (DvmValue v2 : v.otherParent) {
if (v2.local == null) {
queue.add(v2);
}
}
}
}
Set<com.googlecode.dex2jar.ir.expr.Value> phiValues = new HashSet<>();
List<LabelStmt> phiLabels = new ArrayList<>();
for (int i = 0; i < frames.length; i++) {
Dex2IrFrame frame = frames[i];
if (parentCount[i] > 1 && frame != null && access.get(i)) {
DexStmtNode p = insnList.get(i);
LabelStmt labelStmt = getLabel(((DexLabelStmtNode) p).label);
List<AssignStmt> phis = new ArrayList<>();
for (int j = 0; j < frame.getTotalRegisters(); j++) {
DvmValue v = frame.getReg(j);
addPhi(v, phiValues, phis);
}
labelStmt.phis = phis;
phiLabels.add(labelStmt);
}
}
if (phiLabels.size() > 0) {
target.phiLabels = phiLabels;//好像主要是后面指令优化时候要用
}
return target;
}
这个函数比较长,主要做了如下几件事:
1、新建一个IrMethod
2、处理标签
3、处理异常指令
4、初始化parentCount,主要跟跳转等有关
5、调用dfs进行指令转换
6、把处理完的指令添加到target.stmts
我们看下dfs函数
private void dfs(BitSet[] exBranch, BitSet handlers, BitSet access, DvmInterpreter<DvmValue> interpreter) {
currentEmit = preEmit;
Dex2IrFrame first = initFirstFrame(dexCodeNode, target);//初始化第一个帧
if (parentCount[0] > 1) {
merge(first, 0);
} else {
frames[0] = first;
}
Stack<DexStmtNode> stack = new Stack<>();
stack.push(insnList.get(0));
Dex2IrFrame tmp = new Dex2IrFrame(dexCodeNode.totalRegister);//创建一个临时的帧
while (!stack.isEmpty()) {
DexStmtNode p = stack.pop();
int index = p.__index;//获取指令的索引index
if (!access.get(index)) {//是否已经处理过
access.set(index);
} else {
continue;
}
Dex2IrFrame frame = frames[index];//frames大小为dex指令的大小
setCurrentEmit(index);//如果为空则新建一个
if (p instanceof DexLabelStmtNode) {//标签指令节点
emit(getLabel(((DexLabelStmtNode) p).label));
if (handlers.get(index)) {
Local ex = newLocal();
emit(Stmts.nIdentity(ex, Exprs.nExceptionRef("Ljava/lang/Throwable;")));
frame.setTmp(new DvmValue(ex));
}
}
BitSet ex = exBranch[index];//跳转
if (ex != null) {
for (int i = ex.nextSetBit(0); i >= 0; i = ex.nextSetBit(i + 1)) {
merge(frame, i);
stack.push(insnList.get(i));
}
}
tmp.init(frame);//用frame初始化tmp
try {
if (p.op != null) {
switch (p.op) {
case RETURN_VOID:
emit(nReturnVoid());//添加一个ReturnVoidStmt
break;
case GOTO:
case GOTO_16:
case GOTO_32:
emit(nGoto(getLabel(((JumpStmtNode) p).label)));
break;
case NOP:
emit(nNop());
break;
case BAD_OP:
emit(nThrow(nInvokeNew(new Value[]{nString("bad dex opcode")}, new String[]{
"Ljava/lang/String;"},
"Ljava/lang/VerifyError;")));
break;
default:
tmp.execute(p, interpreter);//缺省情况执行execute tmp为Dex2IrFrame
break;
}
}
} catch (Exception exception) {
throw new RuntimeException("Fail on Op " + p.op + " index " + index, exception);
}
if (p.op != null) {
Op op = p.op;
if (op.canBranch()) {//分支指令,则把条件不满足时的指令偏移入栈
JumpStmtNode jump = (JumpStmtNode) p;
int targetIndex = indexOf(jump.label);
stack.push(insnList.get(targetIndex));
merge(tmp, targetIndex);
}
if (op.canSwitch()) {
BaseSwitchStmtNode switchStmtNode = (BaseSwitchStmtNode) p;
for (DexLabel label : switchStmtNode.labels) {
int targetIndex = indexOf(label);
stack.push(insnList.get(targetIndex));
merge(tmp, targetIndex);
}
}
if (op.canContinue()) {//继续下一条
stack.push(insnList.get(index + 1));//下一条指令入栈
merge(tmp, index + 1);//把temp和index+1进行merge
}
} else {
stack.push(insnList.get(index + 1));
merge(tmp, index + 1);
}
// cleanup frame it is useless
if (parentCount[index] <= 1) {//重新设置为null
frames[index] = null;
}
}
}
这个函数也是比较长,主要做了如下工作:
1、调用initFirstFrame初始化第一个帧
2、依次处理各条指令
我们先看initFirstFrame
private Dex2IrFrame initFirstFrame(DexCodeNode methodNode, IrMethod target) {
Dex2IrFrame first = new Dex2IrFrame(methodNode.totalRegister);//总的寄存器个数
int x = methodNode.totalRegister - methodArgCount(target.args);//减去参数使用的寄存器个数
if (!target.isStatic) {// not static 非静态方法第一个参数是this
Local thiz = newLocal();
emit(Stmts.nIdentity(thiz, Exprs.nThisRef(target.owner)));//新建一个this变量
first.setReg(x - 1, new DvmValue(thiz));//参数的前面一个寄存器摄者为this
}
for (int i = 0; i < target.args.length; i++) {//依次对应参数到寄存器,寄存器的下标依据添加的顺序
Local p = newLocal();
emit(Stmts.nIdentity(p, Exprs.nParameterRef(target.args[i], i)));
first.setReg(x, new DvmValue(p));
x += sizeofType(target.args[i]);//递增它的类型大小
}
if (initAllToZero) {//把所有寄存器的初始值设置为0
for (int i