8149469: ByteBuffer API and implementation enhancements for VarHandles
authorpsandoz
Thu, 24 Mar 2016 11:21:18 +0100
changeset 36933 3e6453e2d833
parent 36930 74e9f4b90006
child 36934 590fc47a0aeb
8149469: ByteBuffer API and implementation enhancements for VarHandles Reviewed-by: chegar, alanb
jdk/src/java.base/share/classes/java/nio/Buffer.java
jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template
jdk/src/java.base/share/classes/java/nio/StringCharBuffer.java
jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template
jdk/test/java/nio/Buffer/Basic-X.java.template
jdk/test/java/nio/Buffer/Basic.java
jdk/test/java/nio/Buffer/BasicByte.java
jdk/test/java/nio/Buffer/BasicChar.java
jdk/test/java/nio/Buffer/BasicDouble.java
jdk/test/java/nio/Buffer/BasicFloat.java
jdk/test/java/nio/Buffer/BasicInt.java
jdk/test/java/nio/Buffer/BasicLong.java
jdk/test/java/nio/Buffer/BasicShort.java
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,9 @@
 
 package java.nio;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 import java.util.Spliterator;
-import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * A container for data of a specific primitive type.
@@ -188,7 +189,15 @@
     private int limit;
     private int capacity;
 
-    // Used only by direct buffers
+    // Used by heap byte buffers or direct buffers with Unsafe access
+    // For heap byte buffers this field will be the address relative to the
+    // array base address and offset into that array. The address might
+    // not align on a word boundary for slices, nor align at a long word
+    // (8 byte) boundary for byte[] allocations on 32-bit systems.
+    // For direct buffers it is the start address of the memory region. The
+    // address might not align on a word boundary for slices, nor when created
+    // using JNI, see NewDirectByteBuffer(void*, long).
+    // Should ideally be declared final
     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
     long address;
 
--- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Thu Mar 24 11:21:18 2016 +0100
@@ -140,6 +140,7 @@
         att = null;
 #else[rw]
         super(cap);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -180,6 +181,7 @@
         att = null;
 #else[rw]
         super(cap, addr, fd, unmapper);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -200,6 +202,7 @@
         att = db;
 #else[rw]
         super(db, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -213,6 +216,15 @@
         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
     }
 
+#if[byte]
+    public $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Direct$Type$Buffer$RW$$BO$(this,
                                               this.markValue(),
--- a/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,9 @@
         super(cap, lim);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
@@ -87,6 +90,9 @@
         super(buf, off, len);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     protected Heap$Type$Buffer$RW$($type$[] buf,
@@ -103,6 +109,9 @@
         super(buf, mark, pos, lim, cap, off);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset + off;
+#end[byte]
     }
 
     public $Type$Buffer slice() {
@@ -114,6 +123,20 @@
                                         this.position() + offset);
     }
 
+#if[byte]
+    $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        rem,
+                                        rem,
+                                        pos + offset);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Heap$Type$Buffer$RW$(hb,
                                         this.markValue(),
@@ -144,7 +167,7 @@
 
 #if[byte]
     private long byteOffset(long i) {
-        return arrayBaseOffset + i + offset;
+        return address + i;
     }
 #end[byte]
 
--- a/jdk/src/java.base/share/classes/java/nio/StringCharBuffer.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/StringCharBuffer.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@
         if ((start < 0) || (start > n) || (end < start) || (end > n))
             throw new IndexOutOfBoundsException();
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer slice() {
@@ -58,6 +59,7 @@
                              int offset) {
         super(mark, pos, limit, cap, null, offset);
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer duplicate() {
--- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -269,7 +269,7 @@
     //
     final $type$[] hb;                  // Non-null only for heap buffers
     final int offset;
-    boolean isReadOnly;                 // Valid only for heap buffers
+    boolean isReadOnly;
 
     // Creates a new buffer with the given mark, position, limit, capacity,
     // backing array, and array offset
@@ -530,6 +530,10 @@
      * it will be read-only if, and only if, this buffer is read-only.  </p>
      *
      * @return  The new $type$ buffer
+#if[byte]
+     *
+     * @see #alignedSlice(int)
+#end[byte]
      */
     public abstract $Type$Buffer slice();
 
@@ -1611,6 +1615,143 @@
         return this;
     }
 
+    /**
+     * Returns the memory address, pointing to the byte at the given index,
+     * modulus the given unit size.
+     *
+     * <p> A return value greater than zero indicates the address of the byte at
+     * the index is misaligned for the unit size, and the value's quantity
+     * indicates how much the index should be rounded up or down to locate a
+     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
+     * that the address of the byte at the index is aligned for the unit size.
+     *
+     * @apiNote
+     * This method may be utilized to determine if unit size bytes from an
+     * index can be accessed atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  index
+     *         The index to query for alignment offset, must be non-negative, no
+     *         upper bounds check is performed
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The indexed byte's memory address modulus the unit size
+     *
+     * @throws IllegalArgumentException
+     *         If the index is negative or the unit size is not a power of
+     *         {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable alignment offset
+     *         values for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignedSlice(int)
+     * @since 9
+     */
+    public final int alignmentOffset(int index, int unitSize) {
+        if (index < 0)
+            throw new IllegalArgumentException("Index less than zero: " + index);
+        if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+            throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+        if (unitSize > 8 && !isDirect())
+            throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+        return (int) ((address + index) % unitSize);
+    }
+
+    /**
+     * Creates a new byte buffer whose content is a shared and aligned
+     * subsequence of this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position rounded up to the index of the nearest aligned byte for the
+     * given unit size, and end at this buffer's limit rounded down to the index
+     * of the nearest aligned byte for the given unit size.
+     * If rounding results in out-of-bound values then the new buffer's capacity
+     * and limit will be zero.  If rounding is within bounds the following
+     * expressions will be true for a new buffer {@code nb} and unit size
+     * {@code unitSize}:
+     * <pre>{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }</pre>
+     *
+     * <p> Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer or fewer subject to
+     * alignment, its mark will be undefined, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @apiNote
+     * This method may be utilized to create a new buffer where unit size bytes
+     * from index, that is a multiple of the unit size, may be accessed
+     * atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The new byte buffer
+     *
+     * @throws IllegalArgumentException
+     *         If the unit size not a power of {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable aligned slices
+     *         for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignmentOffset(int, int)
+     * @see #slice()
+     * @since 9
+     */
+    public final ByteBuffer alignedSlice(int unitSize) {
+        int pos = position();
+        int lim = limit();
+
+        int pos_mod = alignmentOffset(pos, unitSize);
+        int lim_mod = alignmentOffset(lim, unitSize);
+
+        // Round up the position to align with unit size
+        int aligned_pos = (pos_mod > 0)
+            ? pos + (unitSize - pos_mod)
+            : pos;
+
+        // Round down the limit to align with unit size
+        int aligned_lim = lim - lim_mod;
+
+        if (aligned_pos > lim || aligned_lim < pos) {
+            aligned_pos = aligned_lim = pos;
+        }
+
+        return slice(aligned_pos, aligned_lim);
+    }
+
+    abstract ByteBuffer slice(int pos, int lim);
+
     // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
     //
     abstract byte _get(int i);                          // package-private
--- a/jdk/test/java/nio/Buffer/Basic-X.java.template	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/Basic-X.java.template	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -336,6 +336,103 @@
 
     }
 
+    private static void testAlign(final ByteBuffer b, boolean direct) {
+        // index out-of bounds
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+
+        // unit size values
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        for (int us = 1; us < 65; us++) {
+            int _us = us;
+            if ((us & (us - 1)) != 0) {
+                // unit size not a power of two
+                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+            } else {
+                if (direct || us <= 8) {
+                    b.alignmentOffset(0, us);
+                } else {
+                    // unit size > 8 with non-direct buffer
+                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                }
+            }
+        }
+
+        // Probe for long misalignment at index zero for a newly created buffer
+        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
+        if (direct) {
+            // Freshly created direct byte buffers should be aligned at index 0
+            // for ref and primitive values (see Unsafe.allocateMemory)
+            if (longMisalignmentAtZero != 0)
+                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        } else {
+            // For heap byte buffers misalignment may occur on 32-bit systems
+            // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
+            // Note the GC will preserve alignment of the base address of the
+            // array
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
+                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        }
+
+        // Ensure test buffer is correctly aligned at index 0
+        if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+            fail("Test input buffer not correctly aligned at index 0", b);
+
+        // Test misalignment values
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int i = 0; i < us * 2; i++) {
+                int am = b.alignmentOffset(i, us);
+                int expectedAm = (longMisalignmentAtZero + i) % us;
+
+                if (am != expectedAm)
+                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+            }
+        }
+
+        // Created aligned slice to test against
+        int ap = 8 - longMisalignmentAtZero;
+        int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+        ByteBuffer ab = b.position(ap).limit(al).
+                slice();
+        if (ab.limit() == 0)
+            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.alignmentOffset(0, 8) != 0)
+            fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int p = 1; p < 16; p++) {
+                int l = ab.limit() - p;
+
+                ByteBuffer as = ab.slice().position(p).limit(l).
+                        alignedSlice(us);
+
+                ck(as, 0, as.position());
+                ck(as, as.capacity(), as.limit());
+                if (b.isDirect() != as.isDirect())
+                    fail("Lost direction", as);
+                if (b.isReadOnly() != as.isReadOnly())
+                    fail("Lost read-only", as);
+
+                if (as.alignmentOffset(0, us) != 0)
+                    fail("Buffer not correctly aligned at index 0", as);
+
+                if (as.alignmentOffset(as.limit(), us) != 0)
+                    fail("Buffer not correctly aligned at limit", as);
+
+                int p_mod = ab.alignmentOffset(p, us);
+                int l_mod = ab.alignmentOffset(l, us);
+                // Round up position
+                p = (p_mod > 0) ? p + (us - p_mod) : p;
+                // Round down limit
+                l = l - l_mod;
+
+                int ec = l - p;
+                if (as.limit() != ec)
+                    fail("Buffer capacity incorrect, expected: " + ec, as);
+            }
+        }
+    }
 #end[byte]
 
     private static void fail(String problem,
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+#if[byte]
+        // Test alignment
+
+        testAlign(b, direct);
+#end[byte]
     }
 
 #if[char]
--- a/jdk/test/java/nio/Buffer/Basic.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/Basic.java	Thu Mar 24 11:21:18 2016 +0100
@@ -26,6 +26,7 @@
  * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
  *      4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
  *      6221101 6234263 6535542 6591971 6593946 6795561 7190219 7199551 8065556
+ *      8149469
  * @author Mark Reinhold
  */
 
--- a/jdk/test/java/nio/Buffer/BasicByte.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicByte.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -336,6 +336,103 @@
 
     }
 
+    private static void testAlign(final ByteBuffer b, boolean direct) {
+        // index out-of bounds
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(-1, (short) 1));
+
+        // unit size values
+        tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, (short) 0));
+        for (int us = 1; us < 65; us++) {
+            int _us = us;
+            if ((us & (us - 1)) != 0) {
+                // unit size not a power of two
+                tryCatch(b, IllegalArgumentException.class, () -> b.alignmentOffset(0, _us));
+            } else {
+                if (direct || us <= 8) {
+                    b.alignmentOffset(0, us);
+                } else {
+                    // unit size > 8 with non-direct buffer
+                    tryCatch(b, UnsupportedOperationException.class, () -> b.alignmentOffset(0, _us));
+                }
+            }
+        }
+
+        // Probe for long misalignment at index zero for a newly created buffer
+        ByteBuffer empty = direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
+        int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
+        if (direct) {
+            // Freshly created direct byte buffers should be aligned at index 0
+            // for ref and primitive values (see Unsafe.allocateMemory)
+            if (longMisalignmentAtZero != 0)
+                fail("Direct byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        } else {
+            // For heap byte buffers misalignment may occur on 32-bit systems
+            // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
+            // Note the GC will preserve alignment of the base address of the
+            // array
+            if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 != longMisalignmentAtZero)
+                fail("Heap byte buffer misalligned at index 0 for ref and primitive values " + longMisalignmentAtZero);
+        }
+
+        // Ensure test buffer is correctly aligned at index 0
+        if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+            fail("Test input buffer not correctly aligned at index 0", b);
+
+        // Test misalignment values
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int i = 0; i < us * 2; i++) {
+                int am = b.alignmentOffset(i, us);
+                int expectedAm = (longMisalignmentAtZero + i) % us;
+
+                if (am != expectedAm)
+                    fail(String.format("b.alignmentOffset(%d, %d) == %d incorrect, expected %d", i, us, am, expectedAm));
+            }
+        }
+
+        // Created aligned slice to test against
+        int ap = 8 - longMisalignmentAtZero;
+        int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+        ByteBuffer ab = b.position(ap).limit(al).
+                slice();
+        if (ab.limit() == 0)
+            fail("Test input buffer not sufficiently sized to cover an aligned region for all values", b);
+        if (ab.alignmentOffset(0, 8) != 0)
+            fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+        for (int us : new int[]{1, 2, 4, 8}) {
+            for (int p = 1; p < 16; p++) {
+                int l = ab.limit() - p;
+
+                ByteBuffer as = ab.slice().position(p).limit(l).
+                        alignedSlice(us);
+
+                ck(as, 0, as.position());
+                ck(as, as.capacity(), as.limit());
+                if (b.isDirect() != as.isDirect())
+                    fail("Lost direction", as);
+                if (b.isReadOnly() != as.isReadOnly())
+                    fail("Lost read-only", as);
+
+                if (as.alignmentOffset(0, us) != 0)
+                    fail("Buffer not correctly aligned at index 0", as);
+
+                if (as.alignmentOffset(as.limit(), us) != 0)
+                    fail("Buffer not correctly aligned at limit", as);
+
+                int p_mod = ab.alignmentOffset(p, us);
+                int l_mod = ab.alignmentOffset(l, us);
+                // Round up position
+                p = (p_mod > 0) ? p + (us - p_mod) : p;
+                // Round down limit
+                l = l - l_mod;
+
+                int ec = l - p;
+                if (as.limit() != ec)
+                    fail("Buffer capacity incorrect, expected: " + ec, as);
+            }
+        }
+    }
 
 
     private static void fail(String problem,
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+        // Test alignment
+
+        testAlign(b, direct);
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicChar.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicChar.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              CharBuffer xb, CharBuffer yb,
                              char x, char y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicDouble.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              DoubleBuffer xb, DoubleBuffer yb,
                              double x, double y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicFloat.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              FloatBuffer xb, FloatBuffer yb,
                              float x, float y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicInt.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicInt.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              IntBuffer xb, IntBuffer yb,
                              int x, int y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicLong.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicLong.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              LongBuffer xb, LongBuffer yb,
                              long x, long y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }
 
 
--- a/jdk/test/java/nio/Buffer/BasicShort.java	Mon Mar 21 11:21:08 2016 +0100
+++ b/jdk/test/java/nio/Buffer/BasicShort.java	Thu Mar 24 11:21:18 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -338,6 +338,103 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void fail(String problem,
                              ShortBuffer xb, ShortBuffer yb,
                              short x, short y) {
@@ -854,6 +951,11 @@
 
         relPut(b);                       // Required by testViews
 
+
+
+
+
+
     }