<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>Hi,<br>
      I had the same reaction as Remi when first reading this thread. In
      principle, yes, replacing invokespecial with invokevirtual can
      cause bridge calls to go up and down the hierarchy and has more
      potential for generating infinite loops. That said, I have not
      been able to come up with a reasonable test case that would
      introduce an infinite loop should javac implement the proposed
      change. While 6996415 is definitively related, I believe that the
      loop in that example is started by a bad descriptor ending up in
      the explicit supercall (see bug evaluation) rather than by a
      problem between invokevirtual vs. invokespecial.</p>
    <p>I also note that ECJ already generates an invokevirtual in the
      reported example. Again, I could not find any clue of a
      bridge-related loop that shows up in ECJ but not in javac (but I'd
      be happy to know if something like that exists),.</p>
    <p>So, maybe it's a safe move after all?<br>
    </p>
    <p>Maurizio<br>
    </p>
    <p><br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 03/10/16 14:42, Remi Forax wrote:<br>
    </div>
    <blockquote
      cite="mid:126526629.325590.1475502172744.JavaMail.zimbra@u-pem.fr"
      type="cite">
      <div style="font-family: arial, helvetica, sans-serif; font-size:
        12pt; color: #000000">
        <div>Hi Rafael,<br>
        </div>
        <div>it's not a binary compatible change.<br>
        </div>
        <div><br data-mce-bogus="1">
        </div>
        <div>if the compiler emits an invokevirtual instead of an
          invokespecial, you can create an infinite loop between the
          bridges <br data-mce-bogus="1">
        </div>
        <div><a class="moz-txt-link-freetext" href="https://bugs.openjdk.java.net/browse/JDK-6996415">https://bugs.openjdk.java.net/browse/JDK-6996415</a></div>
        <div><br data-mce-bogus="1">
        </div>
        <div>Rémi<br data-mce-bogus="1">
        </div>
        <div><br>
        </div>
        <hr id="zwchr" data-marker="__DIVIDER__">
        <div data-marker="__HEADERS__">
          <blockquote style="border-left: 2px solid #1010FF;
            margin-left: 5px; padding-left: 5px; color: #000;
            font-weight: normal; font-style: normal; text-decoration:
            none; font-family: Helvetica,Arial,sans-serif; font-size:
            12pt;" data-mce-style="border-left: 2px solid #1010FF;
            margin-left: 5px; padding-left: 5px; color: #000;
            font-weight: normal; font-style: normal; text-decoration:
            none; font-family: Helvetica,Arial,sans-serif; font-size:
            12pt;"><b>De: </b>"Rafael Winterhalter"
            <a class="moz-txt-link-rfc2396E" href="mailto:rafael.wth@gmail.com"><rafael.wth@gmail.com></a><br>
            <b>À: </b><a class="moz-txt-link-abbreviated" href="mailto:compiler-dev@openjdk.java.net">compiler-dev@openjdk.java.net</a><br>
            <b>Envoyé: </b>Lundi 3 Octobre 2016 12:13:29<br>
            <b>Objet: </b>Why does javac use "invokespecial" for
            diamond inheritance?<br>
          </blockquote>
        </div>
        <div data-marker="__QUOTED_TEXT__">
          <blockquote style="border-left: 2px solid #1010FF;
            margin-left: 5px; padding-left: 5px; color: #000;
            font-weight: normal; font-style: normal; text-decoration:
            none; font-family: Helvetica,Arial,sans-serif; font-size:
            12pt;" data-mce-style="border-left: 2px solid #1010FF;
            margin-left: 5px; padding-left: 5px; color: #000;
            font-weight: normal; font-style: normal; text-decoration:
            none; font-family: Helvetica,Arial,sans-serif; font-size:
            12pt;">
            <div dir="ltr">
              <div>
                <div>
                  <div>I am wondering why javac is using an
                    invokespecial instruction for a bridge method in the
                    following case. Considering the following
                    refactoring starting from:<br>
                    <br>
                  </div>
                  class A {<br>
                </div>
                Â  public void m(String s) {<br>
              </div>
              Â Â Â  System.out.println("foo");<br>
              <div>  }<br>
                <div>}<br>
                  <br>
                </div>
                <div>class B extends A { }<br>
                  <br>
                </div>
                <div>class C extends B {<br>
                  Â  public void m(String s) {<br>
                  Â Â Â  System.out.println("bar");<br>
                  Â  }<br>
                  }<br>
                  <br>
                </div>
                <div>I would change the implementing of B to implement
                  an additional interface:<br>
                  <br>
                </div>
                <div>interface I<T> {<br>
                </div>
                <div>  void m(T t);<br>
                </div>
                <div>}<br>
                </div>
                <div><br>
                  class B extends A implements I<String> { }<br>
                  <br>
                </div>
                <div>C would live in its own module that is not
                  recompiled upon changing B. I do however not consider
                  this a problem as the change of B is binary
                  compatible. However, B ends up with the following
                  bridge method:<br>
                  <br>
                  class B extends A implements I<String> { <br>
                </div>
                <div>  public bridge void m(Object o) {<br>
                </div>
                <div>    Foo.special.m((String) o);<br>
                </div>
                <div>  }<br>
                </div>
                <div>}<br>
                  <br>
                </div>
                <div>If a program does now invoke I::m on an instance of
                  C, "foo" is printed instead of "bar". This violates
                  the intended virtual dispatch for C. In my opinion,
                  this should not happen. Bridge methods, unless
                  "visibility bridges" should always use invokevirtual
                  as an override in C, should make it impossible to
                  invoke A::m directly from outside the class.<br>
                  <br>
                </div>
                <div>Did I miss something here or is this a bug?<br>
                  <br>
                </div>
                <div>Thank you for the clarification,<br>
                  Best regards, Rafael</div>
              </div>
            </div>
            <br>
          </blockquote>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>