use of com.googlecode.d2j.asm.LdcOptimizeAdapter in project dex2jar by pxb1988.
the class IR2JConverter method reBuildInstructions.
private void reBuildInstructions(IrMethod ir, MethodVisitor asm) {
asm = new LdcOptimizeAdapter(asm);
int maxLocalIndex = 0;
for (Local local : ir.locals) {
maxLocalIndex = Math.max(maxLocalIndex, local._ls_index);
}
Map<String, Integer> lockMap = new HashMap<String, Integer>();
for (Stmt st : ir.stmts) {
switch(st.st) {
case LABEL:
LabelStmt labelStmt = (LabelStmt) st;
Label label = (Label) labelStmt.tag;
asm.visitLabel(label);
if (labelStmt.lineNumber >= 0) {
asm.visitLineNumber(labelStmt.lineNumber, label);
}
break;
case ASSIGN:
{
E2Stmt e2 = (E2Stmt) st;
Value v1 = e2.op1;
Value v2 = e2.op2;
switch(v1.vt) {
case LOCAL:
Local local = ((Local) v1);
int i = local._ls_index;
boolean skipOrg = false;
if (v2.vt == VT.LOCAL && (i == ((Local) v2)._ls_index)) {
// check for a=a
skipOrg = true;
} else if (v1.valueType.charAt(0) == 'I') {
// check for IINC
if (v2.vt == VT.ADD) {
if (isLocalWithIndex(v2.getOp1(), i) && v2.getOp2().vt == VT.CONSTANT) {
// a=a+1;
int increment = (Integer) ((Constant) v2.getOp2()).value;
if (increment >= Short.MIN_VALUE && increment <= Short.MAX_VALUE) {
asm.visitIincInsn(i, increment);
skipOrg = true;
}
} else if (isLocalWithIndex(v2.getOp2(), i) && v2.getOp1().vt == VT.CONSTANT) {
// a=1+a;
int increment = (Integer) ((Constant) v2.getOp1()).value;
if (increment >= Short.MIN_VALUE && increment <= Short.MAX_VALUE) {
asm.visitIincInsn(i, increment);
skipOrg = true;
}
}
} else if (v2.vt == VT.SUB) {
if (isLocalWithIndex(v2.getOp1(), i) && v2.getOp2().vt == VT.CONSTANT) {
// a=a-1;
int increment = -(Integer) ((Constant) v2.getOp2()).value;
if (increment >= Short.MIN_VALUE && increment <= Short.MAX_VALUE) {
asm.visitIincInsn(i, increment);
skipOrg = true;
}
}
}
}
if (!skipOrg) {
accept(v2, asm);
if (i >= 0) {
asm.visitVarInsn(getOpcode(v1, ISTORE), i);
} else if (!v1.valueType.equals("V")) {
// skip void type locals
switch(v1.valueType.charAt(0)) {
case 'J':
case 'D':
asm.visitInsn(POP2);
break;
default:
asm.visitInsn(POP);
break;
}
}
}
break;
case STATIC_FIELD:
{
StaticFieldExpr fe = (StaticFieldExpr) v1;
accept(v2, asm);
insertI2x(v2.valueType, fe.type, asm);
asm.visitFieldInsn(PUTSTATIC, toInternal(fe.owner), fe.name, fe.type);
break;
}
case FIELD:
{
FieldExpr fe = (FieldExpr) v1;
accept(fe.op, asm);
accept(v2, asm);
insertI2x(v2.valueType, fe.type, asm);
asm.visitFieldInsn(PUTFIELD, toInternal(fe.owner), fe.name, fe.type);
break;
}
case ARRAY:
ArrayExpr ae = (ArrayExpr) v1;
accept(ae.op1, asm);
accept(ae.op2, asm);
accept(v2, asm);
String tp1 = ae.op1.valueType;
String tp2 = ae.valueType;
if (tp1.charAt(0) == '[') {
String arrayElementType = tp1.substring(1);
insertI2x(v2.valueType, arrayElementType, asm);
asm.visitInsn(getOpcode(arrayElementType, IASTORE));
} else {
asm.visitInsn(getOpcode(tp2, IASTORE));
}
break;
}
}
break;
case IDENTITY:
{
E2Stmt e2 = (E2Stmt) st;
if (e2.op2.vt == VT.EXCEPTION_REF) {
int index = ((Local) e2.op1)._ls_index;
if (index >= 0) {
asm.visitVarInsn(ASTORE, index);
} else {
asm.visitInsn(POP);
}
}
}
break;
case FILL_ARRAY_DATA:
{
E2Stmt e2 = (E2Stmt) st;
if (e2.getOp2().vt == VT.CONSTANT) {
Object arrayData = ((Constant) e2.getOp2()).value;
int arraySize = Array.getLength(arrayData);
String arrayValueType = e2.getOp1().valueType;
String elementType;
if (arrayValueType.charAt(0) == '[') {
elementType = arrayValueType.substring(1);
} else {
elementType = "I";
}
int iastoreOP = getOpcode(elementType, IASTORE);
accept(e2.getOp1(), asm);
for (int i = 0; i < arraySize; i++) {
asm.visitInsn(DUP);
asm.visitLdcInsn(i);
asm.visitLdcInsn(Array.get(arrayData, i));
asm.visitInsn(iastoreOP);
}
asm.visitInsn(POP);
} else {
FilledArrayExpr filledArrayExpr = (FilledArrayExpr) e2.getOp2();
int arraySize = filledArrayExpr.ops.length;
String arrayValueType = e2.getOp1().valueType;
String elementType;
if (arrayValueType.charAt(0) == '[') {
elementType = arrayValueType.substring(1);
} else {
elementType = "I";
}
int iastoreOP = getOpcode(elementType, IASTORE);
accept(e2.getOp1(), asm);
for (int i = 0; i < arraySize; i++) {
asm.visitInsn(DUP);
asm.visitLdcInsn(i);
accept(filledArrayExpr.ops[i], asm);
asm.visitInsn(iastoreOP);
}
asm.visitInsn(POP);
}
}
break;
case GOTO:
asm.visitJumpInsn(GOTO, (Label) ((GotoStmt) st).target.tag);
break;
case IF:
reBuildJumpInstructions((IfStmt) st, asm);
break;
case LOCK:
{
Value v = ((UnopStmt) st).op;
accept(v, asm);
if (optimizeSynchronized) {
switch(v.vt) {
case LOCAL:
// break;
case CONSTANT:
{
String key;
if (v.vt == VT.LOCAL) {
key = "L" + ((Local) v)._ls_index;
} else {
key = "C" + ((Constant) v).value;
}
Integer integer = lockMap.get(key);
int nIndex = integer != null ? integer : ++maxLocalIndex;
asm.visitInsn(DUP);
asm.visitVarInsn(getOpcode(v, ISTORE), nIndex);
lockMap.put(key, nIndex);
}
break;
default:
throw new RuntimeException();
}
}
asm.visitInsn(MONITORENTER);
}
break;
case UNLOCK:
{
Value v = ((UnopStmt) st).op;
if (optimizeSynchronized) {
switch(v.vt) {
case LOCAL:
case CONSTANT:
{
String key;
if (v.vt == VT.LOCAL) {
key = "L" + ((Local) v)._ls_index;
} else {
key = "C" + ((Constant) v).value;
}
Integer integer = lockMap.get(key);
if (integer != null) {
asm.visitVarInsn(getOpcode(v, ILOAD), integer);
} else {
accept(v, asm);
}
}
break;
// TODO other
default:
{
accept(v, asm);
break;
}
}
} else {
accept(v, asm);
}
asm.visitInsn(MONITOREXIT);
}
break;
case NOP:
break;
case RETURN:
{
Value v = ((UnopStmt) st).op;
accept(v, asm);
insertI2x(v.valueType, ir.ret, asm);
asm.visitInsn(getOpcode(v, IRETURN));
}
break;
case RETURN_VOID:
asm.visitInsn(RETURN);
break;
case LOOKUP_SWITCH:
{
LookupSwitchStmt lss = (LookupSwitchStmt) st;
accept(lss.op, asm);
Label[] targets = new Label[lss.targets.length];
for (int i = 0; i < targets.length; i++) {
targets[i] = (Label) lss.targets[i].tag;
}
asm.visitLookupSwitchInsn((Label) lss.defaultTarget.tag, lss.lookupValues, targets);
}
break;
case TABLE_SWITCH:
{
TableSwitchStmt tss = (TableSwitchStmt) st;
accept(tss.op, asm);
Label[] targets = new Label[tss.targets.length];
for (int i = 0; i < targets.length; i++) {
targets[i] = (Label) tss.targets[i].tag;
}
asm.visitTableSwitchInsn(tss.lowIndex, tss.lowIndex + targets.length - 1, (Label) tss.defaultTarget.tag, targets);
}
break;
case THROW:
accept(((UnopStmt) st).op, asm);
asm.visitInsn(ATHROW);
break;
case VOID_INVOKE:
Value op = st.getOp();
accept(op, asm);
String ret = op.valueType;
if (op.vt == VT.INVOKE_NEW) {
asm.visitInsn(POP);
} else if (!"V".equals(ret)) {
switch(ret.charAt(0)) {
case 'J':
case 'D':
asm.visitInsn(POP2);
break;
default:
asm.visitInsn(POP);
break;
}
}
break;
default:
throw new RuntimeException("not support st: " + st.st);
}
}
}
Aggregations