Community
Participate
Working Groups
I have a Java source file (attached in next post) that when compiled by Eclipse, produces a class file that causes javap from JDK 1.6.0-beta2-b86 to crash when trying to disassemble a particular StackMap attribute. I am using Eclipse with build ID I20060526-0010 on a Linux-AMD64 platform.
Created attachment 43501 [details] Java source that is incorrectly compiled by Eclipse The StackMap attribute generated for the 'getExceptionDispatchers' method causes javap in the latest Mustang (i.e. JDK 6) build to crash.
I'll investigate.
Philippe, The error reported by javap is fixed by using RC7. However there is another bug. We don't manage the locals right in the foreach statement. The range for the local corresponding to the elementVariable is too wide. Here is a shorted example: import java.util.ArrayList; import java.util.Iterator; import java.util.List; class B {} class C {} public class X { private List<B> list; public ArrayList<B> foo() { final ArrayList<B> tab = new ArrayList<B>(list.size()); for (B b : list) { tab.add(b); } return tab; } public static void main(String[] args) { } } for (B b : list) { tab.add(b); } is macro expanded to: for (Iterator<B> iterator = list.iterator(); iterator.hasNext(); ) { B b = iterator.next(); tab.add(b); } 0 new java.util.ArrayList [21] 3 dup 4 aload_0 [this] 5 getfield X.list : java.util.List [23] 8 invokeinterface java.util.List.size() : int [25] [nargs: 1] 13 invokespecial java.util.ArrayList(int) [31] 16 astore_1 [tab] 17 aload_0 [this] 18 getfield X.list : java.util.List [23] 21 invokeinterface java.util.List.iterator() : java.util.Iterator [34] [nargs: 1] 26 astore_3 27 goto 46 30 aload_3 31 invokeinterface java.util.Iterator.next() : java.lang.Object [38] [nargs: 1] 36 checkcast B [44] 39 astore_2 [b] 40 aload_1 [tab] 41 aload_2 [b] 42 invokevirtual java.util.ArrayList.add(java.lang.Object) : boolean [46] 45 pop 46 aload_3 47 invokeinterface java.util.Iterator.hasNext() : boolean [50] [nargs: 1] 52 ifne 30 55 aload_1 [tab] 56 areturn Line numbers: [pc: 0, line: 12] [pc: 17, line: 13] [pc: 40, line: 14] [pc: 46, line: 13] [pc: 55, line: 16] Local variable table: [pc: 0, pc: 57] local: this index: 0 type: X [pc: 17, pc: 57] local: tab index: 1 type: java.util.ArrayList [pc: 40, pc: 55] local: b index: 2 type: B Local variable type table: [pc: 17, pc: 57] local: tab index: 1 type: java.util.ArrayList<B> Stack map table: number of frames 2 [pc: 30, full, stack: {}, locals: {X, java.util.ArrayList, _, java.util.Iterator}] [pc: 46, full, stack: {}, locals: {X, java.util.ArrayList, B, java.util.Iterator}] But if you look at the bytecode that we generate, you will see that b is visible when we check iterator.hasNext() and this should not be the case. So I ended up with inconsistent stack frame. If you use this command line: java -XX:-FailOverToOldVerifier -Xverify:all X, you'll get a verify error: Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 46 in method X.foo()Ljava/util/ArrayList; at offset 27 This is due to the fact that in 27, the locals array looks like: this ArrayList _ Iterator And in 46, it looks like: this ArrayList B Iterator These two arrays should be identical. We have a scope for the forearch statement. All variables belongs to this scope, and I believe this is wrong. The elementVariable should not belongs to the same scope that the inits. It should belong to the scope of the action block. So we might want to emulate this by adding a new scope to hold this local that would be a subscope of the foreach scope. Then b would be put in local 3 instead of 2 and the iterator local would be 2 instead of 3. We could then remove b from the scope and let iterator visible till the end of the condition. What do you think? I'll start to fix it that way. Let me know if you see anything wrong with this approach.
Created attachment 43656 [details] Proposed fix This patch removes the elementVariable from the visible locals without introducing a new scope. I'll continue to check if this is good enough to fix this issue. At least the reported test case would be fixed.
Don't we have the same issue with regular for statements as well ? Adding an extra scope feels overkill, since per construction variables are not inserted in scopes at place they would interfere (i.e. though in scope of inits, inits cannot bind to variable by the time it is resolved). One thing to double check though, which could vote in favor of inserting a scope, is whether the current solution using one scope is altering the local variable allocation (when computing the variable offset and reusing entries in between sibling scopes). If we can produce a testcase where our allocation is unoptimal, then I would sign up for an extra scope, if not then I would favour an alternate solution. BTW - is this 3.2.1 or 3.3 ?
Cannot reproduce issue with standard FOR loops, as explicit variables are correctly managed (using inits). I suspect a similar story should be put in place for artificially inserted variables (synthetics), since their life cycle doesn't match the entire scope. Added new scopes for these is a no go I think.
Created attachment 45323 [details] Better patch More complete fix. There is still one remaining issues with try/catch/finally statement.
*** Bug 154480 has been marked as a duplicate of this bug. ***
Fixed and released in HEAD. Added org.eclipse.jdt.core.tests.compiler.regression.StackMapAttributeTest.test018/019.
Created attachment 48472 [details] Proposed patch Final patch that has been released.
Created attachment 48473 [details] Regression tests updated Corresponding regression tests that have been released.
Released for 3.2.1
Verified for 3.2.1 using build M20060908-1655
Released for 3.3 M2
Verified for 3.3 M2 using build I20060918-0010.