JSR handling reworked

Allow fields to get their constant twice.


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1133 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent e88bfb332d
commit c41a61b4a3
  1. 429
      jode/jode/obfuscator/ConstantAnalyzer.java.in

@ -45,7 +45,6 @@ import @COLLECTIONS@.ListIterator;
* @author Jochen Hoenicke
*/
public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
Map constInfos;
BytecodeInfo bytecode;
@ -65,18 +64,25 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
private final static int CMP_EQUAL_MASK
= (1 << CMP_GE)|(1 << CMP_LE)|(1 << CMP_EQ);
final static int REACHABLE = 0x1;
final static int CONSTANT = 0x2;
final static int CONSTANTFLOW = 0x4;
final static int CONSTANT = 0x02;
final static int CONSTANTFLOW = 0x04;
final static int RETASTORE = 0x08;
final static int RETURNINGJSR = 0x10;
private interface ConstantListener {
public void constantChanged();
}
private static class JSRTargetInfo implements Cloneable {
private final static class JSRTargetInfo implements Cloneable {
Instruction jsrTarget;
BitSet usedLocals;
StackLocalInfo retInfo = null;
/**
* The dependent entries, that want to know if the bit set changed.
* This is either a StackLocalInfo (the ret info) or a single
* JSRTargetInfo or a Collection of JSRTargetInfos.
*/
Object dependent;
public JSRTargetInfo(Instruction target) {
jsrTarget = target;
@ -87,28 +93,65 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
try {
JSRTargetInfo result = (JSRTargetInfo) clone();
result.usedLocals = (BitSet) usedLocals.clone();
addDependent(result);
return result;
} catch (CloneNotSupportedException ex) {
throw new IncompatibleClassChangeError(ex.getMessage());
}
}
private void addDependent(JSRTargetInfo result) {
if (dependent == null || dependent == result)
dependent = result;
else if (dependent instanceof JSRTargetInfo) {
Set newDeps = new HashSet();
newDeps.add(dependent);
newDeps.add(result);
} else if (dependent instanceof Collection) {
((Collection) dependent).add(result);
}
}
public void setRetInfo(StackLocalInfo retInfo) {
dependent = retInfo;
}
public boolean uses(int localSlot) {
return usedLocals.get(localSlot);
}
public void addUsed(int localSlot) {
if (usedLocals.get(localSlot))
return;
usedLocals.set(localSlot);
if (dependent instanceof StackLocalInfo)
((StackLocalInfo) dependent).enqueue();
else if (dependent instanceof JSRTargetInfo)
((JSRTargetInfo) dependent).addUsed(localSlot);
else if (dependent instanceof Collection) {
Iterator iter = ((Collection) dependent).iterator();
while (iter.hasNext()) {
JSRTargetInfo dep = (JSRTargetInfo) iter.next();
dep.addUsed(localSlot);
}
}
}
public void merge(JSRTargetInfo o) {
BitSet used = (BitSet) usedLocals.clone();
used.or(o.usedLocals);
if (retInfo != null) {
if (o.retInfo != null && o.retInfo != retInfo)
throw new AssertError("retInfos differ");
o.retInfo = retInfo;
retInfo.enqueue();
o.addDependent(this);
for (int slot = 0; slot < o.usedLocals.size(); slot++) {
if (o.usedLocals.get(slot))
addUsed(slot);
}
}
public String toString() {
StringBuffer sb = new StringBuffer(String.valueOf(jsrTarget));
if (retInfo != null)
sb.append("->").append(retInfo.instr);
return sb.append(usedLocals).toString();
if (dependent instanceof StackLocalInfo)
sb.append("->").append(((StackLocalInfo) dependent).instr);
return sb.append(usedLocals)
.append('_').append(hashCode()).toString();
}
}
@ -180,8 +223,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
if (this == other)
return;
if (value == other.value
|| (value != null && value.equals(other.value))) {
if (value == null ? other.value == null
: value.equals(other.value)) {
if (value != VOLATILE) {
// other.addConstantListener(this);
this.addConstantListener(other);
@ -190,11 +233,13 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
}
if (value instanceof JSRTargetInfo
&& other.value instanceof JSRTargetInfo) {
&& other.value instanceof JSRTargetInfo
&& (((JSRTargetInfo) value).jsrTarget
== ((JSRTargetInfo) other.value).jsrTarget)) {
((JSRTargetInfo) value).merge((JSRTargetInfo) other.value);
return;
}
if (value != VOLATILE)
fireChanged();
// if (other.value != VOLATILE)
@ -214,6 +259,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
ConstValue[] stack;
ConstValue[] locals;
Instruction instr;
ConstantInfo constInfo;
StackLocalInfo retInfo;
StackLocalInfo nextOnQueue;
@ -333,20 +380,65 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
for (int i=0; i< locals.length; i++) {
if (locals[i] != null
&& locals[i].value instanceof JSRTargetInfo) {
locals[i] = locals[i].copy();
locals[i].value = ((JSRTargetInfo) locals[i].value).copy();
((JSRTargetInfo)locals[i].value).usedLocals.set(slot);
JSRTargetInfo jsrInfo = (JSRTargetInfo)locals[i].value;
if (!jsrInfo.uses(slot)) {
jsrInfo = jsrInfo.copy();
locals[i] = locals[i].copy();
locals[i].value = jsrInfo;
jsrInfo.addUsed(slot);
}
}
}
for (int i=0; i< stack.length; i++) {
if (stack[i] != null
&& stack[i].value instanceof JSRTargetInfo) {
JSRTargetInfo jsrInfo = (JSRTargetInfo)stack[i].value;
if (!jsrInfo.uses(slot)) {
jsrInfo = jsrInfo.copy();
stack[i] = stack[i].copy();
stack[i].value = jsrInfo;
jsrInfo.addUsed(slot);
}
}
}
return this;
}
public StackLocalInfo mergeRetLocals(JSRTargetInfo jsrTargetInfo,
StackLocalInfo retInfo) {
for (int slot = 0; slot < locals.length; slot++) {
if (jsrTargetInfo.uses(slot))
locals[slot] = retInfo.locals[slot];
}
locals[retInfo.instr.getLocalSlot()] = null;
for (int i=0; i< locals.length; i++) {
if (locals[i] != null
&& locals[i].value instanceof JSRTargetInfo) {
JSRTargetInfo jsrInfo = (JSRTargetInfo) locals[i].value;
jsrInfo = jsrInfo.copy();
locals[i] = locals[i].copy();
locals[i].value = ((JSRTargetInfo)locals[i].value).copy();
((JSRTargetInfo)locals[i].value).usedLocals.set(slot);
locals[i].value = jsrInfo;
for (int slot = 0; slot < locals.length; slot++) {
if (jsrTargetInfo.uses(slot))
jsrInfo.addUsed(slot);
}
}
}
return new StackLocalInfo(stack, locals, notifyQueue);
for (int i=0; i< stack.length; i++) {
if (stack[i] != null
&& stack[i].value instanceof JSRTargetInfo) {
JSRTargetInfo jsrInfo = (JSRTargetInfo)stack[i].value;
jsrInfo = jsrInfo.copy();
stack[i] = stack[i].copy();
stack[i].value = jsrInfo;
for (int slot = 0; slot < locals.length; slot++) {
if (jsrTargetInfo.uses(slot))
jsrInfo.addUsed(slot);
}
}
}
return this;
}
public void merge(StackLocalInfo other) {
@ -378,7 +470,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
private static class ConstantInfo implements ConstantListener {
ConstantInfo() {
this(REACHABLE, null);
this(0, null);
}
ConstantInfo(int flags) {
@ -488,7 +580,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void handleOpcode(StackLocalInfo info, Identifier fieldListener) {
Instruction instr = info.instr;
constInfos.put(instr, unknownConstInfo);
info.constInfo = unknownConstInfo;
int opcode = instr.getOpcode();
Handler[] handlers = bytecode.getExceptionHandlers();
@ -519,11 +611,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
System.err.println(instr);
}
if (result.value != ConstValue.VOLATILE) {
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = result.value;
result.addConstantListener(shortInfo);
info.constInfo = new ConstantInfo(CONSTANT, result.value);
result.addConstantListener(info.constInfo);
}
mergeInfo(instr.getNextByAddr(),
info.poppush(0, result)
@ -573,8 +662,11 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
break;
}
case opc_istore: case opc_fstore: case opc_astore: {
result = info.getStack(1);
if (result.value instanceof JSRTargetInfo)
info.constInfo.flags |= RETASTORE;
mergeInfo(instr.getNextByAddr(),
info.pop(1).setLocal(instr.getLocalSlot(), info.getStack(1)));
info.pop(1).setLocal(instr.getLocalSlot(), result));
break;
}
case opc_lstore: case opc_dstore: {
@ -590,8 +682,11 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
mergeInfo(instr.getNextByAddr(), info.pop(2+size));
break;
}
case opc_pop: case opc_pop2:
mergeInfo(instr.getNextByAddr(), info.pop(opcode - (opc_pop - 1)));
case opc_pop:
mergeInfo(instr.getNextByAddr(), info.pop(1));
break;
case opc_pop2:
mergeInfo(instr.getNextByAddr(), info.pop(2));
break;
case opc_dup: case opc_dup_x1: case opc_dup_x2:
@ -763,12 +858,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
default:
throw new jode.AssertError("Can't happen.");
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = newValue;
info.constInfo = new ConstantInfo(CONSTANT, newValue);
result = new ConstValue(newValue);
result.addConstantListener(shortInfo);
result.addConstantListener(info.constInfo);
value1.addConstantListener(result);
value2.addConstantListener(result);
} else
@ -801,12 +893,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
default:
throw new jode.AssertError("Can't happen.");
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = newValue;
info.constInfo = new ConstantInfo(CONSTANT, newValue);
result = new ConstValue(newValue);
result.addConstantListener(shortInfo);
result.addConstantListener(info.constInfo);
value.addConstantListener(result);
} else
result = unknownValue[size-1];
@ -857,12 +946,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
default:
throw new jode.AssertError("Can't happen.");
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = newValue;
info.constInfo = new ConstantInfo(CONSTANT, newValue);
result = new ConstValue(newValue);
result.addConstantListener(shortInfo);
result.addConstantListener(info.constInfo);
value1.addConstantListener(result);
value2.addConstantListener(result);
} else
@ -907,12 +993,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
default:
throw new jode.AssertError("Can't happen.");
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = newVal;
info.constInfo = new ConstantInfo(CONSTANT, newVal);
result = new ConstValue(newVal);
result.addConstantListener(shortInfo);
result.addConstantListener(info.constInfo);
stack.addConstantListener(result);
} else {
switch (opcode) {
@ -942,12 +1025,10 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
val = (short) val;
break;
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = new Integer(val);
result = new ConstValue(shortInfo.constant);
stack.addConstantListener(shortInfo);
Integer newVal = new Integer(val);
info.constInfo = new ConstantInfo(CONSTANT, newVal);
result = new ConstValue(newVal);
stack.addConstantListener(info.constInfo);
stack.addConstantListener(result);
} else
result = unknownValue[0];
@ -962,13 +1043,11 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
&& val2.value != ConstValue.VOLATILE) {
long value1 = ((Long) val1.value).longValue();
long value2 = ((Long) val1.value).longValue();
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = new Integer(value1 == value2 ? 0
: value1 < value2 ? -1 : 1);
result = new ConstValue(shortInfo.constant);
result.addConstantListener(shortInfo);
Integer newVal = new Integer(value1 == value2 ? 0
: value1 < value2 ? -1 : 1);
info.constInfo = new ConstantInfo(CONSTANT, newVal);
result = new ConstValue(newVal);
result.addConstantListener(info.constInfo);
val1.addConstantListener(result);
val2.addConstantListener(result);
} else
@ -983,16 +1062,14 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
&& val2.value != ConstValue.VOLATILE) {
float value1 = ((Float) val1.value).floatValue();
float value2 = ((Float) val1.value).floatValue();
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = new Integer
Integer newVal = new Integer
(value1 == value2 ? 0
: ( opcode == opc_fcmpg
? (value1 < value2 ? -1 : 1)
: (value1 > value2 ? 1 : -1)));
result = new ConstValue(shortInfo.constant);
result.addConstantListener(shortInfo);
info.constInfo = new ConstantInfo(CONSTANT, newVal);
result = new ConstValue(newVal);
result.addConstantListener(info.constInfo);
val1.addConstantListener(result);
val2.addConstantListener(result);
} else
@ -1007,16 +1084,14 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
&& val2.value != ConstValue.VOLATILE) {
double value1 = ((Double) val1.value).doubleValue();
double value2 = ((Double) val1.value).doubleValue();
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = new Integer
Integer newVal = new Integer
(value1 == value2 ? 0
: ( opcode == opc_dcmpg
? (value1 < value2 ? -1 : 1)
: (value1 > value2 ? 1 : -1)));
result = new ConstValue(shortInfo.constant);
result.addConstantListener(shortInfo);
info.constInfo = new ConstantInfo(CONSTANT, newVal);
result = new ConstValue(newVal);
result.addConstantListener(info.constInfo);
val1.addConstantListener(result);
val2.addConstantListener(result);
} else
@ -1077,10 +1152,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
if ((opc_mask & (1<<opcode)) != 0)
pc = instr.getSingleSucc();
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANTFLOW;
shortInfo.constant = pc;
info.constInfo = new ConstantInfo(CONSTANTFLOW, pc);
mergeInfo(pc, info.pop(size));
} else {
mergeInfo(instr.getNextByAddr(), info.pop(size));
@ -1091,12 +1163,6 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_goto:
mergeInfo(instr.getSingleSucc(), info.copy());
break;
case opc_jsr:
mergeInfo(instr.getSingleSucc(),
info.poppush(0, new ConstValue
(new JSRTargetInfo(instr.getSingleSucc()))
));
break;
case opc_lookupswitch: {
ConstValue stacktop = info.getStack(1);
if (stacktop.value != ConstValue.VOLATILE) {
@ -1111,10 +1177,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
break;
}
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANTFLOW;
shortInfo.constant = pc;
info.constInfo = new ConstantInfo(CONSTANTFLOW, pc);
mergeInfo(pc, info.pop(1));
} else {
for (int i=0; i < instr.getSuccs().length; i++)
@ -1122,28 +1185,48 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
}
break;
}
case opc_jsr:
// dumpStackLocalInfo();
// System.err.println(instr);
if (instr.getSingleSucc().getOpcode() != opc_astore)
throw new RuntimeException("Can't handle jsr to non astores");
StackLocalInfo oldJsrInfo =
(StackLocalInfo) instr.getSingleSucc().getTmpInfo();
if (oldJsrInfo != null) {
result = oldJsrInfo.getStack(1);
if (oldJsrInfo.retInfo != null
&& result.value instanceof JSRTargetInfo) {
mergeInfo(instr.getNextByAddr(),
info.copy()
.mergeRetLocals((JSRTargetInfo) result.value,
oldJsrInfo.retInfo));
}
} else {
result = new ConstValue
(new JSRTargetInfo(instr.getSingleSucc()));
}
mergeInfo(instr.getSingleSucc(), info.poppush(0, result));
break;
case opc_ret: {
// dumpStackLocalInfo();
// System.err.println(instr);
result = info.getLocal(instr.getLocalSlot());
JSRTargetInfo jsrInfo = (JSRTargetInfo) result.value;
jsrInfo.retInfo = info;
jsrInfo.setRetInfo(info);
result.addConstantListener(info);
Instruction jsrTarget = jsrInfo.jsrTarget;
for (int i=0; i < jsrTarget.getPreds().length; i++) {
Instruction jsr = jsrTarget.getPreds()[i];
if (jsr.getTmpInfo() == null)
continue;
StackLocalInfo nextInfo
= ((StackLocalInfo) jsr.getTmpInfo()).copy();
int maxLocals = bytecode.getMaxLocals();
for (int slot = 0; slot < maxLocals; slot++) {
if (slot == instr.getLocalSlot())
nextInfo.setLocal(slot, null);
else if (jsrInfo.usedLocals.get(slot))
nextInfo.setLocal(slot, info.getLocal(slot));
StackLocalInfo jsrTargetStackInfo =
(StackLocalInfo) jsrTarget.getTmpInfo();
jsrTargetStackInfo.retInfo = info;
jsrTargetStackInfo.constInfo.flags |= RETURNINGJSR;
Instruction[] jsrs = jsrTarget.getPreds();
for (int i=0; i < jsrs.length; i++) {
Instruction jsr = jsrs[i];
if (jsr.getTmpInfo() != null) {
mergeInfo(jsr.getNextByAddr(),
((StackLocalInfo) jsr.getTmpInfo()).copy()
.mergeRetLocals(jsrInfo, info));
}
mergeInfo(jsr.getNextByAddr(), nextInfo);
}
break;
}
@ -1156,13 +1239,22 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
case opc_putstatic:
case opc_putfield: {
FieldIdentifier fi = (FieldIdentifier) canonizeReference(instr);
int size = (opcode == opc_putstatic) ? 0 : 1;
Reference ref = instr.getReference();
size += TypeSignature.getTypeSize(ref.getType());
int size = TypeSignature.getTypeSize(ref.getType());
if (fi != null && !fi.isNotConstant()) {
fi.setNotConstant();
fieldNotConstant(fi);
ConstValue stacktop = info.getStack(size);
Object fieldVal = fi.getConstant();
if (fieldVal == null)
fieldVal = runtime.getDefaultValue(ref.getType());
if (stacktop.value == null ? fieldVal == null
: stacktop.value.equals(fieldVal)) {
stacktop.addConstantListener(info);
} else {
fi.setNotConstant();
fieldNotConstant(fi);
}
}
size += (opcode == opc_putstatic) ? 0 : 1;
mergeInfo(instr.getNextByAddr(), info.pop(size));
break;
}
@ -1178,32 +1270,11 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
result = unknownValue[typesize - 1];
} else {
Object obj = fi.getConstant();
if (obj == null) {
switch (ref.getType().charAt(0)) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
obj = new Integer(0);
break;
case 'J':
obj = new Long(0);
break;
case 'F':
obj = new Float(0);
break;
case 'D':
obj = new Double(0);
break;
}
}
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = obj;
if (obj == null)
obj = runtime.getDefaultValue(ref.getType());
info.constInfo = new ConstantInfo(CONSTANT, obj);
result = new ConstValue(obj);
result.addConstantListener(shortInfo);
result.addConstantListener(info.constInfo);
fi.addFieldListener(fieldListener);
}
} else
@ -1280,12 +1351,9 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
int retsize = TypeSignature.getTypeSize(retType);
returnVal = unknownValue[retsize - 1];
} else {
ConstantInfo shortInfo = new ConstantInfo();
constInfos.put(instr, shortInfo);
shortInfo.flags |= CONSTANT;
shortInfo.constant = methodResult;
info.constInfo = new ConstantInfo(CONSTANT, methodResult);
returnVal = new ConstValue(methodResult);
returnVal.addConstantListener(shortInfo);
returnVal.addConstantListener(info.constInfo);
if (clsValue != null)
clsValue.addConstantListener(returnVal);
for (int i=0; i< argValues.length; i++)
@ -1304,10 +1372,10 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
// ConstValue array = info.getStack(1);
// if (array.value != ConstValue.VOLATILE
// && array.value != null) {
// shortInfo.flags |= CONSTANT;
// shortInfo.constant = new Integer(Array.getLength(array.value));
// result = new ConstValue(shortInfo.constant);
// result.addConstantListener(shortInfo);
// Integer newValue = new Integer(Array.getLength(array.value));
// info.constInfo = new ConstantInfo(CONSTANT, newValue);
// result = new ConstValue(newValue);
// result.addConstantListener(info.constInfo);
// array.addConstantListener(result);
// } else
result = unknownValue[0];
@ -1334,9 +1402,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
info.poppush(instr.getDimensions(), unknownValue[0]));
break;
default:
throw new jode.AssertError("Invalid opcode "+opcode);
throw new IllegalArgumentException("Invalid opcode "+opcode);
}
}
public void fieldNotConstant(FieldIdentifier fi) {
@ -1359,8 +1426,7 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
for (Iterator iter = bytecode.getInstructions().iterator();
iter.hasNext(); ) {
Instruction instr = (Instruction) iter.next();
StackLocalInfo info = (StackLocalInfo) instr.getTmpInfo();
System.err.println(""+info);
System.err.println(""+instr.getTmpInfo());
System.err.println(instr.getDescription());
}
}
@ -1368,10 +1434,15 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
public void analyzeCode(MethodIdentifier methodIdent,
BytecodeInfo bytecode) {
this.bytecode = bytecode;
if (constInfos == null)
constInfos = new HashMap();
TodoQueue modifiedQueue = new TodoQueue();
MethodInfo minfo = bytecode.getMethodInfo();
for (Iterator iter = bytecode.getInstructions().iterator();
iter.hasNext(); ) {
Instruction instr = (Instruction) iter.next();
instr.setTmpInfo(null);
}
StackLocalInfo firstInfo = new StackLocalInfo
(bytecode.getMaxLocals(), minfo.isStatic(), minfo.getType(),
modifiedQueue);
@ -1392,8 +1463,16 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
Main.getClassBundle().reachableClass(handlers[i].type);
}
for (Iterator iter = bytecode.getInstructions().iterator();
iter.hasNext(); )
((Instruction) iter.next()).setTmpInfo(null);
iter.hasNext(); ) {
Instruction instr = (Instruction) iter.next();
StackLocalInfo info = (StackLocalInfo) instr.getTmpInfo();
if (info != null) {
if (info.constInfo.flags == 0)
instr.setTmpInfo(unknownConstInfo);
else
instr.setTmpInfo(info.constInfo);
}
}
}
public static void replaceWith(ListIterator iter, Instruction instr,
@ -1509,9 +1588,13 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
for (ListIterator iter = bytecode.getInstructions().listIterator();
iter.hasNext(); ) {
Instruction instr = (Instruction) iter.next();
ConstantInfo info = (ConstantInfo) constInfos.get(instr);
if (info == null || (info.flags & REACHABLE) == 0) {
/* This instruction can't be reached logically */
ConstantInfo info = (ConstantInfo) instr.getTmpInfo();
instr.setTmpInfo(null);
if (info == null
|| (info.flags & (RETURNINGJSR | RETASTORE)) == RETASTORE) {
/* This instruction can't be reached logically, or
* it is a return value astore, that should be removed */
iter.remove();
} else if ((info.flags & CONSTANT) != 0) {
if (instr.getOpcode() > opc_ldc2_w) {
@ -1539,9 +1622,8 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
+ " with goto " + pc.getAddr());
while (iter.hasNext()) {
ConstantInfo nextinfo = (ConstantInfo)
constInfos.get((Instruction) iter.next());
if (nextinfo != null
&& (nextinfo.flags & REACHABLE) != 0) {
((Instruction) iter.next()).getTmpInfo();
if (nextinfo != null) {
Instruction nextInstr = (Instruction) iter.previous();
if (pc != nextInstr)
appendJump(iter, pc);
@ -1558,6 +1640,21 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
iter.remove();
break;
case opc_jsr:
ConstantInfo jsrinfo = (ConstantInfo)
instr.getSingleSucc().getTmpInfo();
if ((jsrinfo.flags & RETURNINGJSR) != 0)
/* A normal jsr, don't change it */
break;
/* This means, the jsr will never return. We
* replace it with a goto, the jsr will transform
* itself to remove the astore operation.
*/
Instruction gotoInstr = new Instruction(opc_goto);
gotoInstr.setSuccs(instr.getSingleSucc());
iter.set(gotoInstr);
/* fall through */
case opc_goto:
case opc_ifeq: case opc_ifne:
case opc_iflt: case opc_ifge:
@ -1570,18 +1667,22 @@ public class ConstantAnalyzer implements Opcodes, CodeAnalyzer {
while (iter.hasNext()) {
ConstantInfo nextinfo = (ConstantInfo)
constInfos.get((Instruction) iter.next());
((Instruction) iter.next()).getTmpInfo();
if (nextinfo != null
&& (nextinfo.flags & REACHABLE) != 0) {
&& ((nextinfo.flags & (RETURNINGJSR | RETASTORE))
!= RETASTORE)) {
Instruction nextInstr
= (Instruction) iter.previous();
if (instr.getSingleSucc() == nextInstr) {
/* put iter in sane state */
iter.previous();
iter.next();
replaceWith(iter, instr, null);
}
break;
}
/* Next instruction can't be reached logically */
/* Next instruction can be removed */
iter.remove();
}
break;

Loading…
Cancel
Save