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()));
        }
    }
  }
private static void processSpecialInstructions(DataPoint data, Instruction instr, ConstantPool pool)