Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8058527

Compiler Bug - Incorrect results (for example by using nested xor-equal ops.)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 8u20
    • tools
    • x86
    • windows_8

      FULL PRODUCT VERSION :
      ----------------------------------------
      Versions:
      ------------------------------

      javac.exe version:
      javac 1.8.0_20

      --------------------

      java.exe version:
      java version "1.8.0_20"
      Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
      Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

      --------------------

      javap.exe version:
      1.8.0_20

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.3.9600]
      Any other OSs

      A DESCRIPTION OF THE PROBLEM :
      ----------------------------------------
      Overview and description:
      ------------------------------

      As this code

      int a = 10, b = 20;
      a ^= (b ^= (a ^= b));

      should swap the values of "a" and "b", actually makes the compiler spit out wrong bytecode,
      hence you get different results in the end.

      Results:
      a = 0
      b = 10


      Where this method

      int a = 10, b = 20;
      a ^= b;
      b ^= a;
      a ^= b;

      returns the correct values.

      Results:
      a = 20
      b = 10

      ADDITIONAL REGRESSION INFORMATION:
      ----------------------------------------
      Versions:
      ------------------------------

      javac.exe version:
      javac 1.8.0_20

      --------------------

      java.exe version:
      java version "1.8.0_20"
      Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
      Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)

      --------------------

      javap.exe version:
      1.8.0_20

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the given code. To decompile the bytecode and watch its assembly, just use javap -c <filename>

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Swapping values of the variables "a" and "b" for example
      a = 20
      b = 10
      ACTUAL -
      a = 0
      b = 10

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class BugSwap
      {
      public static void main(String args[])
      {
      int a = 10, b = 20;

      // Swaps values (Not correctly working)
      a ^= (b ^= (a ^= b));
      System.out.println("a = "+a+"; b = "+b);
      }
      }

      /*
      ----------------------------------------
      Decompiled bytecode from the incorrect working method (partial):
      ------------------------------

      ; BugSwap.class (partial view of the main() method)

      ; int a = 10, b = 20;
      bipush 10 ; Push 10 into stack (Int)
      istore_1 ; Store into 1st variable (Int)
      bipush 20 ; Push 20 into stack (Int)
      istore_2 ; Store into 2nd variable (Int)

      ; a ^= (b ^= (a ^= b));
      iload_1 ; Load from 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      iload_1 ; Load from 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      dup ; Duplicate top operand into stack
      istore_1 ; Store into 1st variable (Int)
      ixor ; XOR (Int)
      dup ; Duplicate top operand into stack
      istore_2 ; Store into 2nd variable (Int)
      ixor ; XOR (Int)
      istore_1 ; Store into 1st variable (Int)

      ; Results:
      ; a = 0
      ; b = 10
      ;
      ; Incorrect!


      ----------------------------------------
      Decompiled bytecode from the correct working method (partial):
      ------------------------------

      ; AlternativeSwap.class (partial view of the main() method)

      ; int a = 10, b = 20;
      bipush 10 ; Push 10 into stack (Int)
      istore_1 ; Store into 1st variable (Int)
      bipush 20 ; Push 20 into stack (Int)
      istore_2 ; Store into 2nd variable (Int)

      ; a ^= b;
      iload_1 ; Load from 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      istore_1 ; Store into 1st variable (Int)

      ; b ^= a;
      iload_2 ; Load from 2nd variable (Int)
      iload_1 ; Load from 1st variable (Int)
      ixor ; XOR (Int)
      istore_2 ; Store into 2nd variable (Int)

      ; a ^= b;
      iload_1 ; Load from 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      istore_1 ; Store into 1st variable (Int)

      ; Results:
      ; a = 20
      ; b = 10
      ;
      ; Correct!


      ----------------------------------------
      Decompiled bytecode and edited from the former incorrect working method (partial):
      ------------------------------

      ; EditedBugSwap.class (partial view of the main() method, which is edited)

      ; int a = 10, b = 20;
      bipush 10 ; Push 10 into stack (Int)
      istore_1 ; Store into 1st variable (Int)
      bipush 20 ; Push 20 into stack (Int)
      istore_2 ; Store into 2nd variable (Int)

      ; a ^= (b ^= (a ^= b));
      iload_1 ; Load from 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      dup ; Duplicate top operand into stack
      istore_1 ; Store into 1st variable (Int)
      iload_2 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      dup ; Duplicate top operand into stack
      istore_2 ; Store into 2nd variable (Int)
      iload_1 ; Load from 2nd variable (Int)
      ixor ; XOR (Int)
      istore_1 ; Store into 1st variable (Int)

      ; Results:
      ; a = 20
      ; b = 10
      ;
      ; Correct!
      */
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      a ^= b;
      b ^= a;
      a ^= b;

      /*
      ----------------------------------------
      Conclusion:
      ------------------------------

      Loading the old values in the first place may work correctly,
      if the stack values are synced with the variables,
      otherwise you may end up using the incorrect values within the stack,
      because the variables are being manipulated in runtime,
      hence the alternative assembly code (3rd one provided as comment in source code) works as intended.



      Best regards

      Ethem Kurt
      */

            pardesha Pardeep Sharma
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: