private static <T> void appendGetDelayedCellSetterSwitch(
      DelayedCellSetterFactory<T, ?>[] delayedCellSetters,
      String classType,
      MethodVisitor mv,
      int switchStart,
      int switchEnd) {
    mv.visitVarInsn(ILOAD, 1);
    Label defaultLabel = new Label();
    Label[] labels = newLabels(switchEnd - switchStart);
    mv.visitTableSwitchInsn(switchStart, switchEnd - 1, defaultLabel, labels);

    for (int i = switchStart; i < switchEnd; i++) {
      mv.visitLabel(labels[i - switchStart]);
      mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
      if (delayedCellSetters != null) {
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD, classType, "delayedCellSetter" + i, "L" + DELAYED_CELL_SETTER_TYPE + ";");
      } else {
        mv.visitInsn(ACONST_NULL);
      }
      mv.visitInsn(ARETURN);
    }

    mv.visitLabel(defaultLabel);
    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
  }
  protected void injectGetByIndex(
      ClassWriter classWriter, String targetClassName, List<Field> fields) {
    MethodVisitor methodVisitor =
        classWriter.visitMethod(
            ACC_PUBLIC,
            "get",
            "(Ljava/lang/Object;I)Ljava/lang/Object;",
            null,
            new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())});

    Boxer boxer = new Boxer(methodVisitor);

    methodVisitor.visitCode();
    methodVisitor.visitVarInsn(ILOAD, 2);

    int maxStack = 6;

    Label[] labels = new Label[fields.size()];
    Label errorLabel = new Label();

    for (int i = 0; i < fields.size(); i++) {
      labels[i] = new Label();
    }

    methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels);

    if (!fields.isEmpty()) {
      maxStack--;

      for (int i = 0; i < fields.size(); i++) {
        Field field = fields.get(i);
        Class<?> type = field.getType();
        String fieldDescriptor = Type.getDescriptor(type);

        methodVisitor.visitLabel(labels[i]);

        if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null);
        else methodVisitor.visitFrame(F_SAME, 0, null, 0, null);

        if (isPublic(field)) {
          methodVisitor.visitVarInsn(ALOAD, 1);
          methodVisitor.visitTypeInsn(CHECKCAST, targetClassName);
          methodVisitor.visitFieldInsn(GETFIELD, targetClassName, field.getName(), fieldDescriptor);

          boxer.box(Type.getType(type));
        } else {
          injectReflectiveGetter(methodVisitor);
        }

        methodVisitor.visitInsn(ARETURN);
      }

      methodVisitor.visitLabel(errorLabel);
      methodVisitor.visitFrame(F_SAME, 0, null, 0, null);
    }

    injectException(methodVisitor, IllegalAccessException.class);
    methodVisitor.visitMaxs(maxStack, 3);
    methodVisitor.visitEnd();
  }
 private static <T> void appendCellValue(
     CellSetter<T>[] setters, boolean ignoreException, ClassWriter cw, String classType) {
   MethodVisitor mv;
   mv = cw.visitMethod(ACC_PUBLIC, "cellValue", "([CIII)V", null, null);
   mv.visitCode();
   if (setters.length != 0) {
     if (ignoreException) {
       callCellValue(mv, classType);
     } else {
       Label l0 = new Label();
       Label l1 = new Label();
       Label l2 = new Label();
       mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
       mv.visitLabel(l0);
       callCellValue(mv, classType);
       mv.visitLabel(l1);
       Label l3 = new Label();
       mv.visitJumpInsn(GOTO, l3);
       mv.visitLabel(l2);
       mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/Exception"});
       mv.visitVarInsn(ASTORE, 5);
       mv.visitVarInsn(ALOAD, 0);
       mv.visitVarInsn(ILOAD, 4);
       mv.visitVarInsn(ALOAD, 5);
       mv.visitMethodInsn(
           INVOKEVIRTUAL, classType, "fieldError", "(ILjava/lang/Exception;)V", false);
       mv.visitLabel(l3);
       mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
     }
   }
   mv.visitInsn(RETURN);
   mv.visitMaxs(5, 6);
   mv.visitEnd();
 }
Example #4
0
  private static void insertGetString(
      ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv =
        cw.visitMethod(
            ACC_PUBLIC, "getString", "(Ljava/lang/Object;I)Ljava/lang/String;", null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
      maxStack--;
      Label[] labels = new Label[fields.size()];
      Label labelForInvalidTypes = new Label();
      boolean hasAnyBadTypeLabel = false;
      for (int i = 0, n = labels.length; i < n; i++) {
        if (fields.get(i).getType().equals(String.class)) labels[i] = new Label();
        else {
          labels[i] = labelForInvalidTypes;
          hasAnyBadTypeLabel = true;
        }
      }
      Label defaultLabel = new Label();
      mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

      for (int i = 0, n = labels.length; i < n; i++) {
        if (!labels[i].equals(labelForInvalidTypes)) {
          Field field = fields.get(i);
          mv.visitLabel(labels[i]);
          mv.visitFrame(F_SAME, 0, null, 0, null);
          if (!Modifier.isStatic(field.getModifiers())) {
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, classNameInternal);
          }
          mv.visitFieldInsn(
              Modifier.isStatic(field.getModifiers()) ? GETSTATIC : GETFIELD,
              classNameInternal,
              field.getName(),
              "Ljava/lang/String;");
          mv.visitInsn(ARETURN);
        }
      }
      // Rest of fields: different type
      if (hasAnyBadTypeLabel) {
        mv.visitLabel(labelForInvalidTypes);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        insertThrowExceptionForFieldType(mv, "String");
      }
      // Default: field not found
      mv.visitLabel(defaultLabel);
      mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
  }
 protected void injectGetIndex(ClassWriter classWriter) {
   MethodVisitor mv =
       classWriter.visitMethod(ACC_PRIVATE, "getIndex", "(Ljava/lang/String;)I", null, null);
   mv.visitCode();
   mv.visitInsn(ICONST_0);
   mv.visitVarInsn(ISTORE, 2);
   Label forLoopLabel = new Label();
   mv.visitLabel(forLoopLabel);
   mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null);
   mv.visitVarInsn(ILOAD, 2);
   mv.visitVarInsn(ALOAD, 0);
   mv.visitFieldInsn(
       GETFIELD,
       getAccessorNameInternal(this.getTarget(), this.getAccessorType()),
       "fieldTable",
       "[Ljava/lang/reflect/Field;");
   mv.visitInsn(ARRAYLENGTH);
   Label forLoopIncrementLabel = new Label();
   mv.visitJumpInsn(IF_ICMPGE, forLoopIncrementLabel);
   mv.visitVarInsn(ALOAD, 0);
   mv.visitFieldInsn(
       GETFIELD,
       getAccessorNameInternal(this.getTarget(), this.getAccessorType()),
       "fieldTable",
       "[Ljava/lang/reflect/Field;");
   mv.visitVarInsn(ILOAD, 2);
   mv.visitInsn(AALOAD);
   mv.visitMethodInsn(
       INVOKEVIRTUAL, "java/lang/reflect/Field", "getName", "()Ljava/lang/String;", false);
   mv.visitVarInsn(ALOAD, 1);
   mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
   Label equalsLabel = new Label();
   mv.visitJumpInsn(IFEQ, equalsLabel);
   mv.visitVarInsn(ILOAD, 2);
   mv.visitInsn(IRETURN);
   mv.visitLabel(equalsLabel);
   mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
   mv.visitIincInsn(2, 1);
   mv.visitJumpInsn(GOTO, forLoopLabel);
   mv.visitLabel(forLoopIncrementLabel);
   mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
   mv.visitInsn(ICONST_M1);
   mv.visitInsn(IRETURN);
   mv.visitMaxs(2, 3);
   mv.visitEnd();
 }
 public void visitFrame(int i, int i1, Object[] objects, int i2, Object[] objects1) {
   System.out.println(
       "visitFrame(" + i + ", " + i1 + ", " + objects + ", " + i2 + ", " + objects1 + ")");
   methodVisitor.visitFrame(i, i1, objects, i2, objects1);
 }
    @Override
    public void nodeDispatch(String suffix, int divide, int start, int end) {
      MethodVisitor mv;
      mv = cw.visitMethod(ACC_PRIVATE, name() + suffix, signature(), null, null);
      mv.visitCode();
      Label startLabel = new Label();
      mv.visitLabel(startLabel);
      final int powerOfTwo = Integer.numberOfTrailingZeros(divide);

      int sStart = start >> powerOfTwo;
      int sEnd = end >> powerOfTwo;

      int left = end - (sEnd << powerOfTwo);
      if (left > 0) {
        sEnd++;
      }

      Label[] labels = newLabels(sEnd - sStart);
      Label defaultLabel = new Label();

      mv.visitVarInsn(ILOAD, argIndex());

      int sub = leafStart();
      if (sub != 0) {
        AsmUtils.addIndex(mv, sub);
        mv.visitInsn(ISUB);
      }

      AsmUtils.addIndex(mv, powerOfTwo);
      mv.visitInsn(ISHR);

      mv.visitVarInsn(ISTORE, maxArgIndex() + 1);
      mv.visitVarInsn(ILOAD, maxArgIndex() + 1);
      mv.visitTableSwitchInsn(sStart, sEnd - 1, defaultLabel, labels);

      for (int i = sStart; i < sEnd; i++) {

        int estart = i << powerOfTwo;
        int eend = Math.min(end, (i + 1) << powerOfTwo);

        mv.visitLabel(labels[i - sStart]);
        if (i == start) {
          mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null);
        } else {
          mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }

        loadArguments(mv);
        mv.visitMethodInsn(
            INVOKESPECIAL,
            classType,
            name() + (divide / maxMethodSize) + "n" + estart + "t" + eend,
            signature(),
            false);

        if (isVoid()) {
          if (i < (sEnd - 1)) {
            mv.visitJumpInsn(GOTO, defaultLabel);
          }
        } else {
          mv.visitInsn(ARETURN);
        }
      }

      mv.visitLabel(defaultLabel);
      mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

      if (isVoid()) {
        mv.visitInsn(RETURN);
      } else {
        mv.visitInsn(ACONST_NULL);
        mv.visitInsn(ARETURN);
      }

      Label endLabel = new Label();
      mv.visitLabel(endLabel);
      appendDebugInfo(mv, startLabel, endLabel);
      mv.visitMaxs(6, 5);
      mv.visitEnd();
    }
Example #8
0
 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
   visitor.visitFrame(type, nLocal, local, nStack, stack);
 }
Example #9
0
 @Override
 public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
   super.visitFrame(type, nLocal, local, nStack, stack);
 }
Example #10
0
  private static void insertGetPrimitive(
      ClassWriter cw, String classNameInternal, ArrayList<Field> fields, Type primitiveType) {
    int maxStack = 6;
    final String getterMethodName;
    final String typeNameInternal = primitiveType.getDescriptor();
    final int returnValueInstruction;
    switch (primitiveType.getSort()) {
      case Type.BOOLEAN:
        getterMethodName = "getBoolean";
        returnValueInstruction = IRETURN;
        break;
      case Type.BYTE:
        getterMethodName = "getByte";
        returnValueInstruction = IRETURN;
        break;
      case Type.CHAR:
        getterMethodName = "getChar";
        returnValueInstruction = IRETURN;
        break;
      case Type.SHORT:
        getterMethodName = "getShort";
        returnValueInstruction = IRETURN;
        break;
      case Type.INT:
        getterMethodName = "getInt";
        returnValueInstruction = IRETURN;
        break;
      case Type.FLOAT:
        getterMethodName = "getFloat";
        returnValueInstruction = FRETURN;
        break;
      case Type.LONG:
        getterMethodName = "getLong";
        returnValueInstruction = LRETURN;
        break;
      case Type.DOUBLE:
        getterMethodName = "getDouble";
        returnValueInstruction = DRETURN;
        break;
      default:
        getterMethodName = "get";
        returnValueInstruction = ARETURN;
        break;
    }
    MethodVisitor mv =
        cw.visitMethod(
            ACC_PUBLIC, getterMethodName, "(Ljava/lang/Object;I)" + typeNameInternal, null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
      maxStack--;
      Label[] labels = new Label[fields.size()];
      Label labelForInvalidTypes = new Label();
      boolean hasAnyBadTypeLabel = false;
      for (int i = 0, n = labels.length; i < n; i++) {
        if (Type.getType(fields.get(i).getType()).equals(primitiveType)) labels[i] = new Label();
        else {
          labels[i] = labelForInvalidTypes;
          hasAnyBadTypeLabel = true;
        }
      }
      Label defaultLabel = new Label();
      mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

      for (int i = 0, n = labels.length; i < n; i++) {
        Field field = fields.get(i);
        if (!labels[i].equals(labelForInvalidTypes)) {
          mv.visitLabel(labels[i]);
          mv.visitFrame(F_SAME, 0, null, 0, null);
          if (!Modifier.isStatic(field.getModifiers())) {
            mv.visitVarInsn(ALOAD, 1);
            mv.visitTypeInsn(CHECKCAST, classNameInternal);
          }
          mv.visitFieldInsn(
              Modifier.isStatic(field.getModifiers()) ? GETSTATIC : GETFIELD,
              classNameInternal,
              field.getName(),
              typeNameInternal);
          mv.visitInsn(returnValueInstruction);
        }
      }
      // Rest of fields: different type
      if (hasAnyBadTypeLabel) {
        mv.visitLabel(labelForInvalidTypes);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        insertThrowExceptionForFieldType(mv, primitiveType.getClassName());
      }
      // Default: field not found
      mv.visitLabel(defaultLabel);
      mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    mv = insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
  }
Example #11
0
  private static void insertGetObject(
      ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
      maxStack--;
      Label[] labels = new Label[fields.size()];
      for (int i = 0, n = labels.length; i < n; i++) labels[i] = new Label();
      Label defaultLabel = new Label();
      mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

      for (int i = 0, n = labels.length; i < n; i++) {
        Field field = fields.get(i);

        mv.visitLabel(labels[i]);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        if (!Modifier.isStatic(field.getModifiers())) {
          mv.visitVarInsn(ALOAD, 1);
          mv.visitTypeInsn(CHECKCAST, classNameInternal);
        }
        mv.visitFieldInsn(
            Modifier.isStatic(field.getModifiers()) ? GETSTATIC : GETFIELD,
            classNameInternal,
            field.getName(),
            Type.getDescriptor(field.getType()));

        Type fieldType = Type.getType(field.getType());
        switch (fieldType.getSort()) {
          case Type.BOOLEAN:
            mv.visitMethodInsn(
                INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
            break;
          case Type.BYTE:
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
            break;
          case Type.CHAR:
            mv.visitMethodInsn(
                INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
            break;
          case Type.SHORT:
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
            break;
          case Type.INT:
            mv.visitMethodInsn(
                INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
            break;
          case Type.FLOAT:
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
            break;
          case Type.LONG:
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
            break;
          case Type.DOUBLE:
            mv.visitMethodInsn(
                INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
            break;
        }

        mv.visitInsn(ARETURN);
      }

      mv.visitLabel(defaultLabel);
      mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 3);
    mv.visitEnd();
  }
Example #12
0
  private static void insertSetObject(
      ClassWriter cw, String classNameInternal, ArrayList<Field> fields) {
    int maxStack = 6;
    MethodVisitor mv =
        cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ILOAD, 2);

    if (!fields.isEmpty()) {
      maxStack--;
      Label[] labels = new Label[fields.size()];
      for (int i = 0, n = labels.length; i < n; i++) labels[i] = new Label();
      Label defaultLabel = new Label();
      mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels);

      for (int i = 0, n = labels.length; i < n; i++) {
        Field field = fields.get(i);
        Type fieldType = Type.getType(field.getType());

        mv.visitLabel(labels[i]);
        mv.visitFrame(F_SAME, 0, null, 0, null);
        if (!Modifier.isStatic(field.getModifiers())) {
          mv.visitVarInsn(ALOAD, 1);
          mv.visitTypeInsn(CHECKCAST, classNameInternal);
        }
        mv.visitVarInsn(ALOAD, 3);

        switch (fieldType.getSort()) {
          case Type.BOOLEAN:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
            break;
          case Type.BYTE:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
            break;
          case Type.CHAR:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C");
            break;
          case Type.SHORT:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
            break;
          case Type.INT:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
            break;
          case Type.FLOAT:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
            break;
          case Type.LONG:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
            break;
          case Type.DOUBLE:
            mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
            break;
          case Type.ARRAY:
            mv.visitTypeInsn(CHECKCAST, fieldType.getDescriptor());
            break;
          case Type.OBJECT:
            mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName());
            break;
        }

        mv.visitFieldInsn(
            Modifier.isStatic(field.getModifiers()) ? PUTSTATIC : PUTFIELD,
            classNameInternal,
            field.getName(),
            fieldType.getDescriptor());
        mv.visitInsn(RETURN);
      }

      mv.visitLabel(defaultLabel);
      mv.visitFrame(F_SAME, 0, null, 0, null);
    }
    mv = insertThrowExceptionForFieldNotFound(mv);
    mv.visitMaxs(maxStack, 4);
    mv.visitEnd();
  }
  protected void injectConstructor(ClassWriter classWriter) {
    String resultName = getAccessorNameInternal(this.getTarget(), this.getAccessorType());

    MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    methodVisitor.visitCode();
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
    ;
    methodVisitor.visitTypeInsn(NEW, "java/util/ArrayList");
    methodVisitor.visitInsn(DUP);
    methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
    methodVisitor.visitVarInsn(ASTORE, 1);
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitMethodInsn(
        INVOKEVIRTUAL, resultName, "getTargetClass", "()Ljava/lang/Class;", false);
    methodVisitor.visitVarInsn(ASTORE, 2);
    Label whileLoop = new Label(); // enter the "while (currentClass != Object.class)" loop
    methodVisitor.visitLabel(whileLoop);
    methodVisitor.visitFrame(
        Opcodes.F_FULL,
        3,
        new Object[] {resultName, "java/util/List", "java/lang/Class"},
        0,
        new Object[] {});
    methodVisitor.visitVarInsn(ALOAD, 2);
    methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;"));
    Label classNotObjectComparer =
        new Label(); // compares the current class to Object.class aka currentClass != Object.class
    methodVisitor.visitJumpInsn(IF_ACMPEQ, classNotObjectComparer);
    methodVisitor.visitVarInsn(ALOAD, 2);
    methodVisitor.visitMethodInsn(
        INVOKEVIRTUAL,
        "java/lang/Class",
        "getDeclaredFields",
        "()[Ljava/lang/reflect/Field;",
        false);
    methodVisitor.visitVarInsn(ASTORE, 3);
    methodVisitor.visitVarInsn(ALOAD, 3);
    methodVisitor.visitInsn(ARRAYLENGTH);
    methodVisitor.visitVarInsn(ISTORE, 4);
    methodVisitor.visitInsn(ICONST_0);
    methodVisitor.visitVarInsn(ISTORE, 5);
    Label cachingForLoop = new Label(); // this loop handles the storing of the fields (to the list)
    methodVisitor.visitLabel(cachingForLoop);
    methodVisitor.visitFrame(
        Opcodes.F_APPEND,
        3,
        new Object[] {"[Ljava/lang/reflect/Field;", Opcodes.INTEGER, Opcodes.INTEGER},
        0,
        null);
    methodVisitor.visitVarInsn(ILOAD, 5);
    methodVisitor.visitVarInsn(ILOAD, 4);
    Label cachingForLoopIncrementLabel = new Label(); // handles the looping of the fields
    methodVisitor.visitJumpInsn(IF_ICMPGE, cachingForLoopIncrementLabel);
    methodVisitor.visitVarInsn(ALOAD, 3);
    methodVisitor.visitVarInsn(ILOAD, 5);
    methodVisitor.visitInsn(AALOAD);
    methodVisitor.visitVarInsn(ASTORE, 6);
    methodVisitor.visitVarInsn(ALOAD, 1);
    methodVisitor.visitVarInsn(ALOAD, 6);
    methodVisitor.visitMethodInsn(
        INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
    methodVisitor.visitInsn(POP);
    methodVisitor.visitIincInsn(5, 1);
    methodVisitor.visitJumpInsn(GOTO, cachingForLoop);
    methodVisitor.visitLabel(cachingForLoopIncrementLabel);
    methodVisitor.visitFrame(Opcodes.F_CHOP, 3, null, 0, null);
    methodVisitor.visitVarInsn(ALOAD, 2);
    methodVisitor.visitMethodInsn(
        INVOKEVIRTUAL, "java/lang/Class", "getSuperclass", "()Ljava/lang/Class;", false);
    methodVisitor.visitVarInsn(ASTORE, 2);
    methodVisitor.visitJumpInsn(GOTO, whileLoop);
    methodVisitor.visitLabel(classNotObjectComparer);
    methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitVarInsn(ALOAD, 1);
    methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true);
    methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/reflect/Field");
    methodVisitor.visitFieldInsn(PUTFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;");
    methodVisitor.visitInsn(ICONST_0);
    methodVisitor.visitVarInsn(ISTORE, 3);
    Label storingForLoop =
        new Label(); // this for loop goes about storing the fields in the array defined in the
                     // class
    methodVisitor.visitLabel(storingForLoop);
    methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null);
    methodVisitor.visitVarInsn(ILOAD, 3);
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;");
    methodVisitor.visitInsn(ARRAYLENGTH);
    Label storage =
        new Label(); // gets the field at position x and stores it in the cache (fieldTable)
    methodVisitor.visitJumpInsn(IF_ICMPGE, storage);
    methodVisitor.visitVarInsn(ALOAD, 0);
    methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;");
    methodVisitor.visitVarInsn(ILOAD, 3);
    methodVisitor.visitVarInsn(ALOAD, 1);
    methodVisitor.visitVarInsn(ILOAD, 3);
    methodVisitor.visitMethodInsn(
        INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true);
    methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/reflect/Field");
    methodVisitor.visitInsn(AASTORE);
    methodVisitor.visitIincInsn(3, 1);
    methodVisitor.visitJumpInsn(GOTO, storingForLoop);
    methodVisitor.visitLabel(storage);
    methodVisitor.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);
    methodVisitor.visitInsn(RETURN);
    methodVisitor.visitMaxs(4, 7);
    methodVisitor.visitEnd();
  }
  @Override
  public void visitFrame(
      final int type,
      final int nLocal,
      final Object[] local,
      final int nStack,
      final Object[] stack) {
    if (insnCount == lastFrame) {
      throw new IllegalStateException("At most one frame can be visited at a given code location.");
    }
    lastFrame = insnCount;
    int mLocal;
    int mStack;
    switch (type) {
      case Opcodes.F_NEW:
      case Opcodes.F_FULL:
        mLocal = Integer.MAX_VALUE;
        mStack = Integer.MAX_VALUE;
        break;

      case Opcodes.F_SAME:
        mLocal = 0;
        mStack = 0;
        break;

      case Opcodes.F_SAME1:
        mLocal = 0;
        mStack = 1;
        break;

      case Opcodes.F_APPEND:
      case Opcodes.F_CHOP:
        mLocal = 3;
        mStack = 0;
        break;

      default:
        throw new IllegalArgumentException("Invalid frame type " + type);
    }

    if (nLocal > mLocal) {
      throw new IllegalArgumentException("Invalid nLocal=" + nLocal + " for frame type " + type);
    }
    if (nStack > mStack) {
      throw new IllegalArgumentException("Invalid nStack=" + nStack + " for frame type " + type);
    }

    if (type != Opcodes.F_CHOP) {
      if (nLocal > 0 && (local == null || local.length < nLocal)) {
        throw new IllegalArgumentException("Array local[] is shorter than nLocal");
      }
      for (int i = 0; i < nLocal; ++i) {
        checkFrameValue(local[i]);
      }
    }
    if (nStack > 0 && (stack == null || stack.length < nStack)) {
      throw new IllegalArgumentException("Array stack[] is shorter than nStack");
    }
    for (int i = 0; i < nStack; ++i) {
      checkFrameValue(stack[i]);
    }
    if (type == Opcodes.F_NEW) {
      ++expandedFrames;
    } else {
      ++compressedFrames;
    }
    if (expandedFrames > 0 && compressedFrames > 0) {
      throw new RuntimeException("Expanded and compressed frames must not be mixed.");
    }
    super.visitFrame(type, nLocal, local, nStack, stack);
  }