Sybuser
Sybuser

Reputation: 1382

What piece of code in Java will generate the JVM instructions DUP2, DUP2_X1, SWAP?

I'm building a class that gathers some of the possible JVM opcodes. I found out how to generate DUP2_X2 and DUP_X2 but not DUP2, DUP2_X1, SWAP.

Below the code sample in which I starting gathering some of the jvm opcodes :

public class JvmOpCodes {

    long dup2x2(long[] array, int i, long l) {
        return array[i] = l;
    }

    int dupx2(int[] array, int i, int l) {
        return array[i] = l;
    }
    
    long lneg(long a) {
        return -a;
    }

    long lor(long a, long b) {
        return a | b;
    }

    long land(long a, long b) {
        return a & b;
    }

    long lushr(long a, long b) {
        return a >>> b;
    }

    int iushr(int a, int b) {
        return a >>> b;
    }

    long lshl(long a, long b) {
        return a << b;
    }

    float fsub(float a, float b) {
        return a - b;
    }

    float fadd(float a, float b) {
        return a + b;
    }

    float frem(float a, float b) {
        return a % b;
    }

    float fneg(float a) {
        return -a;
    }

    double drem(double a, double b) {
        return a % b;
    }
    
    double dneg(double a) {
        return -a;
    }
    
    void pop() {
        Math.round(0.5f);
    }
    
    void pop2() {
        Math.round(0.5d);
    }
}

After compiling with javac command and running javap -p -c, I'm able to identify the produced JVM opcodes inside the output :

Compiled from "JvmOpCodes.java"
public class org.apache.bcel.verifier.tests.JvmOpCodes {
  public org.apache.bcel.verifier.tests.JvmOpCodes();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  long dup2x2(long[], int, long);
    Code:
       0: aload_1
       1: iload_2
       2: lload_3
       3: dup2_x2
       4: lastore
       5: lreturn

  int dupx2(int[], int, int);
    Code:
       0: aload_1
       1: iload_2
       2: iload_3
       3: dup_x2
       4: iastore
       5: ireturn

  long lneg(long);
    Code:
       0: lload_1
       1: lneg
       2: lreturn

  long lor(long, long);
    Code:
       0: lload_1
       1: lload_3
       2: lor
       3: lreturn

  long land(long, long);
    Code:
       0: lload_1
       1: lload_3
       2: land
       3: lreturn

  long lushr(long, long);
    Code:
       0: lload_1
       1: lload_3
       2: l2i
       3: lushr
       4: lreturn

  int iushr(int, int);
    Code:
       0: iload_1
       1: iload_2
       2: iushr
       3: ireturn

  long lshl(long, long);
    Code:
       0: lload_1
       1: lload_3
       2: l2i
       3: lshl
       4: lreturn

  float fsub(float, float);
    Code:
       0: fload_1
       1: fload_2
       2: fsub
       3: freturn

  float fadd(float, float);
    Code:
       0: fload_1
       1: fload_2
       2: fadd
       3: freturn

  float frem(float, float);
    Code:
       0: fload_1
       1: fload_2
       2: frem
       3: freturn

  float fneg(float);
    Code:
       0: fload_1
       1: fneg
       2: freturn

  double drem(double, double);
    Code:
       0: dload_1
       1: dload_3
       2: drem
       3: dreturn

  double dneg(double);
    Code:
       0: dload_1
       1: dneg
       2: dreturn

  void pop();
    Code:
       0: ldc           #7                  // float 0.5f
       2: invokestatic  #8                  // Method java/lang/Math.round:(F)I
       5: pop
       6: return

  void pop2();
    Code:
       0: ldc2_w        #14                 // double 0.5d
       3: invokestatic  #16                 // Method java/lang/Math.round:(D)J
       6: pop2
       7: return
}

However, what piece of code in Java will generate the JVM instructions DUP2, DUP2_X1, SWAP ?

Also, an interesting related answer with demo here : https://stackoverflow.com/a/72131218/8315843

Upvotes: 0

Views: 295

Answers (2)

Sybuser
Sybuser

Reputation: 1382

  1. An example for DUP2_X1
    long l1;
    long l2;
    
    void test(String[] s) {
        s[0] += "s"; // Form 1 
        l2 = l1 = 1; // Form 2 
    }

and javap output when compiled in JDK8 :

  void test(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       7: aload_1
       8: iconst_0
       9: dup2_x1
      10: aaload
      11: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #5                  // String s
      16: invokevirtual #4                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #6                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: aastore
      23: aload_0
      24: aload_0
      25: lconst_1
      26: dup2_x1
      27: putfield      #7                  // Field l1:J
      30: putfield      #8                  // Field l2:J
      33: return
}

When compiled with JDK9+, the pattern of makeConcatWithConstants is activated so no DUP2_X1 for Form 1 :

  void test(java.lang.String[]);
    Code:
       0: aload_1
       1: iconst_0
       2: dup2
       3: aaload
       4: invokedynamic #3,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
       9: aastore
      10: aload_0
      11: aload_0
      12: lconst_1
      13: dup2_x1
      14: putfield      #4                  // Field l1:J
      17: putfield      #5                  // Field l2:J
      20: return
  1. An example for SWAP with ecj :
import java.lang.reflect.*;

public class TestSWAP {
    public static Constructor getTestConstructor(Class theClass) throws NoSuchMethodException {
        Class[] args = { String.class };
        try {
            return theClass.getConstructor(args);
        } catch (NoSuchMethodException e) {}
        return theClass.getConstructor(new Class[0]);
    }
}

Compiling with ecj with source/target 1.4 :

java -jar ecj-3.32.0.jar -g -source 1.4 -target 1.4 TestSWAP.java

Checking output of javap with command javap -p -c TestSWAP :

Compiled from "TestSWAP.java"
public class TestSWAP {
  static java.lang.Class class$0;

  public TestSWAP();
    Code:
       0: aload_0
       1: invokespecial #11                 // Method java/lang/Object."<init>":()V
       4: return

  public static java.lang.reflect.Constructor getTestConstructor(java.lang.Class) throws java.lang.NoSuchMethodException;
    Code:
       0: iconst_1
       1: anewarray     #22                 // class java/lang/Class
       4: dup
       5: iconst_0
       6: getstatic     #24                 // Field class$0:Ljava/lang/Class;
       9: dup
      10: ifnonnull     38
      13: pop
      14: ldc           #26                 // String java.lang.String
      16: invokestatic  #28                 // Method java/lang/Class.forName:(Ljava/lang/String;)Ljava/lang/Class;
      19: dup
      20: putstatic     #24                 // Field class$0:Ljava/lang/Class;
      23: goto          38
      26: new           #32                 // class java/lang/NoClassDefFoundError
      29: dup_x1
      30: swap
      31: invokevirtual #34                 // Method java/lang/Throwable.getMessage:()Ljava/lang/String;
      34: invokespecial #40                 // Method java/lang/NoClassDefFoundError."<init>":(Ljava/lang/String;)V
      37: athrow
      38: aastore
      39: astore_1
      40: aload_0
      41: aload_1
      42: invokevirtual #43                 // Method java/lang/Class.getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
      45: areturn
      46: pop
      47: aload_0
      48: iconst_0
      49: anewarray     #22                 // class java/lang/Class
      52: invokevirtual #43                 // Method java/lang/Class.getConstructor:([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
      55: areturn
    Exception table:
       from    to  target type
          14    19    26   Class java/lang/ClassNotFoundException
          40    45    46   Class java/lang/NoSuchMethodException
}

Upvotes: 0

boneill
boneill

Reputation: 1526

dup2:

  public static long example(long a) {
      return a = a + 1;
  }

I doubt that javac ever emits SWAP considering that there's missing variants like SWAP1_2, SWAP2_1, and SWAP2_2. As for DUP2_X1, I'm stumped.

Upvotes: 1

Related Questions