Bug 141810 - [1.5][compiler] Enum switch tables incorrectly generated by the compiler
Summary: [1.5][compiler] Enum switch tables incorrectly generated by the compiler
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.2.1   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-05-15 13:11 EDT by Piotr Kobzda CLA
Modified: 2006-09-12 06:08 EDT (History)
2 users (show)

See Also:


Attachments
Regression test (2.14 KB, patch)
2006-05-15 21:45 EDT, Olivier Thomann CLA
no flags Details | Diff
Proposed fix (2.94 KB, patch)
2006-05-15 23:11 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Piotr Kobzda CLA 2006-05-15 13:11:34 EDT
There is a bug in binary compatibility of enum 'switch tables' generated by the Eclipse compiler.
This bug probably applies to all Eclipse compiler versions supporting Java enums.


The following sample code is used to demonstrate the problem:

enum Action { ONE, TWO };

class Test {
   public static void main(String[] args) {
      for(Action a : Action.values()) {
         switch(a) {
         case ONE:
            System.out.println("one");
            break;
         case TWO:
            System.out.println("two");
            break;
         default:
            System.out.println("unknown action "+ a);
         }
      }
   }
}

The output of running above Test class is:

one
two


When an Action enum will evolve, for example to the following one:

enum Action { ONE, TWO, THREE };

The result of running Test class (without recompiling) will be:

one
two
one

Instead of expected:

one
two
unknown action THREE


Decompiled version of a Test class explains it in details:

// Decompiled by DJ v3.8.8.85 Copyright 2005 Atanas Neshkov  Date: 2006-05-15 18:39:57
// Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
// Decompiler options: packimports(3) deadcode nonlb space 
// Source File Name:   Test.java

import java.io.PrintStream;

// Referenced classes of package :
//         Action

public class Test {

   public Test() {
   }

   public static void main(String args[]) {
      Action aaction[] = Action.values();
      int i = 0;
      for (int j = aaction.length; i < j; i++) {
         Action a = aaction[i];
         switch ($SWITCH_TABLE$Action()[a.ordinal()]) {
         case 0: // '\0'
            System.out.println("one");
            break;

         case 1: // '\001'
            System.out.println("two");
            break;

         default:
            System.out.println((new StringBuilder("unknown action ")).append(a).toString());
            break;
         }
      }

   }

   static int[] $SWITCH_TABLE$Action() {
      $SWITCH_TABLE$Action;
      if ($SWITCH_TABLE$Action == null) goto _L2; else goto _L1
_L1:
      return;
_L2:
      JVM INSTR pop ;
      int ai[] = new int[Action.values().length];
      try {
         ai[Action.ONE.ordinal()] = 0;
      }
      catch (NoSuchFieldError _ex) { }
      try {
         ai[Action.TWO.ordinal()] = 1;
      }
      catch (NoSuchFieldError _ex) { }
      return $SWITCH_TABLE$Action = ai;
   }

   private static int $SWITCH_TABLE$Action[];
}


One of the simplest ways to fix that is to add Arrays.fill(ai, -1), after 'ai' table creation in the above code.

The same will be achieved without adding additional processing using 1 (instead of 0) as a starting ordinal index for known enum constants references in the above like code generation (this is the way chosen by the Sun Java compiler).


Regards,
piotr
Comment 1 Olivier Thomann CLA 2006-05-15 13:59:21 EDT
I'll look at it.
Comment 2 Olivier Thomann CLA 2006-05-15 14:14:05 EDT
We either fill the array with -1 or we never use the value 0 as a return value through the X.$SWITCH_TABLE$Action() call.
Philippe,
This is quite easy to fix. I'll prepare a fix for tomorrow. This will give me the time to run all the tests.
Piotr, nice catch and thanks for the nice test case.
Comment 3 Olivier Thomann CLA 2006-05-15 14:36:59 EDT
I have a fix. I'll do more testing before I post it.
Comment 4 Olivier Thomann CLA 2006-05-15 21:45:13 EDT
Created attachment 41544 [details]
Regression test
Comment 5 Olivier Thomann CLA 2006-05-15 23:11:54 EDT
Created attachment 41547 [details]
Proposed fix

This patch doesn't use 0 as a possible value in the SWITCH_TABLE array.
Comment 6 Olivier Thomann CLA 2006-05-15 23:12:21 EDT
All existing tests passed.
Comment 7 Philipe Mulet CLA 2006-05-16 06:56:23 EDT
Fix looks good.
+1 for 3.2.1
Comment 8 Olivier Thomann CLA 2006-05-16 10:38:32 EDT
Fixed and released in branch 3.2.1.
Regression test added in org.eclipse.jdt.core.tests.compiler.regression.EnumTest.test130
Comment 9 Frederic Fusier CLA 2006-06-12 05:16:04 EDT
Released for 3.2.1
Released for 3.3 M1 while merging TARGET_321 in HEAD
Comment 10 Frederic Fusier CLA 2006-08-08 03:56:42 EDT
Verified for 3.3 M1 using build I20060807-2000.
Comment 11 David Audel CLA 2006-09-12 06:08:49 EDT
Verified for 3.2.1 using build M20060908-1655