<div dir="ltr"><pre style><div style><font color="#000000"><font face="verdana, sans-serif">Hi all,

I had dived into the issue with JDK-HotSpot commits and 
the issue arised after this commit: <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/a60a1309a03a">http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/rev/a60a1309a03a</a>

Then I added some additional logs to <b>"vm/c1/c1_Canonicalizer.cpp"</b>:

</font><font face="monospace, monospace">void Canonicalizer::do_UnsafeGetRaw(UnsafeGetRaw* x) { 
  if (OptimizeUnsafes) do_UnsafeRawOp(x); 
  tty->print_cr("Canonicalizer: do_UnsafeGetRaw id %d: base = id %d, index = id %d, log2_scale = %d",
                    x->id(), x->base()->id(), x->index()->id(), x->log2_scale());
}

void Canonicalizer::do_UnsafePutRaw(UnsafePutRaw* x) { 
  if (OptimizeUnsafes) do_UnsafeRawOp(x); 
  tty->print_cr("Canonicalizer: do_UnsafePutRaw id %d: base = id %d, index = id %d, log2_scale = %d",
                    x->id(), x->base()->id(), x->index()->id(), x->log2_scale());
}</font><font face="verdana, sans-serif">
<br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif"><br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif">
So I run the test by calculating address as 
- <b>"int * long"</b> (int is index and long is 8l)
- <b>"long * long"</b> (the first long is index and the second long is 8l)
- <b>"int * int"</b> (the first int is index and the second int is 8)

Here are the logs:

<b>int * long:</b>
</font><font face="monospace, monospace">Canonicalizer: do_UnsafeGetRaw id 18: base = id 16, index = id 17, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 20: base = id 16, index = id 19, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 22: base = id 16, index = id 21, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 24: base = id 16, index = id 23, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 33: base = id 13, index = id 27, log2_scale = 3
Canonicalizer: do_UnsafeGetRaw id 36: base = id 13, index = id 27, log2_scale = 3</font><font face="verdana, sans-serif">

<b>long * long:</b>
</font><font face="monospace, monospace">Canonicalizer: do_UnsafeGetRaw id 18: base = id 16, index = id 17, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 20: base = id 16, index = id 19, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 22: base = id 16, index = id 21, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 24: base = id 16, index = id 23, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 35: base = id 13, index = id 14, log2_scale = 3
Canonicalizer: do_UnsafeGetRaw id 37: base = id 13, index = id 14, log2_scale = 3</font><font face="verdana, sans-serif">

<b>int * int:</b>
</font><font face="monospace, monospace">Canonicalizer: do_UnsafeGetRaw id 18: base = id 16, index = id 17, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 20: base = id 16, index = id 19, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 22: base = id 16, index = id 21, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 24: base = id 16, index = id 23, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 33: base = id 13, index = id 29, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 36: base = id 13, index = id 29, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 19: base = id 8, index = id 15, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 22: base = id 8, index = id 15, log2_scale = 0</font><font face="verdana, sans-serif">

As you can see, at the problematic runs (<b>"int * long"</b> and <b>"long * long"</b>) there are two scaling.
One for <b>"Unsafe.put"</b> and the other one is for<b> "Unsafe.get"</b> and these instructions points to 
same <b>"base"</b> and <b>"index"</b> instructions. 
This means that address is scaled one more time because there should be only one scale.
<br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif"><br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif">
When I debugged the non-problematic run (<b>"int * int"</b>), 
I saw that <b>"instr->as_ArithmeticOp();"</b> is always returns <b>"null" </b>then <b>"match_index_and_scale"</b> method returns<b> "false"</b> always.
So there is no scaling.

</font><font face="monospace, monospace">static bool match_index_and_scale(Instruction*  instr,
                                  Instruction** index,
                                  int*          log2_scale) {
  ...

  ArithmeticOp* arith = instr->as_ArithmeticOp();
  if (arith != NULL) {
     ...
  }

  return false;
} </font><font face="verdana, sans-serif">
<br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif"><br></font></font></div><div style><font color="#000000"><font face="verdana, sans-serif">
Then I have added my fix attempt to prevent multiple scaling for Unsafe instructions points to same index instruction like this:

</font><font face="monospace, monospace">void Canonicalizer::do_UnsafeRawOp(UnsafeRawOp* x) {
  Instruction* base = NULL;
  Instruction* index = NULL;
  int          log2_scale;

  if (match(x, &base, &index, &log2_scale)) {
    x->set_base(base);
    x->set_index(index);
</font></font><span style="color:rgb(0,0,0);font-family:monospace,monospace">    </span><font color="#000000"><font face="monospace, monospace">// The fix attempt here
</font></font><span style="color:rgb(0,0,0);font-family:monospace,monospace">    </span><font color="#000000"><font face="monospace, monospace">// /////////////////////////////
    if (index != NULL) {
      if (index->is_pinned()) {
        log2_scale = 0;
      } else {
        if (log2_scale != 0) {
          index->pin();
        }
      } 
    }
</font></font><span style="color:rgb(0,0,0);font-family:monospace,monospace">    </span><font color="#000000"><font face="monospace, monospace">// /////////////////////////////
    x->set_log2_scale(log2_scale);
    if (PrintUnsafeOptimization) {
      tty->print_cr("Canonicalizer: UnsafeRawOp id %d: base = id %d, index = id %d, log2_scale = %d",
                    x->id(), x->base()->id(), x->index()->id(), x->log2_scale());
    }
  }
}
</font><font face="verdana, sans-serif">
In this fix attempt, if there is a scaling for the Unsafe instruction, I pin index instruction of that instruction
and at next calls, if the index instruction is pinned, I assummed that there is already scaling so no need to another scaling.

After this fix, I rerun the problematic test (<b>"int * long"</b>) and it works with these logs:

<b>int * long (after fix):</b>
</font><font face="monospace, monospace">Canonicalizer: do_UnsafeGetRaw id 18: base = id 16, index = id 17, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 20: base = id 16, index = id 19, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 22: base = id 16, index = id 21, log2_scale = 0
Canonicalizer: do_UnsafeGetRaw id 24: base = id 16, index = id 23, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 35: base = id 13, index = id 14, log2_scale = 3
Canonicalizer: do_UnsafeGetRaw id 37: base = id 13, index = id 14, log2_scale = 0
Canonicalizer: do_UnsafePutRaw id 21: base = id 8, index = id 11, log2_scale = 3
Canonicalizer: do_UnsafeGetRaw id 23: base = id 8, index = id 11, log2_scale = 0</font><font face="verdana, sans-serif">

I am not sure my fix attempt is a really fix or maybe there are better fixes.

Regards.

--</font>

Serkan ÖZAL<br></font></div><div style="color:rgb(0,0,0)"> </div><blockquote class="gmail_quote" style="color:rgb(0,0,0);margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Btw, (thanks to one my colleagues), when address calculation in the loop is<br>converted to
long address = baseAddress + (i * 8)
test passes. Only difference is next long pointer is calculated using<br>integer 8 instead of long 8.
```<br>for (int i = 0; i < count; i++) {<br>    long address = baseAddress + (i * 8); // <--- here, integer 8 instead<br>of long 8
    long expected = i;<br>    unsafe.putLong(address, expected);
    long actual = unsafe.getLong(address);
    if (expected != actual) {<br>        throw new AssertionError("Expected: " + expected + ", Actual: " +<br>actual);<br>    }<br>}<br>```
On Tue, Jun 9, 2015 at 1:07 PM Mehmet Dogan <<a href="http://mail.openjdk.java.net/mailman/listinfo/hotspot-compiler-dev">mehmet at hazelcast.com</a>> wrote:
><i> Hi all,
</i>><br>><i> While I was testing my app using java 8, I encountered the previously
</i>><i> reported sun.misc.Unsafe issue.
</i>><br>><i> <a href="https://bugs.openjdk.java.net/browse/JDK-8076445">https://bugs.openjdk.java.net/browse/JDK-8076445</a>
</i>><br>><i> <a href="http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2015-April/017685.html">http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2015-April/017685.html</a>
</i>><br>><i> Issue status says it's resolved with resolution "Cannot Reproduce".  But
</i>><i> unfortunately it's still reproducible using "1.8.0_60-ea-b18" and
</i>><i> "1.9.0-ea-b67".
</i>><br>><i> Test is very simple:
</i>><br>><i> ```
</i>><i> public static void main(String[] args) throws Exception {
</i>><i>         Unsafe unsafe = findUnsafe();
</i>><i>         // 10000 pass
</i>><i>         // 100000 jvm crash
</i>><i>         // 1000000 fail
</i>><i>         int count = 100000;
</i>><i>         long size = count * 8L;
</i>><i>         long baseAddress = unsafe.allocateMemory(size);
</i>><br>><i>         try {
</i>><i>             for (int i = 0; i < count; i++) {
</i>><i>                 long address = baseAddress + (i * 8L);
</i>><br>><i>                 long expected = i;
</i>><i>                 unsafe.putLong(address, expected);
</i>><br>><i>                 long actual = unsafe.getLong(address);
</i>><br>><i>                 if (expected != actual) {
</i>><i>                     throw new AssertionError("Expected: " + expected + ",
</i>><i> Actual: " + actual);
</i>><i>                 }
</i>><i>             }
</i>><i>         } finally {
</i>><i>             unsafe.freeMemory(baseAddress);
</i>><i>         }
</i>><i>     }
</i>><i> ```
</i>><i> It's not failing up to version 1.8.0.31, by starting 1.8.0.40 test is
</i>><i> failing constantly.
</i>><br>><i> - With iteration count 10000, test is passing.
</i>><i> - With iteration count 100000, jvm is crashing with SIGSEGV.
</i>><i> - With iteration count 1000000, test is failing with AssertionError.
</i>><br>><i> When one of compilation (-Xint) or inlining (-XX:-Inline) or
</i>><i> on-stack-replacement (-XX:-UseOnStackReplacement) is disabled, test is not
</i>><i> failing at all.
</i>><br>><i> I tested on platforms:
</i>><i> - Centos-7/openjdk-1.8.0.45
</i>><i> - OSX/oraclejdk-1.8.0.40
</i>><i> - OSX/oraclejdk-1.8.0.45
</i>><i> - OSX/oraclejdk-1.8.0_60-ea-b18
</i>><i> - OSX/oraclejdk-1.9.0-ea-b67
</i>><br>><i> Previous issue comment (
</i>><i> <a href="https://bugs.openjdk.java.net/browse/JDK-8076445?focusedCommentId=13633043#comment-13633043">https://bugs.openjdk.java.net/browse/JDK-8076445?focusedCommentId=13633043#comment-13633043</a>)
</i>><i> says "Cannot reproduce based on the latest version". I hope that latest
</i>><i> version is not mentioning to '1.8.0_60-ea-b18' or '1.9.0-ea-b67'. Because
</i>><i> both are failing.
</i>><br>><i> I'm looking forward to hearing from you.
</i>><br>><i> Thanks,
</i>><i> -Mehmet Dogan-
</i>><i> --
</i>><br>><i> @mmdogan
</i>></blockquote></pre><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr">Serkan ÖZAL<div>Remotest Software Engineer</div><div>GSM: +90 542 680 39 18</div><div>Twitter: @serkan_ozal</div></div></div>
</div>