Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 359495 - [1.7][compiler] VerifyError in try-finally block with lock encompassing for-each block and unlock in finally clause
Summary: [1.7][compiler] VerifyError in try-finally block with lock encompassing for-e...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.8   Edit
Hardware: PC Linux
: P3 major (vote)
Target Milestone: 3.7.2   Edit
Assignee: Ayushman Jain CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 368996 (view as bug list)
Depends on:
Blocks:
 
Reported: 2011-09-29 18:06 EDT by Anthony CLA
Modified: 2012-05-29 11:29 EDT (History)
5 users (show)

See Also:
Olivier_Thomann: review+


Attachments
proposed fix v1.0 + regression tests (14.43 KB, patch)
2011-10-03 07:52 EDT, Ayushman Jain CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony CLA 2011-09-29 18:06:49 EDT
Build Identifier: M20110909-1335

Executing the following test case will result in a VerifyError "Inconsistent
stackmap frames at branch target".

Environment:
- Eclipse 3.7.1 (M20110909-1335)
- Linux (x86_64/GTK 2)
- JDK7

Stacktrace:
---
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 48 in method E7Bug.main([Ljava/lang/String;)V at offset 34
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
	at java.lang.Class.getMethod0(Class.java:2685)
	at java.lang.Class.getMethod(Class.java:1620)
	at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:484)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:476)
---

---
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class E7Bug
{
   public static void main(final String[] args)
   {
      final Lock lock = new ReentrantLock();
      final List<String> strings = Arrays.asList(args);
      lock.lock();
      try
      {
         for (final String string : strings)
         {
            return;
         }

         return;
      }
      finally
      {
         lock.unlock();
      }
   }
}
---


Reproducible: Always

Steps to Reproduce:
1. Run testcase in Eclipse with JavaSE-1.7 target
Comment 1 Olivier Thomann CLA 2011-09-29 19:52:46 EDT
Reproduced when -preserveAllLocals option is used. If unused locals are optimized out, the code runs fine.
Comment 2 Olivier Thomann CLA 2011-09-29 20:31:40 EDT
In this case, both return statements are "shared". We compare state index of both return statements and they are identical. Now I need to investigate why they are identical when one should define one more local than the other one.
Comment 3 Anthony CLA 2011-09-29 20:49:02 EDT
(In reply to comment #1)
> Reproduced when -preserveAllLocals option is used. If unused locals are
> optimized out, the code runs fine.

If the loop
         for (final String string : strings)
         {
            return;
         }
is replaced with
         for (final String string : strings)
         {
            if(string == null)
               return;
         }
the code causes the error regardless of whether the -preserveAllLocals option is used.  But removing either of the return statements from the try block or the lock.unlock() statement from the finally block will allow the code to run fine.
Comment 4 Olivier Thomann CLA 2011-09-29 20:54:40 EDT
(In reply to comment #3)
> the code causes the error regardless of whether the -preserveAllLocals option
> is used.  But removing either of the return statements from the try block or
> the lock.unlock() statement from the finally block will allow the code to run
> fine.
The problem comes from the sharing of the return statement and we do so because we believe they both have the same state index which is wrong.
I am investigating what is going on.
Comment 5 Olivier Thomann CLA 2011-09-29 21:07:15 EDT
Ayushman, could you please investigate why the state index is identical for both return statements?
I believe this is the key of the problem here. They should not be identical since the locals initializations state is different for both return statement. If I replace the code with its for statement equivalent, the code generation is fine.
Comment 6 Ayushman Jain CLA 2011-10-03 06:24:23 EDT
(In reply to comment #5)
> Ayushman, could you please investigate why the state index is identical for
> both return statements?

I think this happens because the merged info that we return after the foreach statement has been analysed still consists of the initialization info of the foreach condition variable 'string' (it is still marked as definitely initialized in the flow info at the end of foreach analysis). This polluted flow info, is in turn, used to initialize the state index for the second return as well, and thus both return statements end up with the same indices. The flow info outside the foreach should not contain any initialization info for 'string'
Comment 7 Ayushman Jain CLA 2011-10-03 07:52:27 EDT
Created attachment 204440 [details]
proposed fix v1.0 + regression tests

The fix for the foreach case is fairly localised. We were adding the initialization info from the condition into the exit branch's info, which was finding its way into the final merged info. But since in foreach, a variable is always declared in the condition, and its scope ends with end of the foreach, we should not add any initialization info from the foreach condition. Also added a test for this.

I also saw the same thing happening in for statement case, although there was no verify error there as such. But again, any variable initialized in the for statement itself has no business to pollute the flow info after the for loop. This needed some more work as currently there was no infrastructure to remove the init info of specific variables from the flow info. 

Now the generated code is same as the one generated by javac 7 in both for and foreach case.

(I still need to run the complete test suite)
Comment 8 Ayushman Jain CLA 2011-10-03 10:39:05 EDT
(In reply to comment #7)
> (I still need to run the complete test suite)

All tests pass.
Comment 9 Ayushman Jain CLA 2011-10-03 11:57:45 EDT
Released in HEAD via commit 99350dc001d49db8dc24214c00ce73e1cd4de055.
Comment 10 Ayushman Jain CLA 2011-10-03 11:58:35 EDT
Reopening for backporting in R3_7_maintenance.

Olivier, need your +1 on this.
Comment 11 Olivier Thomann CLA 2011-10-04 10:41:48 EDT
Looks good to me.
Comment 12 Ayushman Jain CLA 2011-10-05 01:49:17 EDT
Released commit 4b5d6df0b2e1a9471a757e456125a40aa1a7569d in R3_7_maintenance.
Comment 13 Srikanth Sankaran CLA 2011-10-25 06:51:21 EDT
Verified for 3.8 M3 using build id: N20111022-2000
Comment 14 Srikanth Sankaran CLA 2012-01-19 01:18:09 EST
Verified for 3.7.2RC2 using build M20120118-0800
Comment 15 Ayushman Jain CLA 2012-01-19 01:46:09 EST
*** Bug 368996 has been marked as a duplicate of this bug. ***
Comment 16 Carsten Otto CLA 2012-05-25 05:09:50 EDT
(In reply to comment #14)
> Verified for 3.7.2RC2 using build M20120118-0800

Sadly, this is not fixed in 3.7.2 build M20120208-0800. Should it be fixed? If so, please reopen this bug (or my original one #368996).

Thanks,
Carsten
Comment 17 Srikanth Sankaran CLA 2012-05-25 10:08:43 EDT
(In reply to comment #16)
> (In reply to comment #14)
> > Verified for 3.7.2RC2 using build M20120118-0800
> 
> Sadly, this is not fixed in 3.7.2 build M20120208-0800. Should it be fixed? If
> so, please reopen this bug (or my original one #368996).

Version: 3.7.2
Build id: M20120127-0800 runs the test case from
https://bugs.eclipse.org/bugs/show_bug.cgi?id=368996#c2 just fine.

Are you sure you are not confusing the same symptom for the same problem ?

We have had multiple fixes in this area - one is also underway as we
speak.

Could you test with 3.8 RC1 bits posted ?
Comment 18 Ayushman Jain CLA 2012-05-25 10:53:29 EDT
(In reply to comment #16)
> (In reply to comment #14)
> > Verified for 3.7.2RC2 using build M20120118-0800
> 
> Sadly, this is not fixed in 3.7.2 build M20120208-0800. Should it be fixed? If
> so, please reopen this bug (or my original one #368996).
> 
> Thanks,
> Carsten

I downloaded the build and tried both the test cases in comment 0 of this bug and also the one that you gave in bug 368996. Both run fine without any errors.

What problem do you see?
Comment 19 Carsten Otto CLA 2012-05-29 11:11:44 EDT
> Are you sure you are not confusing the same symptom for the same problem ?

This may indeed be the problem. Sorry!

> We have had multiple fixes in this area - one is also underway as we
> speak.

Where can I find it?

> Could you test with 3.8 RC1 bits posted ?

I do not have Eclipse 3.8 RC1. However, I can provide a simple test case that breaks with Eclipse 3.7SR2 (20120216-1857):

public class E7Bug {
    public final static Object f() {
        final Object a = null;
        Object b;

        label: do {
            switch (0) {
            case 1: {
                b = a;
            }
                break;
            default:
                break label;
            }
        } while (true);

        return a;
    }

    public static void main(final String[] args) {
        f();
    }
}


Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 25 in method E7Bug.f()Ljava/lang/Object; at offset 3

This code results out of code generated by antlr (which is why we cannot easlily work around the bug).

Please re-open this ticket (or create a new one?).

Best regards,
Carsten Otto
Comment 20 Olivier Thomann CLA 2012-05-29 11:29:39 EDT
Carsten,

This is still an issue with the code in latest. I opened bug 380927 to cover your test case.
Thanks for the test case.