Bug 44213 - Compiler generates unreachable bytecode instructions
Summary: Compiler generates unreachable bytecode instructions
Status: RESOLVED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 RC4   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2003-10-06 05:20 EDT by eichberg CLA
Modified: 2007-06-21 10:52 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description eichberg CLA 2003-10-06 05:20:19 EDT
Hello,

[Short summary:
For a given method bytecode instruction(s) are generated which will never be 
executed, neither in a normal nor in an exceptionel control flow. 
]

For the following method:
_________________________

public void ifTryCatchFinallyMethod(){
 for (int i = 0 ; i < 100 ; i++){
  try {		   
   if (i == 50){
    i++;				
    continue;		
   }  
   else {   
    try{	
     foo(); // System.out.println("Within try..."); // 1
     continue;
    } catch (Exception e){
     foo(); // System.out.println("Within catch..."); // 2
    } finally {
     foo(); // System.out.println("within inner finally: (round: "+i+")"); // 3
    }
   }
  } finally {
   foo(); // System.out.println("within outer finally: (round: "+i+")"); // 4
  }
 }
}

the compiler generates the following bytecode instructions:
___________________________________________________________

	LINE 75:
	[START OF VARIABLE 0 (localvariableindex = 0)]: 
de.tud.bat.testclasses.ControlFlowsTestClass this
	0: iconst_0 /* stack change = 1 */ 
	1: istore_1 /* stack change = -1 */ 
	[START OF VARIABLE 1 (localvariableindex = 1)]: int i
	2: goto /* stack change = 0 */ 
		#90
	LINE 78:
	TRY[2]{
	5: iload_1 /* stack change = 1 */ 
	6: bipush = 50 /* stack change = 1 */ 
	8: if_icmpne /* stack change = -2 */ 
		#20
	LINE 79:
	11: iinc_1 /* stack change = 0 */ 
	LINE 80:
	14: jsr /* stack change = 1 */ 
		#79
	17: goto /* stack change = 0 */ 
		#87
	LINE 84:
	TRY[0]{
	TRY[1]{
	20: aload_0 /* stack change = 1 */ 
	21: invokespecial <de.tud.bat.testclasses.ControlFlowsTestClass>.foo 
() : void /* stack change = -1 */ 
	LINE 85:
	24: jsr /* stack change = 1 */ 
		#55
	27: jsr /* stack change = 1 */ 
		#79
	30: goto /* stack change = 0 */ 
		#87
	LINE 86:
	}[0]
	CATCH [0](java.lang.Exception)
	33: astore_2 /* stack change = -1 */ 
	LINE 87:
	[START OF VARIABLE 2 (localvariableindex = 2)]: java.lang.Exception e
	34: aload_0 /* stack change = 1 */ 
	35: invokespecial <de.tud.bat.testclasses.ControlFlowsTestClass>.foo 
() : void /* stack change = -1 */ 
	[END OF VARIABLE 2]
	}[1]
	38: goto /* stack change = 0 */ 
		#49
	LINE 88:
	CATCH [1] (any exception)
	41: astore_4 /* stack change = -1 */ 
	43: jsr /* stack change = 1 */ 
		#55
	46: aload_4 /* stack change = 1 */ 
	48: athrow /* stack change = 0 */ 
	49: jsr /* stack change = 1 */ 
		#55
	52: goto /* stack change = 0 */ 
		#73
	55: astore_3 /* stack change = -1 */ 
	LINE 89:
	56: aload_0 /* stack change = 1 */ 
	57: invokespecial <de.tud.bat.testclasses.ControlFlowsTestClass>.foo 
() : void /* stack change = -1 */ 
	LINE 83:
	60: ret_3 /* stack change = 0 */ 
	62: goto /* stack change = 0 */ 
		#73
	LINE 92:
	}[2]
	CATCH [2] (any exception)
	65: astore_6 /* stack change = -1 */ 
	67: jsr /* stack change = 1 */ 
		#79
	70: aload_6 /* stack change = 1 */ 
	72: athrow /* stack change = 0 */ 
	73: jsr /* stack change = 1 */ 
		#79
	76: goto /* stack change = 0 */ 
		#87
	79: astore_5 /* stack change = -1 */ 
	LINE 93:
	81: aload_0 /* stack change = 1 */ 
	82: invokespecial <de.tud.bat.testclasses.ControlFlowsTestClass>.foo 
() : void /* stack change = -1 */ 
	LINE 77:
	85: ret_5 /* stack change = 0 */ 
	LINE 75:
	87: iinc_1 /* stack change = 0 */ 
	90: iload_1 /* stack change = 1 */ 
	91: bipush = 100 /* stack change = 1 */ 
	93: if_icmplt /* stack change = -2 */ 
		#5
	LINE 97:
	[END OF VARIABLE 1]
	96: return /* stack change = 0 */ 

The "goto 73" instruction with "offset 62" will never be reached. The 
instruction with offset 62 is no jump target and is not a handler instruction.

Even though this is not a violation of the JVM Spec. this behaviour is 
nevertheless suspicious.
Comment 1 Olivier Thomann CLA 2003-10-06 14:07:01 EDT
Using latest code, I get:
  public void ifTryCatchFinallyMethod();
    /* Stack: 2, Locals: 7 */
    Code attribute:
       0  iconst_0
       1  istore_1
       2  goto 84
       5  iload_1
       6  bipush 50
       8  if_icmpne 20
      11  iinc 1 1
      14  jsr 70
      17  goto 81
      20  aload_0
      21  invokespecial #17 <Method A#foo() void>
      24  jsr 49
      27  jsr 70
      30  goto 81
      33  astore_2
      34  aload_0
      35  invokespecial #17 <Method A#foo() void>
      38  goto 56
      41  astore 4
      43  jsr 49
      46  aload 4
      48  athrow
      49  astore_3
      50  aload_0
      51  invokespecial #17 <Method A#foo() void>
      54  ret 3
      56  jsr 49
      59  goto 78
      62  astore 6
      64  jsr 70
      67  aload 6
      69  athrow
      70  astore 5
      72  aload_0
      73  invokespecial #17 <Method A#foo() void>
      76  ret 5
      78  jsr 70
      81  iinc 1 1
      84  iload_1
      85  bipush 100
      87  if_icmplt 5
      90  return

    Exception Table:
      [pc: 20, pc: 33] -> 33 when : java.lang.Exception
      [pc: 20, pc: 27] -> 41 when : any
      [pc: 33, pc: 38] -> 41 when : any
      [pc: 56, pc: 59] -> 41 when : any
      [pc: 5, pc: 17] -> 62 when : any
      [pc: 20, pc: 30] -> 62 when : any
      [pc: 33, pc: 62] -> 62 when : any
      [pc: 78, pc: 81] -> 62 when : any

I don't see what bytecodes are unreachable. Could you please comment on this output?
Comment 2 eichberg CLA 2003-10-07 04:25:23 EDT
Hello,


> public void ifTryCatchFinallyMethod();
[...]
> I don't see what bytecodes are unreachable. Could you please comment 
> on this output?

I'm sorry - I thought I was using the most current version of Eclipse but I 
wasn't. The most current version does not longer produce unreachable 
instructions for the IfTryCatchFinallyMethod. 

However, the Versions Eclipse 3.0M3 and the Nightly Build with Build id: 
200310070010 (Okt. 7.) still produce unreachable instructions.

For the following class:

public class Test {
        Object anchorInstruction = new Object();
        public String toString(){
                StringBuffer stringBuffer = new StringBuffer();
                Object instr = anchorInstruction;
                while (true){
                        stringBuffer.append(instr);

                        if (instr != null) {
                                if (!(instr instanceof Exception))
                                        stringBuffer.append("\n");
                        } else
                                break;
                }

                return stringBuffer.toString();
        }
}

The following Bytecode Instructions are generated:

public java.lang.String toString();
  Code:
   Stack=2, Locals=3, Args_size=1
   0:   new     #21; //class StringBuffer
   3:   dup
   4:   invokespecial   #22; //Method java/lang/StringBuffer."<init>":()V
   7:   astore_1
   8:   aload_0
   9:   getfield        #13; //Field anchorInstruction:Ljava/lang/Object;
   12:  astore_2
   13:  aload_1
   14:  aload_2
   15:  invokevirtual   #26; //Method java/lang/StringBuffer.append:
(Ljava/lang/Object;)Ljava/lang/StringBuffer;
   18:  pop
   19:  aload_2
   20:  ifnull  46
   23:  aload_2
   24:  instanceof      #28; //class Exception
   27:  ifne    43
   30:  aload_1
   31:  ldc     #30; //String \n
   33:  invokevirtual   #33; //Method java/lang/StringBuffer.append:
(Ljava/lang/String;)Ljava/lang/StringBuffer;
   36:  pop
   37:  goto    43
   40:  goto    46
   43:  goto    13
   46:  aload_1
   47:  invokevirtual   #35; //Method java/lang/StringBuffer.toString:()
Ljava/lang/String;
   50:  areturn

The "goto 46" instruction with offset 40 is unreachable.

Best regards,
Michael 
Comment 3 Philipe Mulet CLA 2003-10-07 05:07:02 EDT
This is a known issue as a result of our branch chaining (inline branch to a 
branch). 

Other example (with jsr generation disabled):
public class X {	
	public static void main(String[] argv){	
	    int var;	
		a: do {	
			try {	
				if (argv != null) break a;	
			} finally { 
				var = 12;	
				System.out.print("SUB-");	
			}	
		} while (argv.length == 0);	
		System.out.println(var);	
	}	
}	

       0  aload_0
       1  ifnull 35
       4  bipush 12
       6  istore_1
       7  getstatic #21 <Field java.lang.System#out java.io.PrintStream>
      10  ldc #23 <String "SUB-">
      12  invokevirtual #29 <Method java.io.PrintStream#print(java.lang.String 
arg) void>
      15  goto 51
      18  goto 35
      21  astore_2
      22  bipush 12
      24  istore_1
      25  getstatic #21 <Field java.lang.System#out java.io.PrintStream>
      28  ldc #23 <String "SUB-">
      30  invokevirtual #29 <Method java.io.PrintStream#print(java.lang.String 
arg) void>
      33  aload_2
      34  athrow
      35  bipush 12
      37  istore_1
      38  getstatic #21 <Field java.lang.System#out java.io.PrintStream>
      41  ldc #23 <String "SUB-">
      43  invokevirtual #29 <Method java.io.PrintStream#print(java.lang.String 
arg) void>
      46  aload_0
      47  arraylength
      48  ifeq 0
      51  getstatic #21 <Field java.lang.System#out java.io.PrintStream>
      54  iload_1
      55  invokevirtual #33 <Method java.io.PrintStream#println(int arg) void>
      58  return



Our branch chaining instruction should be smart enough to realize that the goto 
instruction in 18 isn't reachable and should be optimized out (no fall through 
since previous instruction is a goto elsewhere). Need to be careful about 
possible subsequent backward branches to this location (but we can figure if a 
label got placed at same location or not).

Note that these dead bytecode are non lethal, but should still be removed.
Comment 4 Philipe Mulet CLA 2003-10-07 05:18:17 EDT
should investigate within 3.0 time frame
Comment 5 Philipe Mulet CLA 2004-03-25 05:58:17 EST
Not for 3.0
Comment 6 Philipe Mulet CLA 2004-05-19 10:32:58 EDT
Removing milestone of deferred item.
Comment 7 Philipe Mulet CLA 2007-04-02 07:37:56 EDT
reopening
Comment 8 Philipe Mulet CLA 2007-04-02 07:38:25 EDT
Olivier - is this still an issue ? Especially in the light of stackmap tables.
Comment 9 Olivier Thomann CLA 2007-06-21 10:52:43 EDT
Closing as WORKSFORME since there is no more deadbytecodes with 3.3RC4