1 class EscapeInInitializer { 2 private final int foo; 3 private final int bar; 4 private static EscapeInInitializer cache; 5 6 EscapeInInitializer() { 7 this.foo = 1; // put a final field, set_alloc_with_final(obj) 8 cache = this; // materialize this here. 9 this.bar = 2; // put a final field again, set_alloc_with_final(obj) 10 } 11 12 EscapeInInitializer(int i) { 13 this.foo = 1; // put a final field, set_alloc_with_final(obj) 14 this.bar = the_answer(); // invocation, either inline or not line may trigger materialization. 15 } 16 17 EscapeInInitializer(boolean cond) { 18 this.foo = 1; // put a final field, set_alloc_with_final(obj) 19 this.bar = 2; 20 if (cond) { 21 cache = this; // materialize this here. 22 } 23 // we need to merge 'this' here, and then emit the trailing barrier for the phi. 24 } 25 26 int the_answer() { // of life, the universe and everything... 27 cache = this; // materialize 'this' here 28 return 42; 29 } 30 31 static class Scope { 32 public int kind; 33 final Scope parent; 34 final Scope compilationUnitScope; 35 36 // https://github.com/testforstephen/eclipse.jdt.core/blob/c74a21fabed6931812aac1d1cc3b5b09690e8c96/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java#L159C86-L159C106 37 public Scope(int kind, Scope parent) { 38 this.kind = kind; 39 this.parent = parent; 40 this.compilationUnitScope = (parent == null ? this : parent.compilationUnitScope()); 41 } 42 43 public Scope compilationUnitScope() { 44 return new Scope(0, null); 45 } 46 } 47 48 static void test(int i) { 49 var kase = new EscapeInInitializer(); 50 var kase2 = new EscapeInInitializer(i); 51 var kase3 = new EscapeInInitializer(0 == (i % 100)); 52 } 53 54 static void test2(int i) { 55 Scope parent = new Scope(1, null); 56 var kase = new Scope(i, 0 == (i % 100) ? null : parent); 57 } 58 public static void main(String[] args) { 59 for (int i = 0; i < 30_000; ++i) { 60 test(i); 61 test2(i); 62 } 63 } 64 }