in src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java [367:510]
private static void processSpecialInstructions(DataPoint data, Instruction instr, ConstantPool pool) {
VarType var1;
PrimitiveConstant cn;
LinkConstant ck;
ListStack<VarType> stack = data.getStack();
switch (instr.opcode) {
case CodeConstants.opc_aconst_null:
stack.push(new VarType(CodeConstants.TYPE_NULL, 0, null));
break;
case CodeConstants.opc_ldc:
case CodeConstants.opc_ldc_w:
case CodeConstants.opc_ldc2_w:
PooledConstant constant = pool.getConstant(instr.operand(0));
switch (constant.type) {
case CodeConstants.CONSTANT_Integer -> stack.push(new VarType(CodeConstants.TYPE_INT));
case CodeConstants.CONSTANT_Float -> stack.push(new VarType(CodeConstants.TYPE_FLOAT));
case CodeConstants.CONSTANT_Long -> {
stack.push(new VarType(CodeConstants.TYPE_LONG));
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
case CodeConstants.CONSTANT_Double -> {
stack.push(new VarType(CodeConstants.TYPE_DOUBLE));
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
case CodeConstants.CONSTANT_String -> stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"));
case CodeConstants.CONSTANT_Class -> stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"));
case CodeConstants.CONSTANT_MethodHandle -> stack.push(new VarType(((LinkConstant)constant).descriptor));
case CodeConstants.CONSTANT_Dynamic -> {
ck = pool.getLinkConstant(instr.operand(0));
FieldDescriptor constDescriptor = FieldDescriptor.parseDescriptor(ck.descriptor);
stack.push(constDescriptor.type);
if (constDescriptor.type.getStackSize() == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
}
}
break;
case CodeConstants.opc_aload:
var1 = data.getVariable(instr.operand(0));
if (var1 != null) {
stack.push(var1);
}
else {
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, null));
}
break;
case CodeConstants.opc_aaload:
var1 = stack.pop(2);
stack.push(new VarType(var1.getType(), var1.getArrayDim() - 1, var1.getValue()));
break;
case CodeConstants.opc_astore:
data.setVariable(instr.operand(0), stack.pop());
break;
case CodeConstants.opc_dup:
case CodeConstants.opc_dup_x1:
case CodeConstants.opc_dup_x2:
int depth1 = 88 - instr.opcode;
stack.insertByOffset(depth1, stack.getByOffset(-1).copy());
break;
case CodeConstants.opc_dup2:
case CodeConstants.opc_dup2_x1:
case CodeConstants.opc_dup2_x2:
int depth2 = 90 - instr.opcode;
stack.insertByOffset(depth2, stack.getByOffset(-2).copy());
stack.insertByOffset(depth2, stack.getByOffset(-1).copy());
break;
case CodeConstants.opc_swap:
var1 = stack.pop();
stack.insertByOffset(-1, var1);
break;
case CodeConstants.opc_getfield:
stack.pop();
case CodeConstants.opc_getstatic:
ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
stack.push(var1);
if (var1.getStackSize() == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
break;
case CodeConstants.opc_putfield:
stack.pop();
case CodeConstants.opc_putstatic:
ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
stack.pop(var1.getStackSize());
break;
case CodeConstants.opc_invokevirtual:
case CodeConstants.opc_invokespecial:
case CodeConstants.opc_invokeinterface:
stack.pop();
case CodeConstants.opc_invokestatic:
case CodeConstants.opc_invokedynamic:
if (instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecodeVersion >= CodeConstants.BYTECODE_JAVA_7) {
ck = pool.getLinkConstant(instr.operand(0));
MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor);
for (int i = 0; i < md.params.length; i++) {
stack.pop(md.params[i].getStackSize());
}
if (md.ret.getType() != CodeConstants.TYPE_VOID) {
stack.push(md.ret);
if (md.ret.getStackSize() == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
}
}
break;
case CodeConstants.opc_new:
cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_newarray:
stack.pop();
stack.push(new VarType(arr_type[instr.operand(0) - 4], 1).resizeArrayDim(1));
break;
case CodeConstants.opc_athrow:
var1 = stack.pop();
stack.clear();
stack.push(var1);
break;
case CodeConstants.opc_checkcast:
case CodeConstants.opc_instanceof:
stack.pop();
cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_anewarray:
case CodeConstants.opc_multianewarray:
int dimensions = (instr.opcode == CodeConstants.opc_anewarray) ? 1 : instr.operand(1);
stack.pop(dimensions);
cn = pool.getPrimitiveConstant(instr.operand(0));
if (cn.isArray) {
var1 = new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString());
var1 = var1.resizeArrayDim(var1.getArrayDim() + dimensions);
stack.push(var1);
}
else {
stack.push(new VarType(CodeConstants.TYPE_OBJECT, dimensions, cn.getString()));
}
}
}