<div dir="ltr"><div><div dir="ltr">On Tue, Nov 1, 2022 at 4:30 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br>
    </div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><blockquote type="cite">
      <div dir="ltr">
        <div class="gmail_quote">
          <div>First of all, when should this rule apply?</div>
          <div><br>
          </div>
          <div>At any point in a constructor (one that successfully
            compiles), the new object is always definitively in one of
            three states:<br>
          </div>
          <div>
            <div><br>
            </div>
            <div>State 0: neither <span style="font-family:monospace">super()</span>
              nor <span style="font-family:monospace">this()</span> has
              been invoked; neither the superclass nor this class are
              initialized</div>
            <div>State 1: <span style="font-family:monospace">super()</span>
              has been invoked, so the superclass is initialized, but at
              least one final field in this class has not been
              initialized<br>
            </div>
            <div>State 2: <span style="font-family:monospace">super()</span>
              has been invoked and all final fields in this class have
              been initialized</div>
            <div><br>
            </div>
            <div>BTW, the current state is easily tracked within the
              existing DA/DU analysis of the prototype patch.<br>
            </div>
            <div><br>
            </div>
            <div>The possible state transitions are:</div>
            <div><br>
            </div>
            <div>- <span style="font-family:monospace">super()</span>
              takes you from:</div>
            <div>  - State 0 → State 1 if there remain any uninitialized
              final fields</div>
            <div>  - State 0 → State 2 if there are no remaining
              uninitialized final fields</div>
            <div>- <span style="font-family:monospace">this()</span>
              takes you from State 0 → State 2</div>
            <div>- Initializing the last final field takes you from:</div>
            <div>
              <div>  - State 0 → State 0<br>
              </div>
              <div>  - State 1 → State 2</div>
              <div><br>
              </div>
              <div>Presumably the 'this' escape analysis should only
                apply in State 1. This is when the object is vulnerable
                because it's half initialized.</div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
    In actuality, `this` can escape in any of the states; escaping means
    that `this` is exposed before the return from the constructor. 
    (Even the very last line of the constructor is suspect.  A class
    could have subclasses, which means we're still in "the middle" of
    the subclass constructor, and even for a final class, the write
    barrier does not get emitted until after the constructor
    completes.) <br></div></blockquote><div><br></div><div>It can't escape in State 0, because the JVM itself prevents that, right?<br></div><div><br></div><div>But of course you're right about State 2 - the subclass constructor is still happening at that point, and so you could invoke a method that is overridden in the subclass, but the subclass won't be ready for it yet.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>In any case, let's start with the strictest view and work backwards
    to relaxation.  The receiver may escape if:<br>
    <br>
     - a non-final instance method is invoked (*)<br>
     - an instance method declared in a superclass is invoked<br>
     - the variable `this` is used for anything other than field access
    <br>
    <br>
    We should analyze not only constructor code, but instance
    initializer blocks and instance field initializers as well. </div></blockquote><div><br></div><div>Yes... they are just blobs of code that get executed immediately after any <span style="font-family:monospace">super()</span> calls (as I've learned) and the patch includes a similar change to that effect for DA/DU already.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>We can
    exclude final instance methods declared in the same class if the
    same analysis of the method (recursively) shows no escape of `this`
    (this is the * in the first bullet above.)<br></div></blockquote><div><div> </div><div><div>Neat.</div><div><br><div>You could also analyze static methods in the class 
to verify non-escape if they were invoked with 'this' as a parameter... 
it's more or less the same situation.</div><div><br></div><div>Any code 
in the compilation unit that is directly invoked by the constructor and 
that can't possibly be overridden could in theory be fair game for this 
non-escape analysis.</div><div><br></div></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
    Inner class creation is a similar story as calling final methods in
    the same class; we can do a similar analysis of the inner class
    constructor to verify non-escape.<br></div></blockquote></div><br><div><div>But the inner class <span style="font-family:monospace">Outer.Inner</span>'s constructor is going to say <span style="font-family:monospace">this.$0 = Outer.this</span>, which is an escape for <span style="font-family:monospace">Outer.this</span>, right?<br></div><div><br></div><div>That would permit sneaky situations like this (choose either lambda or inner class variant):</div><div><div><br></div><div><span style="font-family:monospace">    public class MyClass  {</span></div><br><div><span style="font-family:monospace">        public MyClass() {</span></div><div><span style="font-family:monospace">            new Runnable() {</span></div><div><span style="font-family:monospace">                public void run() {<br></span></div><div><span style="font-family:monospace">                    MyClass.this.foo();<br></span></div><div><span style="font-family:monospace">                }<br></span></div><div><span style="font-family:monospace">            }.run();<br></span></div><span style="font-family:monospace">        }</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">        public void foo() {<br>            // ...</span></div><div><span style="font-family:monospace">        }</span></div><div><span style="font-family:monospace">    }<br></span></div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
    <br>
    <blockquote type="cite">
      <div dir="ltr">
        <div class="gmail_quote">For the meaning of "known to be equal
          to 'this'", we would be limited in our ability to infer it in
          the usual ways (Turing complete, blah blah), so you'd still be
          able to evade the warning e.g.:<br>
        </div>
      </div>
    </blockquote>
    <br>
    For this to happen, `this` must have already escaped or have been
    assigned to another variable.  The above already detects this.<br>
  </div>

</blockquote></div><br clear="all"></div><div>Right - in other words, the "anything other than field access" clause would disallow casting <span style="font-family:monospace">(Object)this</span> like in the example.<br></div><div><br></div><div>-Archie</div><div><br></div><div>-- <br><div dir="ltr" class="gmail_signature">Archie L. Cobbs<br></div></div></div>