continue;
}
ValueBox allowedBox = null; // the only place the statement is allowed to reference an array without breaking it
boolean affected = false;
if (stmt instanceof DefinitionStmt) {
DefinitionStmt def = (DefinitionStmt)stmt;
if (def.getLeftOp() instanceof ArrayRef) {
ArrayRef array = (ArrayRef)def.getLeftOp();
allowedBox = array.getBaseBox();
if (array.getBase() == local) {
// assignment into interesting array
if (array.getIndex() instanceof IntConstant) {
IntConstant index = (IntConstant)array.getIndex();
if (index.value >= 0 && index.value < info.contents.length) {
ArrayConstantInfo out = info.clone();
out.contents[index.value] = def.getRightOpBox();
dest.put(local, out);
} else {
// definitely ArrayIndexOutOfBoundsException
// let's just map it to BOTTOM by not adding the array
dest.clear();
return;
}
} else {
// unknown index, information is lost
dead.add(local);
}
affected = true;
}
}
else if (def.getLeftOp() instanceof Local) {
for (int i=0; i<info.contents.length; i++) {
if (info.contents[i] == def.getLeftOp()) {
dead.add(local);
continue srcloop;
}
}
}
}
if (!affected) {
dest.put(local, src.get(local));
}
for (ValueBox used : stmt.getUseBoxes()) {
if (used.getValue() == local && used != allowedBox) {
dead.add(local);
break;
}
}
}
// consider new arrays that become live
if (stmt instanceof DefinitionStmt) {
DefinitionStmt def = (DefinitionStmt)stmt;
if (def.getRightOp() instanceof NewArrayExpr) {
Local left = (Local)def.getLeftOp(); // left side is local because right side is complex expression
NewArrayExpr expr = (NewArrayExpr)def.getRightOp();
if (expr.getSize() instanceof IntConstant) {
int size = ((IntConstant)expr.getSize()).value;
dest.put(left, new ArrayConstantInfo(new ValueBox[size]));
} else {
// unknown length
dead.add(left);
}
}
else if (def.getLeftOp().getType() instanceof ArrayType) {
if (def.getLeftOp() instanceof Local) {
Local left = (Local)def.getLeftOp();
// array acquired by some other means (method call, multidimensional array, typecast, aliasing, etc.)
dead.add(left);
}
}
}