case RETURN_VOID:
break;
/** pushes some static field variable to the stack */
case GETSTATIC: {
final FieldInsnNode f = (FieldInsnNode) instruction.getInstruction();
final StaticField field = new StaticField(f.owner, f.name, f.desc);
stack.push(field);
fields.add(field);
break;
}
/** pops one operand (..., value) and store to a static field variable.
* this is a definition of that variable */
case PUTSTATIC: {
final FieldInsnNode f = (FieldInsnNode) instruction.getInstruction();
final ValueRef value = stack.pop();
/* new frame to indicate definition of static variable
* and use of the value in top of the stack */
final StaticField definition = new StaticField(f.owner, f.name, f.desc);
frame = new DefUseFrame(definition, value);
if (value instanceof ArrayRef) {
final BytecodeInstruction arraydef =
new BytecodeInstruction(new InsnNode(Opcodes.NOP));
final List<VariableRef> uses = Collections.emptyList();
arraydef.frame = new DefUseFrame(new ArrayComponent(definition), uses);
node.instructions.add(idx + 1, arraydef);
}
break;
}
/** pops one operand (..., object reference) and
* pushes a object field variable to the stack */
case GETFIELD: {
final FieldInsnNode f = (FieldInsnNode) instruction.getInstruction();
final ValueRef objectref = stack.pop();
final ObjectField field = new ObjectField(f.owner, f.name, f.desc, objectref);
stack.push(field);
ValueRef root = objectref;
while (root instanceof ObjectField) {
root = ObjectField.class.cast(root).objectref;
}
if (root instanceof Local || root instanceof StaticField) {
fields.add(field);
}
break;
}
/** pops two operands (..., object reference, value) and
* store value to a object field variable.
* this is a definition of that variable */
case PUTFIELD: {
final FieldInsnNode f = (FieldInsnNode) instruction.getInstruction();
final ValueRef value = stack.pop();
final ValueRef objectref = stack.pop();
ValueRef root = objectref;
while (root instanceof ObjectField) {