< prev index next >

test/hotspot/jtreg/compiler/stable/TestStableArrayMembars.java

Print this page
@@ -25,31 +25,44 @@
   * @test
   * @bug 8377541
   * @summary Test that membars are eliminated when loading from a stable array.
   * @library /test/lib /
   * @modules java.base/jdk.internal.misc
+  * @modules java.base/jdk.internal.value
   * @modules java.base/jdk.internal.vm.annotation
   * @run driver ${test.main.class}
   */
  
  package compiler.stable;
  
  import java.util.Objects;
+ import java.util.Set;
  
  import jdk.internal.misc.Unsafe;
+ import jdk.internal.value.ValueClass;
  import jdk.internal.vm.annotation.Stable;
  
+ import jdk.test.lib.Asserts;
  import compiler.lib.ir_framework.*;
  
  public class TestStableArrayMembars {
  
      private static final Unsafe UNSAFE = Unsafe.getUnsafe();
  
+     private static final int THE_VALUE = 42;
+ 
      public static void main(String[] args) {
          TestFramework tf = new TestFramework();
          tf.addTestClassesToBootClassPath();
-         tf.addFlags( "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED");
+         tf.addFlags("--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
+                     "--add-exports=java.base/jdk.internal.value=ALL-UNNAMED");
+         if (Integer.class.isValue()) {
+             tf.addCrossProductScenarios(Set.of("", "-XX:-UseArrayFlattening",
+                                                "-XX:-UseArrayFlattening -XX:-InlineTypePassFieldsAsArgs",
+                                                "-XX:-UseArrayFlattening -XX:-InlineTypeReturnedAsFields",
+                                                "-XX:-UseArrayFlattening -XX:-InlineTypePassFieldsAsArgs -XX:-InlineTypeReturnedAsFields"));
+         }
          tf.start();
      }
  
      static final class LazyIntArray {
          @Stable

@@ -59,47 +72,73 @@
              this.arr = new Integer[10];
          }
  
          @ForceInline
          Integer get(int idx) {
-             Integer i = contentsAcquire(offsetFor(idx));
+             Integer i = contentsAcquire(offsetFor(arr, idx));
              return i == null ? slowPath(arr, idx) : i;
          }
  
          @ForceInline
          private Integer contentsAcquire(long offset) {
-             return (Integer) UNSAFE.getReferenceAcquire(arr, offset);
+             return (Integer) (ValueClass.isFlatArray(arr) ?
+                 UNSAFE.getFlatValueAcquire(arr, offset, UNSAFE.arrayLayout(arr), Integer.class) :
+                 UNSAFE.getReferenceAcquire(arr, offset));
          }
  
          @ForceInline
-         private static long offsetFor(long index) {
-             return Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index;
+         private static long offsetFor(Integer[] arr, long index) {
+             return UNSAFE.arrayInstanceBaseOffset(arr) + UNSAFE.arrayInstanceIndexScale(arr) * index;
          }
  
          static Integer slowPath(final Integer[] array, final int index) {
-             final long offset = offsetFor(index);
+             final long offset = offsetFor(array, index);
              final Integer t = array[index];
              if (t == null) {
-                 final Integer newValue = Integer.valueOf(42);
+                 final Integer newValue = Integer.valueOf(THE_VALUE);
                  Objects.requireNonNull(newValue);
-                 set(array, index, newValue);
+                 set(array, index, offset, newValue);
  
                  return newValue;
              }
              return t;
          }
  
-         static void set(Integer[] array, int index, Integer newValue) {
+         static void set(Integer[] array, int index, long offset, Integer newValue) {
              if (array[index] == null) {
-                 UNSAFE.putReferenceRelease(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * (long) index, newValue);
+                 if (!ValueClass.isFlatArray(array)) {
+                     UNSAFE.putReferenceRelease(array, offset, newValue);
+                 } else {
+                     UNSAFE.putFlatValueRelease(array, offset, UNSAFE.arrayLayout(array), Integer.class, newValue);
+                 }
              }
          }
      }
  
      static final LazyIntArray la = new LazyIntArray();
  
      @Test
-     @IR(failOn = { IRNode.LOAD, IRNode.MEMBAR })
+     // We cannot eliminate all barriers with flat arrays, because Unsafe.getFlatValueAcquire()
+     // explicitly adds a loadFence() in Java. Hence, there is no way for C2 to correlate those
+     // barriers to an eliminated memory access and thus no way to remove them.
+     // The barrier elimination only works with tiered compilation as the profiling information
+     // is necessary to inline the low-frequency Unsafe.put* methods.
+     @IR(failOn = { IRNode.LOAD, IRNode.MEMBAR },
+         applyIfAnd = {"enable-valhalla", "false",
+                       "TieredCompilation", "true"})
+     @IR(failOn = { IRNode.LOAD, IRNode.MEMBAR },
+         applyIfAnd = {"UseArrayFlattening", "false",
+                       "TieredCompilation", "true"})
+     @IR(counts = { IRNode.MEMBAR, ">0",
+                    IRNode.LOAD, "=1"}, // There is exactly one load fence, but no load
+         applyIfAnd = {"enable-valhalla", "true",
+                       "UseArrayFlattening", "true",
+                       "TieredCompilation", "true"})
      static Integer test() {
          return la.get(0);
      }
+ 
+     @Check(test = "test")
+     static void check(Integer testResult) {
+         Asserts.assertEQ(THE_VALUE, testResult.intValue(), "Incorrect result from LazyIntArray");
+     }
  }
< prev index next >