Bug 82407 - [compiler][1.5] Java 5.0 Compiler generates bogus code
Summary: [compiler][1.5] Java 5.0 Compiler generates bogus code
Status: VERIFIED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 critical (vote)
Target Milestone: 3.1 M5   Edit
Assignee: Philipe Mulet CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-01-07 18:39 EST by Heiko Selber CLA
Modified: 2005-02-24 04:47 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Heiko Selber CLA 2005-01-07 18:39:02 EST
The Java 5.0 Compiler of Eclipse 3.1M4 generates bogus code.

An example java source file is included below.

If compiled by Eclipse 3.1M4 and started as Java application, it throws an error:
---
java.lang.VerifyError: (class: Bogon, method: substitutionList signature:
(Ljava/lang/String;Ljava/lang/String;)Ljava/util/HashMap;) Incompatible object
argument for function call
Exception in thread "main" 
---

If compiled with Sun's compiler (1.5.0_01), it simply prints "Bogon".

Apparently the compiler confuses the methods main() and substitutionList().

I think this bug is related to bugs 72528 and 79368.

Here is the smallest example I could make to reproduce the problem:

(I found that removing any more code fragment removes the bug,too.)

--- Begin File: Bogon.java ---
import java.util.HashMap;

public class Bogon {

	static HashMap<Character, Character> substitutionList(String s1, String s2) {

		HashMap<Character, Character> subst = new HashMap<Character, Character>();

		for (int i = 0; i < s1.length(); i++) {
			char key = s1.charAt(i);
			char value = s2.charAt(i);
			if (subst.containsKey(key)) {
				if (value != subst.get(key)) {
					return null;
				}
			} else if (subst.containsValue(value)) {
				return null;
			} else {
				subst.put(key, value);
			}
		}

		return subst;
	}

	public static void main(String[] args) {
		System.out.println("Bogon");
	}
}
--- End File: Bogon.java ---
Comment 1 Philipe Mulet CLA 2005-01-11 08:05:28 EST
Offending method code is:
  // Method descriptor  #15
(Ljava/lang/String;Ljava/lang/String;)Ljava/util/HashMap;
  // Signature:
(Ljava/lang/String;Ljava/lang/String;)Ljava/util/HashMap<Ljava/lang/Character;Ljava/lang/Character;>;
  // Stack: 3, Locals: 6
  static HashMap substitutionList(String s1, String s2);
      0  new #19 java/util/HashMap
      3  dup
      4  invokespecial #20 <Method java/util/HashMap.<init>()V>
      7  astore_2
      8  iconst_0
      9  istore_3
     10  goto 96
     13  aload_0
     14  iload_3
     15  invokevirtual #26 <Method java/lang/String.charAt(I)C>
     18  istore 4
     20  aload_1
     21  iload_3
     22  invokevirtual #26 <Method java/lang/String.charAt(I)C>
     25  istore 5
     27  aload_2
     28  iload 4
     30  invokestatic #32 <Method
java/lang/Character.valueOf(C)Ljava/lang/Character;>
     33  invokevirtual #36 <Method
java/util/HashMap.containsKey(Ljava/lang/Object;)Z>
     36  ifeq 64
     39  iload 5
     41  aload_2
     42  iload 4
     44  invokestatic #32 <Method
java/lang/Character.valueOf(C)Ljava/lang/Character;>
     47  invokevirtual #40 <Method
java/util/HashMap.get(Ljava/lang/Object;)Ljava/lang/Object;>
     50  checkcast #42 java/lang/Integer
     53  invokevirtual #46 <Method java/lang/Character.charValue()C>
     56  if_icmpeq 93
     59  aconst_null
     60  areturn
     61  goto 93
     64  aload_2
     65  iload 5
     67  invokestatic #32 <Method
java/lang/Character.valueOf(C)Ljava/lang/Character;>
     70  invokevirtual #49 <Method
java/util/HashMap.containsValue(Ljava/lang/Object;)Z>
     73  ifeq 78
     76  aconst_null
     77  areturn
     78  aload_2
     79  iload 4
     81  invokestatic #32 <Method
java/lang/Character.valueOf(C)Ljava/lang/Character;>
     84  iload 5
     86  invokestatic #32 <Method
java/lang/Character.valueOf(C)Ljava/lang/Character;>
     89  invokevirtual #53 <Method
java/util/HashMap.put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;>
     92  pop
     93  iinc 3 1
     96  iload_3
     97  aload_0
     98  invokevirtual #57 <Method java/lang/String.length()I>
    101  if_icmplt 13
    104  aload_2
    105  areturn

Problem is at line:
     50  checkcast #42 java/lang/Integer

which should rather checkcast Character.

Suspecting interference of autoboxing with generic cast.
Comment 2 Philipe Mulet CLA 2005-01-12 07:00:41 EST
Problem comes from the fact we use the operator signature to drive the
conversion mechanism. Signature is: char2int == char2int --> int.
If we changed it to: char2char == char2char --> int, it have the right behavior.
But the consequences could be quite severe.
Comment 3 Philipe Mulet CLA 2005-01-12 07:02:21 EST
Alternatively, we may instead want to use the compile type instead of runtime
one to perform the autoboxing conversion.
Comment 4 Philipe Mulet CLA 2005-02-18 07:16:44 EST
Got resolved along with changes which occurred during M5.
Added GenericTypeTest#test511.

Fix got implemented along the latter suggestion.
Comment 5 Heiko Selber CLA 2005-02-24 04:18:09 EST
I just checked with 3.1M5:

The fix works well, thank you!

(I was afraid that the fix wouldn't make it into M5. I was proven worng :)
Comment 6 Philipe Mulet CLA 2005-02-24 04:47:38 EST
You're welcome, and thx for double checking.