RFR: 8332106: VerifyError when using switch pattern in this(...) or super(...) [v2]

Vicente Romero vromero at openjdk.org
Fri May 17 20:55:01 UTC 2024


On Tue, 14 May 2024 11:24:22 GMT, Jan Lahoda <jlahoda at 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.

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java line 176:

> 174:     LocalItem switchResult;
> 175:     PatternMatchingCatchConfigration patternMatchingCatchConfiguration =
> 176:             new PatternMatchingCatchConfigration(Set.of(), null, null, null);

typo: Configuration

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

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


More information about the compiler-dev mailing list