case LLOAD_3:
pushByLocalLoad("J", seen - LLOAD_0);
break;
case GETSTATIC: {
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
XField fieldOperand = dbc.getXFieldOperand();
if (fieldOperand != null && fieldSummary.isComplete() && !fieldOperand.isPublic()) {
OpcodeStack.Item item = fieldSummary.getSummary(fieldOperand);
if (item != null) {
Item itm = new Item(item);
itm.setLoadedFromField(fieldOperand, Integer.MAX_VALUE);
itm.setPC(dbc.getPC());
push(itm);
break;
}
}
FieldAnnotation field = FieldAnnotation.fromReferencedField(dbc);
Item i = new Item(dbc.getSigConstantOperand(), field, Integer.MAX_VALUE);
if (field.getFieldName().equals("separator") && field.getClassName().equals("java.io.File")) {
i.setSpecialKind(Item.FILE_SEPARATOR_STRING);
}
i.setPC(dbc.getPC());
push(i);
break;
}
case LDC:
case LDC_W:
case LDC2_W:
cons = dbc.getConstantRefOperand();
pushByConstant(dbc, cons);
break;
case INSTANCEOF:
pop();
push(new Item("I"));
break;
case IFNONNULL:
case IFNULL:
// {
// Item topItem = pop();
// if (seen == IFNONNULL && topItem.isNull())
// break;
// seenTransferOfControl = true;
// addJumpValue(dbc.getPC(), dbc.getBranchTarget());
//
// break;
// }
case IFEQ:
case IFNE:
case IFLT:
case IFLE:
case IFGT:
case IFGE:
seenTransferOfControl = true;
{
Item topItem = pop();
// System.out.printf("%4d %10s %s%n",
// dbc.getPC(),OPCODE_NAMES[seen], topItem);
if (seen == IFLT || seen == IFLE) {
registerTestedFoundToBeNonnegative = topItem.registerNumber;
}
// if we see a test comparing a special negative value with
// 0,
// reset all other such values on the opcode stack
if (topItem.valueCouldBeNegative() && (seen == IFLT || seen == IFLE || seen == IFGT || seen == IFGE)) {
int specialKind = topItem.getSpecialKind();
for (Item item : stack) {
if (item != null && item.getSpecialKind() == specialKind) {
item.setSpecialKind(Item.NOT_SPECIAL);
}
}
for (Item item : lvValues) {
if (item != null && item.getSpecialKind() == specialKind) {
item.setSpecialKind(Item.NOT_SPECIAL);
}
}
}
}
addJumpValue(dbc.getPC(), dbc.getBranchTarget());
break;
case LOOKUPSWITCH:
case TABLESWITCH:
seenTransferOfControl = true;
setReachOnlyByBranch(true);
pop();
addJumpValue(dbc.getPC(), dbc.getBranchTarget());
int pc = dbc.getBranchTarget() - dbc.getBranchOffset();
for (int offset : dbc.getSwitchOffsets()) {
addJumpValue(dbc.getPC(), offset + pc);
}
break;
case ARETURN:
case DRETURN:
case FRETURN:
case IRETURN:
case LRETURN:
seenTransferOfControl = true;
setReachOnlyByBranch(true);
pop();
break;
case MONITORENTER:
case MONITOREXIT:
case POP:
pop();
break;
case PUTSTATIC:
pop();
eraseKnowledgeOf(dbc.getXFieldOperand());
break;
case PUTFIELD:
pop(2);
eraseKnowledgeOf(dbc.getXFieldOperand());
break;
case IF_ACMPEQ:
case IF_ACMPNE:
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPLE:
case IF_ICMPGT:
case IF_ICMPGE:
{
seenTransferOfControl = true;
Item right = pop();
Item left = pop();
Object lConstant = left.getConstant();
Object rConstant = right.getConstant();
boolean takeJump = false;
boolean handled = false;
if (seen == IF_ACMPNE || seen == IF_ACMPEQ) {
if (lConstant != null && rConstant != null && !lConstant.equals(rConstant) || lConstant != null
&& right.isNull() || rConstant != null && left.isNull()) {
handled = true;
takeJump = seen == IF_ACMPNE;
}
} else if (lConstant instanceof Integer && rConstant instanceof Integer) {
int lC = ((Integer) lConstant).intValue();
int rC = ((Integer) rConstant).intValue();
switch (seen) {
case IF_ICMPEQ:
takeJump = lC == rC;
handled = true;
break;
case IF_ICMPNE:
takeJump = lC != rC;
handled = true;
break;
case IF_ICMPGE:
takeJump = lC >= rC;
handled = true;
break;
case IF_ICMPGT:
takeJump = lC > rC;
handled = true;
break;
case IF_ICMPLE:
takeJump = lC <= rC;
handled = true;
break;
case IF_ICMPLT:
takeJump = lC < rC;
handled = true;
break;
default:
assert false;
}
}
if (handled) {
if (takeJump) {
int branchTarget = dbc.getBranchTarget();
addJumpValue(dbc.getPC(), branchTarget);
setTop(true);
break;
} else {
break;
}
}
if (right.hasConstantValue(Integer.MIN_VALUE) && left.mightRarelyBeNegative()
|| left.hasConstantValue(Integer.MIN_VALUE) && right.mightRarelyBeNegative()) {
for (Item i : stack) {
if (i != null && i.mightRarelyBeNegative()) {
i.setSpecialKind(Item.NOT_SPECIAL);
}
}
for (Item i : lvValues) {
if (i != null && i.mightRarelyBeNegative()) {
i.setSpecialKind(Item.NOT_SPECIAL);
}
}
}
int branchTarget = dbc.getBranchTarget();
addJumpValue(dbc.getPC(), branchTarget);
break;
}
case POP2:
it = pop();
if (it.getSize() == 1) {
pop();
}
break;
case IALOAD:
case SALOAD:
pop(2);
push(new Item("I"));
break;
case DUP:
handleDup();
break;
case DUP2:
handleDup2();
break;
case DUP_X1:
handleDupX1();
break;
case DUP_X2:
handleDupX2();
break;
case DUP2_X1:
handleDup2X1();
break;
case DUP2_X2:
handleDup2X2();
break;
case IINC:
register = dbc.getRegisterOperand();
it = getLVValue(register);
it2 = new Item("I", dbc.getIntConstant());
pushByIntMath(dbc, IADD, it2, it);
pushByLocalStore(register);
break;
case ATHROW:
pop();
seenTransferOfControl = true;
setReachOnlyByBranch(true);
setTop(true);
break;
case CHECKCAST: {
String castTo = dbc.getClassConstantOperand();
if (castTo.charAt(0) != '[') {
castTo = "L" + castTo + ";";
}
it = pop();
if (!it.signature.equals(castTo)) {
it = new Item(it, castTo);
}
push(it);
break;
}
case NOP:
break;
case RET:
case RETURN:
seenTransferOfControl = true;
setReachOnlyByBranch(true);
break;
case GOTO:
case GOTO_W:
seenTransferOfControl = true;
setReachOnlyByBranch(true);
addJumpValue(dbc.getPC(), dbc.getBranchTarget());
stack.clear();
setTop(true);
break;
case SWAP:
handleSwap();
break;
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
push(new Item("I", (seen - ICONST_0)));
break;
case LCONST_0:
case LCONST_1:
push(new Item("J", Long.valueOf(seen - LCONST_0)));
break;
case DCONST_0:
case DCONST_1:
push(new Item("D", Double.valueOf(seen - DCONST_0)));
break;
case FCONST_0:
case FCONST_1:
case FCONST_2:
push(new Item("F", Float.valueOf(seen - FCONST_0)));
break;
case ACONST_NULL:
push(new Item());
break;
case ASTORE:
case DSTORE:
case FSTORE:
case ISTORE:
case LSTORE:
pushByLocalStore(dbc.getRegisterOperand());
break;
case ASTORE_0:
case ASTORE_1:
case ASTORE_2:
case ASTORE_3:
pushByLocalStore(seen - ASTORE_0);
break;
case DSTORE_0:
case DSTORE_1:
case DSTORE_2:
case DSTORE_3:
pushByLocalStore(seen - DSTORE_0);
break;
case FSTORE_0:
case FSTORE_1:
case FSTORE_2:
case FSTORE_3:
pushByLocalStore(seen - FSTORE_0);
break;
case ISTORE_0:
case ISTORE_1:
case ISTORE_2:
case ISTORE_3:
pushByLocalStore(seen - ISTORE_0);
break;
case LSTORE_0:
case LSTORE_1:
case LSTORE_2:
case LSTORE_3:
pushByLocalStore(seen - LSTORE_0);
break;
case GETFIELD: {
FieldSummary fieldSummary = AnalysisContext.currentAnalysisContext().getFieldSummary();
XField fieldOperand = dbc.getXFieldOperand();
if (fieldOperand != null && fieldSummary.isComplete() && !fieldOperand.isPublic()) {
OpcodeStack.Item item = fieldSummary.getSummary(fieldOperand);
if (item != null) {
Item addr = pop();
Item itm = new Item(item);
itm.setLoadedFromField(fieldOperand, addr.getRegisterNumber());
itm.setPC(dbc.getPC());