[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-compiler-dev
Subject:    Re: RFR: 8332106: VerifyError when using switch pattern in this(...) or super(...) [v2]
From:       Vicente Romero <vromero () openjdk ! org>
Date:       2024-05-17 21:04:02
Message-ID: 8QygzGCD4GL-tGLGnOiRiy01-GVNN4nl4YqGiEg8Vhs=.86b45365-7c51-4d7b-96c2-c7b245eaa2d4 () github ! com
[Download RAW message or body]

On Tue, 14 May 2024 11:24:22 GMT, Jan Lahoda <jlahoda@openjdk.org> wrote:

> > Considering code like:
> > 
> > public class Test {
> > 
> > public Test(int i) {
> > }
> > 
> > public Test(Object o) {
> > this(o instanceof R(String s) ? s.length() : -1);
> > }
> > 
> > public static void main(String... args) {}
> > 
> > record R(String s) {}
> > }
> > 
> > 
> > Running this crashes:
> > 
> > $ java .../Test.java
> > Exception in thread "main" java.lang.VerifyError: Stack map does not match the \
> > one at exception handler 36 Exception Details:
> > Location:
> > Test.<init>(Ljava/lang/Object;)V @36: astore_2
> > Reason:
> > Type uninitializedThis (current frame, locals[0]) is not assignable to 'Test' \
> > (stack map, locals[0]) Current Frame:
> > bci: @14
> > flags: { flagThisUninit }
> > locals: { uninitializedThis, 'java/lang/Object', top, 'Test$R' }
> > stack: { 'java/lang/Throwable' }
> > Stackmap Frame:
> > bci: @36
> > flags: { }
> > locals: { 'Test', 'java/lang/Object' }
> > stack: { 'java/lang/Throwable' }
> > Bytecode:
> > 0000000: 2a2b c100 0799 0018 2bc0 0007 4e2d b600
> > 0000010: 093a 0419 044d 2cb6 000d a700 0402 b700
> > 0000020: 13a7 0011 4dbb 001a 592c b600 1c2c b700
> > 0000030: 1fbf b1                                
> > Exception Handler Table:
> > bci [14, 17] => handler: 36
> > Stackmap Table:
> > same_locals_1_stack_item_frame(@29,UninitializedThis)
> > full_frame(@30,{UninitializedThis,Object[#2]},{UninitializedThis,Integer})
> > full_frame(@36,{Object[#20],Object[#2]},{Object[#24]})
> > same_frame(@50)
> > 
> > at java.base/java.lang.Class.forName0(Native Method)
> > at java.base/java.lang.Class.forName(Class.java:534)
> > at java.base/java.lang.Class.forName(Class.java:513)
> > at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:432)
> > at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:208)
> > at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:135)
> > 
> > 
> > The reason is that there is a synthetic catch generated wrapping the record \
> > accessors inside the pattern matching. The range where the exception this catch \
> > is catching is before the real `this(...)` `invokespecial`, and hence the `this` \
> > is still an "uninitialized this". But the code for the catch is generated at the \
> > end of the constructor, when `this` is already initialized, and javac generates \
> > the stack maps as if `this` was initialized. 
> > In general, the pattern matching code can be both before and after the `this` has \
> > been initialized. But, I do...
> 
> Jan Lahoda has updated the pull request incrementally with one additional commit \
> since the last revision: 
> Enhancing test as suggested.

test/langtools/tools/javac/patterns/UninitializedThisException.java line 45:

> 43: 
> 44:     public UninitializedThisException(R o1, R o2, R o3) {
> 45:         out.println("-pre(" + o1.fail() + ")" +

I wonder if it makes sense to use annotations instead

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/19217#discussion_r1605542935


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic