This commit is contained in:
Lana Steuck 2018-01-18 18:58:46 +00:00
commit 8f528fba93
608 changed files with 7528 additions and 3300 deletions

View file

@ -27,6 +27,7 @@ package java.io;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Objects;
/**
* This class implements an output stream in which the data is
@ -147,10 +148,7 @@ public class ByteArrayOutputStream extends OutputStream {
* @param len the number of bytes to write.
*/
public synchronized void write(byte b[], int off, int len) {
if ((off < 0) || (off > b.length) || (len < 0) ||
((off + len) - b.length > 0)) {
throw new IndexOutOfBoundsException();
}
Objects.checkFromIndexSize(off, len, b.length);
ensureCapacity(count + len);
System.arraycopy(b, off, buf, count, len);
count += len;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2018, 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
@ -2256,7 +2256,7 @@ public class File
private transient volatile Path filePath;
/**
* Returns a {@link Path java.nio.file.Path} object constructed from the
* Returns a {@link Path java.nio.file.Path} object constructed from
* this abstract path. The resulting {@code Path} is associated with the
* {@link java.nio.file.FileSystems#getDefault default-filesystem}.
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2018, 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,7 +25,9 @@
package java.io;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
@ -53,6 +55,93 @@ public abstract class InputStream implements Closeable {
private static final int DEFAULT_BUFFER_SIZE = 8192;
/**
* Returns a new {@code InputStream} that reads no bytes. The returned
* stream is initially open. The stream is closed by calling the
* {@code close()} method. Subsequent calls to {@code close()} have no
* effect.
*
* <p> While the stream is open, the {@code available()}, {@code read()},
* {@code read(byte[])}, {@code read(byte[], int, int)},
* {@code readAllBytes()}, {@code readNBytes()}, {@code skip()}, and
* {@code transferTo()} methods all behave as if end of stream has been
* reached. After the stream has been closed, these methods all throw
* {@code IOException}.
*
* <p> The {@code markSupported()} method returns {@code false}. The
* {@code mark()} method does nothing, and the {@code reset()} method
* throws {@code IOException}.
*
* @return an {@code InputStream} which contains no bytes
*
* @since 11
*/
public static InputStream nullInputStream() {
return new InputStream() {
private volatile boolean closed;
private void ensureOpen() throws IOException {
if (closed) {
throw new IOException("Stream closed");
}
}
@Override
public int available () throws IOException {
ensureOpen();
return 0;
}
@Override
public int read() throws IOException {
ensureOpen();
return -1;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0) {
return 0;
}
ensureOpen();
return -1;
}
@Override
public byte[] readAllBytes() throws IOException {
ensureOpen();
return new byte[0];
}
@Override
public int readNBytes(byte[] b, int off, int len)
throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
ensureOpen();
return 0;
}
@Override
public long skip(long n) throws IOException {
ensureOpen();
return 0L;
}
@Override
public long transferTo(OutputStream out) throws IOException {
Objects.requireNonNull(out);
ensureOpen();
return 0L;
}
@Override
public void close() throws IOException {
closed = true;
}
};
}
/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an <code>int</code> in the range <code>0</code> to
@ -164,7 +253,6 @@ public abstract class InputStream implements Closeable {
* @see java.io.InputStream#read()
*/
public int read(byte b[], int off, int len) throws IOException {
Objects.requireNonNull(b);
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0) {
return 0;
@ -229,30 +317,55 @@ public abstract class InputStream implements Closeable {
* @since 9
*/
public byte[] readAllBytes() throws IOException {
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int capacity = buf.length;
int nread = 0;
List<byte[]> bufs = null;
byte[] result = null;
int total = 0;
int n;
for (;;) {
// read to EOF which may read more or less than initial buffer size
while ((n = read(buf, nread, capacity - nread)) > 0)
do {
byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
int nread = 0;
// read to EOF which may read more or less than buffer size
while ((n = read(buf, nread, buf.length - nread)) > 0) {
nread += n;
// if the last call to read returned -1, then we're done
if (n < 0)
break;
// need to allocate a larger buffer
if (capacity <= MAX_BUFFER_SIZE - capacity) {
capacity = capacity << 1;
} else {
if (capacity == MAX_BUFFER_SIZE)
throw new OutOfMemoryError("Required array size too large");
capacity = MAX_BUFFER_SIZE;
}
buf = Arrays.copyOf(buf, capacity);
if (nread > 0) {
if (MAX_BUFFER_SIZE - total < nread) {
throw new OutOfMemoryError("Required array size too large");
}
total += nread;
if (result == null) {
result = buf;
} else {
if (bufs == null) {
bufs = new ArrayList<>();
bufs.add(result);
}
bufs.add(buf);
}
}
} while (n >= 0); // if the last call to read returned -1, then break
if (bufs == null) {
if (result == null) {
return new byte[0];
}
return result.length == total ?
result : Arrays.copyOf(result, total);
}
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
result = new byte[total];
int offset = 0;
int remaining = total;
for (byte[] b : bufs) {
int len = Math.min(b.length, remaining);
System.arraycopy(b, 0, result, offset, len);
offset += len;
remaining -= len;
}
return result;
}
/**
@ -299,7 +412,6 @@ public abstract class InputStream implements Closeable {
* @since 9
*/
public int readNBytes(byte[] b, int off, int len) throws IOException {
Objects.requireNonNull(b);
Objects.checkFromIndexSize(off, len, b.length);
int n = 0;

View file

@ -1296,7 +1296,6 @@ public class ObjectInputStream
* @throws InvalidClassException if the filter rejects creation
*/
private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
Objects.requireNonNull(arrayType);
if (! arrayType.isArray()) {
throw new IllegalArgumentException("not an array type");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2018, 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
@ -46,6 +46,51 @@ import java.util.Objects;
* @since 1.0
*/
public abstract class OutputStream implements Closeable, Flushable {
/**
* Returns a new {@code OutputStream} which discards all bytes. The
* returned stream is initially open. The stream is closed by calling
* the {@code close()} method. Subsequent calls to {@code close()} have
* no effect.
*
* <p> While the stream is open, the {@code write(int)}, {@code
* write(byte[])}, and {@code write(byte[], int, int)} methods do nothing.
* After the stream has been closed, these methods all throw {@code
* IOException}.
*
* <p> The {@code flush()} method does nothing.
*
* @return an {@code OutputStream} which discards all bytes
*
* @since 11
*/
public static OutputStream nullOutputStream() {
return new OutputStream() {
private volatile boolean closed;
private void ensureOpen() throws IOException {
if (closed) {
throw new IOException("Stream closed");
}
}
@Override
public void write(int b) throws IOException {
ensureOpen();
}
@Override
public void write(byte b[], int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
ensureOpen();
}
@Override
public void close() {
closed = true;
}
};
}
/**
* Writes the specified byte to this output stream. The general
* contract for <code>write</code> is that one byte is written
@ -106,7 +151,6 @@ public abstract class OutputStream implements Closeable, Flushable {
* stream is closed.
*/
public void write(byte b[], int off, int len) throws IOException {
Objects.requireNonNull(b);
Objects.checkFromIndexSize(off, len, b.length);
// len == 0 condition implicitly handled by loop bounds
for (int i = 0 ; i < len ; i++) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2018, 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
@ -1099,16 +1099,23 @@ public class Runtime {
m.group(VersionPattern.OPT_GROUP));
// empty '+'
if ((m.group(VersionPattern.PLUS_GROUP) != null)
&& !build.isPresent()) {
if (optional.isPresent()) {
if (pre.isPresent())
throw new IllegalArgumentException("'+' found with"
+ " pre-release and optional components:'" + s
+ "'");
if (!build.isPresent()) {
if (m.group(VersionPattern.PLUS_GROUP) != null) {
if (optional.isPresent()) {
if (pre.isPresent())
throw new IllegalArgumentException("'+' found with"
+ " pre-release and optional components:'" + s
+ "'");
} else {
throw new IllegalArgumentException("'+' found with neither"
+ " build or optional components: '" + s + "'");
}
} else {
throw new IllegalArgumentException("'+' found with neither"
+ " build or optional components: '" + s + "'");
if (optional.isPresent() && !pre.isPresent()) {
throw new IllegalArgumentException("optional component"
+ " must be preceeded by a pre-release component"
+ " or '+': '" + s + "'");
}
}
}
return new Version(List.of(version), pre, build, optional);

View file

@ -1667,6 +1667,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
/** Craft a LambdaForm customized for this particular MethodHandle */
/*non-public*/
void customize() {
final LambdaForm form = this.form;
if (form.customized == null) {
LambdaForm newForm = form.customize(this);
updateForm(newForm);

View file

@ -3766,6 +3766,7 @@ assertEquals("xy", h3.invoke("x", "y", 1, "a", "b", "c"));
* specified in the elements of the {@code filters} array.
* The first element of the filter array corresponds to the {@code pos}
* argument of the target, and so on in sequence.
* The filter functions are invoked in left to right order.
* <p>
* Null arguments in the array are treated as identity functions,
* and the corresponding arguments left unchanged.
@ -3836,11 +3837,12 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
filterArgumentsCheckArity(target, pos, filters);
MethodHandle adapter = target;
int curPos = pos-1; // pre-incremented
for (MethodHandle filter : filters) {
curPos += 1;
// process filters in reverse order so that the invocation of
// the resulting adapter will invoke the filters in left-to-right order
for (int i = filters.length - 1; i >= 0; --i) {
MethodHandle filter = filters[i];
if (filter == null) continue; // ignore null elements of filters
adapter = filterArgument(adapter, curPos, filter);
adapter = filterArgument(adapter, pos + i, filter);
}
return adapter;
}

View file

@ -2521,7 +2521,7 @@ public class ModuleDescriptor
* the {@code packageFinder} throws an {@link UncheckedIOException} then
* {@link IOException} cause will be re-thrown. </p>
*
* <p> The module descriptor is read from the buffer stating at index
* <p> The module descriptor is read from the buffer starting at index
* {@code p}, where {@code p} is the buffer's {@link ByteBuffer#position()
* position} when this method is invoked. Upon return the buffer's position
* will be equal to {@code p + n} where {@code n} is the number of bytes

View file

@ -140,14 +140,6 @@ public abstract class Reference<T> {
}
}
/*
* system property to disable clearing before enqueuing.
*/
private static final class ClearBeforeEnqueue {
static final boolean DISABLE =
Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue");
}
/*
* Atomically get and clear (set to null) the VM's pending list.
*/
@ -299,8 +291,7 @@ public abstract class Reference<T> {
* it was not registered with a queue when it was created
*/
public boolean enqueue() {
if (!ClearBeforeEnqueue.DISABLE)
this.referent = null;
this.referent = null;
return this.queue.enqueue(this);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, 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
@ -317,10 +317,9 @@ public class InetSocketAddress
}
/**
*
* Gets the {@code InetAddress}.
*
* @return the InetAdress or {@code null} if it is unresolved.
* @return the InetAddress or {@code null} if it is unresolved.
*/
public final InetAddress getAddress() {
return holder.getAddress();

View file

@ -63,38 +63,38 @@ class Bits { // package-private
// -- Unsafe access --
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
static Unsafe unsafe() {
return unsafe;
return UNSAFE;
}
// -- Processor and memory-system properties --
private static final ByteOrder byteOrder
= unsafe.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
private static final ByteOrder BYTE_ORDER
= UNSAFE.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
static ByteOrder byteOrder() {
return byteOrder;
return BYTE_ORDER;
}
private static int pageSize = -1;
private static int PAGE_SIZE = -1;
static int pageSize() {
if (pageSize == -1)
pageSize = unsafe().pageSize();
return pageSize;
if (PAGE_SIZE == -1)
PAGE_SIZE = unsafe().pageSize();
return PAGE_SIZE;
}
static int pageCount(long size) {
return (int)(size + (long)pageSize() - 1L) / pageSize();
}
private static boolean unaligned = unsafe.unalignedAccess();
private static boolean UNALIGNED = UNSAFE.unalignedAccess();
static boolean unaligned() {
return unaligned;
return UNALIGNED;
}
@ -103,11 +103,11 @@ class Bits { // package-private
// A user-settable upper limit on the maximum amount of allocatable
// direct buffer memory. This value may be changed during VM
// initialization if it is launched with "-XX:MaxDirectMemorySize=<size>".
private static volatile long maxMemory = VM.maxDirectMemory();
private static final AtomicLong reservedMemory = new AtomicLong();
private static final AtomicLong totalCapacity = new AtomicLong();
private static final AtomicLong count = new AtomicLong();
private static volatile boolean memoryLimitSet;
private static volatile long MAX_MEMORY = VM.maxDirectMemory();
private static final AtomicLong RESERVED_MEMORY = new AtomicLong();
private static final AtomicLong TOTAL_CAPACITY = new AtomicLong();
private static final AtomicLong COUNT = new AtomicLong();
private static volatile boolean MEMORY_LIMIT_SET;
// max. number of sleeps during try-reserving with exponentially
// increasing delay before throwing OutOfMemoryError:
@ -120,9 +120,9 @@ class Bits { // package-private
// which a process may access. All sizes are specified in bytes.
static void reserveMemory(long size, int cap) {
if (!memoryLimitSet && VM.initLevel() >= 1) {
maxMemory = VM.maxDirectMemory();
memoryLimitSet = true;
if (!MEMORY_LIMIT_SET && VM.initLevel() >= 1) {
MAX_MEMORY = VM.maxDirectMemory();
MEMORY_LIMIT_SET = true;
}
// optimist!
@ -200,10 +200,10 @@ class Bits { // package-private
// actual memory usage, which will differ when buffers are page
// aligned.
long totalCap;
while (cap <= maxMemory - (totalCap = totalCapacity.get())) {
if (totalCapacity.compareAndSet(totalCap, totalCap + cap)) {
reservedMemory.addAndGet(size);
count.incrementAndGet();
while (cap <= MAX_MEMORY - (totalCap = TOTAL_CAPACITY.get())) {
if (TOTAL_CAPACITY.compareAndSet(totalCap, totalCap + cap)) {
RESERVED_MEMORY.addAndGet(size);
COUNT.incrementAndGet();
return true;
}
}
@ -213,9 +213,9 @@ class Bits { // package-private
static void unreserveMemory(long size, int cap) {
long cnt = count.decrementAndGet();
long reservedMem = reservedMemory.addAndGet(-size);
long totalCap = totalCapacity.addAndGet(-cap);
long cnt = COUNT.decrementAndGet();
long reservedMem = RESERVED_MEMORY.addAndGet(-size);
long totalCap = TOTAL_CAPACITY.addAndGet(-cap);
assert cnt >= 0 && reservedMem >= 0 && totalCap >= 0;
}
@ -234,15 +234,15 @@ class Bits { // package-private
}
@Override
public long getCount() {
return Bits.count.get();
return Bits.COUNT.get();
}
@Override
public long getTotalCapacity() {
return Bits.totalCapacity.get();
return Bits.TOTAL_CAPACITY.get();
}
@Override
public long getMemoryUsed() {
return Bits.reservedMemory.get();
return Bits.RESERVED_MEMORY.get();
}
};
}

View file

@ -26,6 +26,7 @@
package java.nio;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.Unsafe;
import java.util.Spliterator;
@ -181,6 +182,8 @@ import java.util.Spliterator;
*/
public abstract class Buffer {
// Cached unsafe-access object
static final Unsafe UNSAFE = Bits.unsafe();
/**
* The characteristics of Spliterators that traverse and split elements
@ -616,6 +619,14 @@ public abstract class Buffer {
// -- Package-private methods for bounds checking, etc. --
/**
*
* @return the base reference, paired with the address
* field, which in combination can be used for unsafe access into a heap
* buffer or direct byte buffer (and views of).
*/
abstract Object base();
/**
* Checks the current position against the limit, throwing a {@link
* BufferUnderflowException} if it is not smaller than the limit, and then

View file

@ -0,0 +1,198 @@
/*
* Copyright (c) 2017, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.nio;
import jdk.internal.util.ArraysSupport;
/**
* Mismatch methods for buffers
*/
final class BufferMismatch {
static int mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length) {
int i = 0;
if (length > 7) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + aOff,
b.base(), b.address + bOff,
length,
ArraysSupport.LOG2_ARRAY_BYTE_INDEX_SCALE);
if (i >= 0) return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a.get(aOff + i) != b.get(bOff + i))
return i;
}
return -1;
}
static int mismatch(CharBuffer a, int aOff, CharBuffer b, int bOff, int length) {
int i = 0;
// Ensure only heap or off-heap buffer instances use the
// vectorized mismatch. If either buffer is a StringCharBuffer
// (order is null) then the slow path is taken
if (length > 3 && a.charRegionOrder() == b.charRegionOrder()
&& a.charRegionOrder() != null && b.charRegionOrder() != null) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE);
if (i >= 0) return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a.get(aOff + i) != b.get(bOff + i))
return i;
}
return -1;
}
static int mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length) {
int i = 0;
if (length > 3 && a.order() == b.order()) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE);
if (i >= 0) return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a.get(aOff + i) != b.get(bOff + i))
return i;
}
return -1;
}
static int mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length) {
int i = 0;
if (length > 1 && a.order() == b.order()) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE);
if (i >= 0) return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a.get(aOff + i) != b.get(bOff + i))
return i;
}
return -1;
}
static int mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length) {
int i = 0;
if (length > 1 && a.order() == b.order()) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE);
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values; and
// is not associated with +0 and -0
float av = a.get(aOff + i);
float bv = b.get(bOff + i);
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
return i;
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
}
// Matched
else {
i = length - ~i;
}
}
for (; i < length; i++) {
float av = a.get(aOff + i);
float bv = b.get(bOff + i);
if (av != bv && (!Float.isNaN(av) || !Float.isNaN(bv)))
return i;
}
return -1;
}
static int mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length) {
int i = 0;
if (length > 0 && a.order() == b.order()) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE);
return i >= 0 ? i : -1;
}
for (; i < length; i++) {
if (a.get(aOff + i) != b.get(bOff + i))
return i;
}
return -1;
}
static int mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length) {
int i = 0;
if (length > 0 && a.order() == b.order()) {
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
length,
ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE);
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values; and
// is not associated with +0 and -0
double av = a.get(aOff + i);
double bv = b.get(bOff + i);
if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
return i;
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
}
// Matched
else {
return -1;
}
}
for (; i < length; i++) {
double av = a.get(aOff + i);
double bv = b.get(bOff + i);
if (av != bv && (!Double.isNaN(av) || !Double.isNaN(bv)))
return i;
}
return -1;
}
}

View file

@ -36,9 +36,6 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
#if[rw]
// Cached unsafe-access object
private static final Unsafe unsafe = Bits.unsafe();
protected final ByteBuffer bb;
#end[rw]
@ -74,6 +71,11 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
#end[rw]
}
@Override
Object base() {
return bb.hb;
}
public $Type$Buffer slice() {
int pos = this.position();
int lim = this.limit();
@ -117,20 +119,20 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
}
public $type$ get() {
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()),
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(nextGetIndex()),
{#if[boB]?true:false});
return $fromBits$(x);
}
public $type$ get(int i) {
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)),
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)),
{#if[boB]?true:false});
return $fromBits$(x);
}
#if[streamableType]
$type$ getUnchecked(int i) {
$memtype$ x = unsafe.get$Memtype$Unaligned(bb.hb, byteOffset(i),
$memtype$ x = UNSAFE.get$Memtype$Unaligned(bb.hb, byteOffset(i),
{#if[boB]?true:false});
return $fromBits$(x);
}
@ -141,7 +143,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
public $Type$Buffer put($type$ x) {
#if[rw]
$memtype$ y = $toBits$(x);
unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y,
UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(nextPutIndex()), y,
{#if[boB]?true:false});
return this;
#else[rw]
@ -152,7 +154,7 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
public $Type$Buffer put(int i, $type$ x) {
#if[rw]
$memtype$ y = $toBits$(x);
unsafe.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y,
UNSAFE.put$Memtype$Unaligned(bb.hb, byteOffset(checkIndex(i)), y,
{#if[boB]?true:false});
return this;
#else[rw]
@ -241,4 +243,9 @@ class ByteBufferAs$Type$Buffer$RW$$BO$ // package-private
#end[boL]
}
#if[char]
ByteOrder charRegionOrder() {
return order();
}
#end[char]
}

View file

@ -32,7 +32,7 @@ class XXX {
#if[rw]
private $type$ get$Type$(long a) {
$memtype$ x = unsafe.get$Memtype$Unaligned(null, a, bigEndian);
$memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian);
return $fromBits$(x);
}
@ -49,7 +49,7 @@ class XXX {
private ByteBuffer put$Type$(long a, $type$ x) {
#if[rw]
$memtype$ y = $toBits$(x);
unsafe.put$Memtype$Unaligned(null, a, y, bigEndian);
UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -81,7 +81,7 @@ class XXX {
int rem = (off <= lim ? lim - off : 0);
int size = rem >> $LG_BYTES_PER_VALUE$;
if (!unaligned && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
if (!UNALIGNED && ((address + off) % $BYTES_PER_VALUE$ != 0)) {
return (bigEndian
? ($Type$Buffer)(new ByteBufferAs$Type$Buffer$RW$B(this,
-1,

View file

@ -28,7 +28,6 @@
package java.nio;
import java.io.FileDescriptor;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.ref.Cleaner;
import sun.nio.ch.DirectBuffer;
@ -45,14 +44,11 @@ class Direct$Type$Buffer$RW$$BO$
#if[rw]
// Cached unsafe-access object
protected static final Unsafe unsafe = Bits.unsafe();
// Cached array base offset
private static final long arrayBaseOffset = (long)unsafe.arrayBaseOffset($type$[].class);
private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
// Cached unaligned-access capability
protected static final boolean unaligned = Bits.unaligned();
protected static final boolean UNALIGNED = Bits.unaligned();
// Base address, used in all indexing calculations
// NOTE: moved up to Buffer.java for speed in JNI GetDirectBufferAddress
@ -73,8 +69,6 @@ class Direct$Type$Buffer$RW$$BO$
implements Runnable
{
private static Unsafe unsafe = Unsafe.getUnsafe();
private long address;
private long size;
private int capacity;
@ -91,7 +85,7 @@ class Direct$Type$Buffer$RW$$BO$
// Paranoia
return;
}
unsafe.freeMemory(address);
UNSAFE.freeMemory(address);
address = 0;
Bits.unreserveMemory(size, capacity);
}
@ -124,12 +118,12 @@ class Direct$Type$Buffer$RW$$BO$
long base = 0;
try {
base = unsafe.allocateMemory(size);
base = UNSAFE.allocateMemory(size);
} catch (OutOfMemoryError x) {
Bits.unreserveMemory(size, cap);
throw x;
}
unsafe.setMemory(base, size, (byte) 0);
UNSAFE.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {
// Round up to page boundary
address = base + ps - (base & (ps - 1));
@ -206,6 +200,11 @@ class Direct$Type$Buffer$RW$$BO$
#end[rw]
}
@Override
Object base() {
return null;
}
public $Type$Buffer slice() {
int pos = this.position();
int lim = this.limit();
@ -258,16 +257,16 @@ class Direct$Type$Buffer$RW$$BO$
}
public $type$ get() {
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(nextGetIndex()))));
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
}
public $type$ get(int i) {
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(checkIndex(i)))));
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
}
#if[streamableType]
$type$ getUnchecked(int i) {
return $fromBits$($swap$(unsafe.get$Swaptype$(ix(i))));
return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
}
#end[streamableType]
@ -282,10 +281,10 @@ class Direct$Type$Buffer$RW$$BO$
if (length > rem)
throw new BufferUnderflowException();
long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
unsafe.copySwapMemory(null,
UNSAFE.copySwapMemory(null,
ix(pos),
dst,
dstOffset,
@ -293,7 +292,7 @@ class Direct$Type$Buffer$RW$$BO$
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
unsafe.copyMemory(null,
UNSAFE.copyMemory(null,
ix(pos),
dst,
dstOffset,
@ -312,7 +311,7 @@ class Direct$Type$Buffer$RW$$BO$
public $Type$Buffer put($type$ x) {
#if[rw]
unsafe.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -321,7 +320,7 @@ class Direct$Type$Buffer$RW$$BO$
public $Type$Buffer put(int i, $type$ x) {
#if[rw]
unsafe.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -347,7 +346,7 @@ class Direct$Type$Buffer$RW$$BO$
if (srem > rem)
throw new BufferOverflowException();
unsafe.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
sb.position(spos + srem);
position(pos + srem);
} else if (src.hb != null) {
@ -380,10 +379,10 @@ class Direct$Type$Buffer$RW$$BO$
if (length > rem)
throw new BufferOverflowException();
long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$);
long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
#if[!byte]
if (order() != ByteOrder.nativeOrder())
unsafe.copySwapMemory(src,
UNSAFE.copySwapMemory(src,
srcOffset,
null,
ix(pos),
@ -391,7 +390,7 @@ class Direct$Type$Buffer$RW$$BO$
(long)1 << $LG_BYTES_PER_VALUE$);
else
#end[!byte]
unsafe.copyMemory(src,
UNSAFE.copyMemory(src,
srcOffset,
null,
ix(pos),
@ -413,7 +412,7 @@ class Direct$Type$Buffer$RW$$BO$
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
unsafe.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
position(rem);
limit(capacity());
discardMark();
@ -490,17 +489,22 @@ class Direct$Type$Buffer$RW$$BO$
#end[!byte]
#if[char]
ByteOrder charRegionOrder() {
return order();
}
#end[char]
#if[byte]
byte _get(int i) { // package-private
return unsafe.getByte(address + i);
return UNSAFE.getByte(address + i);
}
void _put(int i, byte b) { // package-private
#if[rw]
unsafe.putByte(address + i, b);
UNSAFE.putByte(address + i, b);
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]

View file

@ -27,8 +27,6 @@
package java.nio;
import jdk.internal.misc.Unsafe;
/**
#if[rw]
* A read/write Heap$Type$Buffer.
@ -43,6 +41,11 @@ import jdk.internal.misc.Unsafe;
class Heap$Type$Buffer$RW$
extends {#if[ro]?Heap}$Type$Buffer
{
// Cached array base offset
private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class);
// Cached array base offset
private static final long ARRAY_INDEX_SCALE = UNSAFE.arrayIndexScale($type$[].class);
// For speed these fields are actually declared in X-Buffer;
// these declarations are here as documentation
@ -53,16 +56,6 @@ class Heap$Type$Buffer$RW$
#end[rw]
*/
#if[byte]
// Cached unsafe-access object
private static final Unsafe unsafe = Bits.unsafe();
// Cached array base offset
private static final long arrayBaseOffset = unsafe.arrayBaseOffset($type$[].class);
#end[byte]
Heap$Type$Buffer$RW$(int cap, int lim) { // package-private
#if[rw]
super(-1, 0, lim, cap, new $type$[cap], 0);
@ -70,13 +63,11 @@ class Heap$Type$Buffer$RW$
hb = new $type$[cap];
offset = 0;
*/
this.address = ARRAY_BASE_OFFSET;
#else[rw]
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
@ -86,13 +77,11 @@ class Heap$Type$Buffer$RW$
hb = buf;
offset = 0;
*/
this.address = ARRAY_BASE_OFFSET;
#else[rw]
super(buf, off, len);
this.isReadOnly = true;
#end[rw]
#if[byte]
this.address = arrayBaseOffset;
#end[byte]
}
protected Heap$Type$Buffer$RW$($type$[] buf,
@ -105,13 +94,11 @@ class Heap$Type$Buffer$RW$
hb = buf;
offset = off;
*/
this.address = ARRAY_BASE_OFFSET + off * ARRAY_INDEX_SCALE;
#else[rw]
super(buf, mark, pos, lim, cap, off);
this.isReadOnly = true;
#end[rw]
#if[byte]
this.address = arrayBaseOffset + off;
#end[byte]
}
public $Type$Buffer slice() {
@ -296,18 +283,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public char getChar() {
return unsafe.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
return UNSAFE.getCharUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
}
public char getChar(int i) {
return unsafe.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
return UNSAFE.getCharUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
}
#end[rw]
public $Type$Buffer putChar(char x) {
#if[rw]
unsafe.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
UNSAFE.putCharUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -316,7 +303,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putChar(int i, char x) {
#if[rw]
unsafe.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
UNSAFE.putCharUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -347,18 +334,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public short getShort() {
return unsafe.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
return UNSAFE.getShortUnaligned(hb, byteOffset(nextGetIndex(2)), bigEndian);
}
public short getShort(int i) {
return unsafe.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
return UNSAFE.getShortUnaligned(hb, byteOffset(checkIndex(i, 2)), bigEndian);
}
#end[rw]
public $Type$Buffer putShort(short x) {
#if[rw]
unsafe.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
UNSAFE.putShortUnaligned(hb, byteOffset(nextPutIndex(2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -367,7 +354,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putShort(int i, short x) {
#if[rw]
unsafe.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
UNSAFE.putShortUnaligned(hb, byteOffset(checkIndex(i, 2)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -398,18 +385,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public int getInt() {
return unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
return UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
}
public int getInt(int i) {
return unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
return UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
}
#end[rw]
public $Type$Buffer putInt(int x) {
#if[rw]
unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -418,7 +405,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putInt(int i, int x) {
#if[rw]
unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -449,18 +436,18 @@ class Heap$Type$Buffer$RW$
#if[rw]
public long getLong() {
return unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
return UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
}
public long getLong(int i) {
return unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
return UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
}
#end[rw]
public $Type$Buffer putLong(long x) {
#if[rw]
unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -469,7 +456,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putLong(int i, long x) {
#if[rw]
unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), x, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -500,12 +487,12 @@ class Heap$Type$Buffer$RW$
#if[rw]
public float getFloat() {
int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
int x = UNSAFE.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
return Float.intBitsToFloat(x);
}
public float getFloat(int i) {
int x = unsafe.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
int x = UNSAFE.getIntUnaligned(hb, byteOffset(checkIndex(i, 4)), bigEndian);
return Float.intBitsToFloat(x);
}
@ -514,7 +501,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putFloat(float x) {
#if[rw]
int y = Float.floatToRawIntBits(x);
unsafe.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
UNSAFE.putIntUnaligned(hb, byteOffset(nextPutIndex(4)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -524,7 +511,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putFloat(int i, float x) {
#if[rw]
int y = Float.floatToRawIntBits(x);
unsafe.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
UNSAFE.putIntUnaligned(hb, byteOffset(checkIndex(i, 4)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -555,12 +542,12 @@ class Heap$Type$Buffer$RW$
#if[rw]
public double getDouble() {
long x = unsafe.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
long x = UNSAFE.getLongUnaligned(hb, byteOffset(nextGetIndex(8)), bigEndian);
return Double.longBitsToDouble(x);
}
public double getDouble(int i) {
long x = unsafe.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
long x = UNSAFE.getLongUnaligned(hb, byteOffset(checkIndex(i, 8)), bigEndian);
return Double.longBitsToDouble(x);
}
@ -569,7 +556,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putDouble(double x) {
#if[rw]
long y = Double.doubleToRawLongBits(x);
unsafe.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
UNSAFE.putLongUnaligned(hb, byteOffset(nextPutIndex(8)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -579,7 +566,7 @@ class Heap$Type$Buffer$RW$
public $Type$Buffer putDouble(int i, double x) {
#if[rw]
long y = Double.doubleToRawLongBits(x);
unsafe.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
UNSAFE.putLongUnaligned(hb, byteOffset(checkIndex(i, 8)), y, bigEndian);
return this;
#else[rw]
throw new ReadOnlyBufferException();
@ -643,7 +630,11 @@ class Heap$Type$Buffer$RW$
public ByteOrder order() {
return ByteOrder.nativeOrder();
}
#end[!byte]
#if[char]
ByteOrder charRegionOrder() {
return order();
}
#end[char]
}

View file

@ -127,4 +127,30 @@ class StringCharBuffer // package-private
return ByteOrder.nativeOrder();
}
ByteOrder charRegionOrder() {
return null;
}
public boolean equals(Object ob) {
if (this == ob)
return true;
if (!(ob instanceof CharBuffer))
return false;
CharBuffer that = (CharBuffer)ob;
if (this.remaining() != that.remaining())
return false;
return BufferMismatch.mismatch(this, this.position(),
that, that.position(),
this.remaining()) < 0;
}
public int compareTo(CharBuffer that) {
int i = BufferMismatch.mismatch(this, this.position(),
that, that.position(),
Math.min(this.remaining(), that.remaining()));
if (i >= 0) {
return Character.compare(this.get(this.position() + i), that.get(this.position() + i));
}
return this.remaining() - that.remaining();
}
}

View file

@ -36,6 +36,8 @@ import java.util.stream.StreamSupport;
import java.util.stream.$Streamtype$Stream;
#end[streamableType]
import jdk.internal.util.ArraysSupport;
/**
* $A$ $type$ buffer.
*
@ -287,6 +289,11 @@ public abstract class $Type$Buffer
this(mark, pos, lim, cap, null, 0);
}
@Override
Object base() {
return hb;
}
#if[byte]
/**
@ -1297,19 +1304,9 @@ public abstract class $Type$Buffer
$Type$Buffer that = ($Type$Buffer)ob;
if (this.remaining() != that.remaining())
return false;
int p = this.position();
for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
if (!equals(this.get(i), that.get(j)))
return false;
return true;
}
private static boolean equals($type$ x, $type$ y) {
#if[floatingPointType]
return (x == y) || ($Fulltype$.isNaN(x) && $Fulltype$.isNaN(y));
#else[floatingPointType]
return x == y;
#end[floatingPointType]
return BufferMismatch.mismatch(this, this.position(),
that, that.position(),
this.remaining()) < 0;
}
/**
@ -1336,11 +1333,11 @@ public abstract class $Type$Buffer
* is less than, equal to, or greater than the given buffer
*/
public int compareTo($Type$Buffer that) {
int n = this.position() + Math.min(this.remaining(), that.remaining());
for (int i = this.position(), j = that.position(); i < n; i++, j++) {
int cmp = compare(this.get(i), that.get(j));
if (cmp != 0)
return cmp;
int i = BufferMismatch.mismatch(this, this.position(),
that, that.position(),
Math.min(this.remaining(), that.remaining()));
if (i >= 0) {
return compare(this.get(this.position() + i), that.get(this.position() + i));
}
return this.remaining() - that.remaining();
}
@ -1571,6 +1568,12 @@ public abstract class $Type$Buffer
#end[!byte]
#if[char]
// The order or null if the buffer does not cover a memory region,
// such as StringCharBuffer
abstract ByteOrder charRegionOrder();
#end[char]
#if[byte]
boolean bigEndian // package-private

View file

@ -2954,22 +2954,6 @@ public final class Files {
return newBufferedWriter(path, StandardCharsets.UTF_8, options);
}
/**
* Reads all bytes from an input stream and writes them to an output stream.
*/
private static long copy(InputStream source, OutputStream sink)
throws IOException
{
long nread = 0L;
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = source.read(buf)) > 0) {
sink.write(buf, 0, n);
nread += n;
}
return nread;
}
/**
* Copies all bytes from an input stream to a file. On return, the input
* stream will be at end of stream.
@ -3082,7 +3066,7 @@ public final class Files {
// do the copy
try (OutputStream out = ostream) {
return copy(in, out);
return in.transferTo(out);
}
}
@ -3124,7 +3108,7 @@ public final class Files {
Objects.requireNonNull(out);
try (InputStream in = newInputStream(source)) {
return copy(in, out);
return in.transferTo(out);
}
}

View file

@ -1550,7 +1550,6 @@ public class ArrayList<E> extends AbstractList<E>
setBit(deathRow, i - beg);
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
expectedModCount++;
modCount++;
int w = beg;
for (i = beg; i < end; i++)

View file

@ -26,6 +26,7 @@
package java.util;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.util.ArraysSupport;
import java.lang.reflect.Array;
import java.util.concurrent.ForkJoinPool;

View file

@ -1,545 +0,0 @@
/*
* Copyright (c) 2015, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.Unsafe;
/**
* Utility methods to find a mismatch between two primitive arrays.
*
* <p>Array equality and lexicographical comparison can be built on top of
* array mismatch functionality.
*
* <p>The mismatch method implementation, {@link #vectorizedMismatch}, leverages
* vector-based techniques to access and compare the contents of two arrays.
* The Java implementation uses {@code Unsafe.getLongUnaligned} to access the
* content of an array, thus access is supported on platforms that do not
* support unaligned access. For a byte[] array, 8 bytes (64 bits) can be
* accessed and compared as a unit rather than individually, which increases
* the performance when the method is compiled by the HotSpot VM. On supported
* platforms the mismatch implementation is intrinsified to leverage SIMD
* instructions. So for a byte[] array, 16 bytes (128 bits), 32 bytes
* (256 bits), and perhaps in the future even 64 bytes (512 bits), platform
* permitting, can be accessed and compared as a unit, which further increases
* the performance over the Java implementation.
*
* <p>None of the mismatch methods perform array bounds checks. It is the
* responsibility of the caller (direct or otherwise) to perform such checks
* before calling this method.
*/
class ArraysSupport {
static final Unsafe U = Unsafe.getUnsafe();
private static final boolean BIG_ENDIAN = U.isBigEndian();
private static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE);
private static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE);
private static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE);
private static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE);
private static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE);
private static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE);
private static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE);
private static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE);
private static int exactLog2(int scale) {
if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
return Integer.numberOfTrailingZeros(scale);
}
private ArraysSupport() {}
/**
* Find the relative index of the first mismatching pair of elements in two
* primitive arrays of the same component type. Pairs of elements will be
* tested in order relative to given offsets into both arrays.
*
* <p>This method does not perform type checks or bounds checks. It is the
* responsibility of the caller to perform such checks before calling this
* method.
*
* <p>The given offsets, in bytes, need not be aligned according to the
* given log<sub>2</sub> size the array elements. More specifically, an
* offset modulus the size need not be zero.
*
* @param a the first array to be tested for mismatch, or {@code null} for
* direct memory access
* @param aOffset the relative offset, in bytes, from the base address of
* the first array to test from, otherwise if the first array is
* {@code null}, an absolute address pointing to the first element to test.
* @param b the second array to be tested for mismatch, or {@code null} for
* direct memory access
* @param bOffset the relative offset, in bytes, from the base address of
* the second array to test from, otherwise if the second array is
* {@code null}, an absolute address pointing to the first element to test.
* @param length the number of array elements to test
* @param log2ArrayIndexScale log<sub>2</sub> of the array index scale, that
* corresponds to the size, in bytes, of an array element.
* @return if a mismatch is found a relative index, between 0 (inclusive)
* and {@code length} (exclusive), of the first mismatching pair of elements
* in the two arrays. Otherwise, if a mismatch is not found the bitwise
* compliment of the number of remaining pairs of elements to be checked in
* the tail of the two arrays.
*/
@HotSpotIntrinsicCandidate
static int vectorizedMismatch(Object a, long aOffset,
Object b, long bOffset,
int length,
int log2ArrayIndexScale) {
// assert a.getClass().isArray();
// assert b.getClass().isArray();
// assert 0 <= length <= sizeOf(a)
// assert 0 <= length <= sizeOf(b)
// assert 0 <= log2ArrayIndexScale <= 3
int log2ValuesPerWidth = LOG2_ARRAY_LONG_INDEX_SCALE - log2ArrayIndexScale;
int wi = 0;
for (; wi < length >> log2ValuesPerWidth; wi++) {
long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
long av = U.getLongUnaligned(a, aOffset + bi);
long bv = U.getLongUnaligned(b, bOffset + bi);
if (av != bv) {
long x = av ^ bv;
int o = BIG_ENDIAN
? Long.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
: Long.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
return (wi << log2ValuesPerWidth) + o;
}
}
// Calculate the tail of remaining elements to check
int tail = length - (wi << log2ValuesPerWidth);
if (log2ArrayIndexScale < LOG2_ARRAY_INT_INDEX_SCALE) {
int wordTail = 1 << (LOG2_ARRAY_INT_INDEX_SCALE - log2ArrayIndexScale);
// Handle 4 bytes or 2 chars in the tail using int width
if (tail >= wordTail) {
long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE;
int av = U.getIntUnaligned(a, aOffset + bi);
int bv = U.getIntUnaligned(b, bOffset + bi);
if (av != bv) {
int x = av ^ bv;
int o = BIG_ENDIAN
? Integer.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale)
: Integer.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale);
return (wi << log2ValuesPerWidth) + o;
}
tail -= wordTail;
}
return ~tail;
}
else {
return ~tail;
}
}
// Booleans
// Each boolean element takes up one byte
static int mismatch(boolean[] a,
boolean[] b,
int length) {
int i = 0;
if (length > 7) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(boolean[] a, int aFromIndex,
boolean[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 7) {
int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Bytes
/**
* Find the index of a mismatch between two arrays.
*
* <p>This method does not perform bounds checks. It is the responsibility
* of the caller to perform such bounds checks before calling this method.
*
* @param a the first array to be tested for a mismatch
* @param b the second array to be tested for a mismatch
* @param length the number of bytes from each array to check
* @return the index of a mismatch between the two arrays, otherwise -1 if
* no mismatch. The index will be within the range of (inclusive) 0 to
* (exclusive) the smaller of the two array lengths.
*/
static int mismatch(byte[] a,
byte[] b,
int length) {
// ISSUE: defer to index receiving methods if performance is good
// assert length <= a.length
// assert length <= b.length
int i = 0;
if (length > 7) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_BYTE_BASE_OFFSET,
b, Unsafe.ARRAY_BYTE_BASE_OFFSET,
length, LOG2_ARRAY_BYTE_INDEX_SCALE);
if (i >= 0)
return i;
// Align to tail
i = length - ~i;
// assert i >= 0 && i <= 7;
}
// Tail < 8 bytes
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
/**
* Find the relative index of a mismatch between two arrays starting from
* given indexes.
*
* <p>This method does not perform bounds checks. It is the responsibility
* of the caller to perform such bounds checks before calling this method.
*
* @param a the first array to be tested for a mismatch
* @param aFromIndex the index of the first element (inclusive) in the first
* array to be compared
* @param b the second array to be tested for a mismatch
* @param bFromIndex the index of the first element (inclusive) in the
* second array to be compared
* @param length the number of bytes from each array to check
* @return the relative index of a mismatch between the two arrays,
* otherwise -1 if no mismatch. The index will be within the range of
* (inclusive) 0 to (exclusive) the smaller of the two array bounds.
*/
static int mismatch(byte[] a, int aFromIndex,
byte[] b, int bFromIndex,
int length) {
// assert 0 <= aFromIndex < a.length
// assert 0 <= aFromIndex + length <= a.length
// assert 0 <= bFromIndex < b.length
// assert 0 <= bFromIndex + length <= b.length
// assert length >= 0
int i = 0;
if (length > 7) {
int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_BYTE_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Chars
static int mismatch(char[] a,
char[] b,
int length) {
int i = 0;
if (length > 3) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_CHAR_BASE_OFFSET,
b, Unsafe.ARRAY_CHAR_BASE_OFFSET,
length, LOG2_ARRAY_CHAR_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(char[] a, int aFromIndex,
char[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 3) {
int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_CHAR_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Shorts
static int mismatch(short[] a,
short[] b,
int length) {
int i = 0;
if (length > 3) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_SHORT_BASE_OFFSET,
b, Unsafe.ARRAY_SHORT_BASE_OFFSET,
length, LOG2_ARRAY_SHORT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(short[] a, int aFromIndex,
short[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 3) {
int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_SHORT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Ints
static int mismatch(int[] a,
int[] b,
int length) {
int i = 0;
if (length > 1) {
i = vectorizedMismatch(
a, Unsafe.ARRAY_INT_BASE_OFFSET,
b, Unsafe.ARRAY_INT_BASE_OFFSET,
length, LOG2_ARRAY_INT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[i] != b[i])
return i;
}
return -1;
}
static int mismatch(int[] a, int aFromIndex,
int[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 1) {
int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_INT_INDEX_SCALE);
if (i >= 0)
return i;
i = length - ~i;
}
for (; i < length; i++) {
if (a[aFromIndex + i] != b[bFromIndex + i])
return i;
}
return -1;
}
// Floats
static int mismatch(float[] a,
float[] b,
int length) {
return mismatch(a, 0, b, 0, length);
}
static int mismatch(float[] a, int aFromIndex,
float[] b, int bFromIndex,
int length) {
int i = 0;
if (length > 1) {
int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
if (!Float.isNaN(a[aFromIndex + i]) || !Float.isNaN(b[bFromIndex + i]))
return i;
// Mismatch on two different NaN values that are normalized to match
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
}
// Matched
else {
i = length - ~i;
}
}
for (; i < length; i++) {
if (Float.floatToIntBits(a[aFromIndex + i]) != Float.floatToIntBits(b[bFromIndex + i]))
return i;
}
return -1;
}
// 64 bit sizes
// Long
static int mismatch(long[] a,
long[] b,
int length) {
if (length == 0) {
return -1;
}
int i = vectorizedMismatch(
a, Unsafe.ARRAY_LONG_BASE_OFFSET,
b, Unsafe.ARRAY_LONG_BASE_OFFSET,
length, LOG2_ARRAY_LONG_INDEX_SCALE);
return i >= 0 ? i : -1;
}
static int mismatch(long[] a, int aFromIndex,
long[] b, int bFromIndex,
int length) {
if (length == 0) {
return -1;
}
int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_LONG_INDEX_SCALE);
return i >= 0 ? i : -1;
}
// Double
static int mismatch(double[] a,
double[] b,
int length) {
return mismatch(a, 0, b, 0, length);
}
static int mismatch(double[] a, int aFromIndex,
double[] b, int bFromIndex,
int length) {
if (length == 0) {
return -1;
}
int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
int i = vectorizedMismatch(
a, aOffset,
b, bOffset,
length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i]))
return i;
// Mismatch on two different NaN values that are normalized to match
// Fall back to slow mechanism
// ISSUE: Consider looping over vectorizedMismatch adjusting ranges
// However, requires that returned value be relative to input ranges
i++;
for (; i < length; i++) {
if (Double.doubleToLongBits(a[aFromIndex + i]) != Double.doubleToLongBits(b[bFromIndex + i]))
return i;
}
}
return -1;
}
}

View file

@ -1023,7 +1023,6 @@ public class Vector<E>
setBit(deathRow, i - beg);
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
expectedModCount++;
modCount++;
int w = beg;
for (i = beg; i < end; i++)

View file

@ -245,8 +245,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
Future<T> f = futures.get(i);
if (!f.isDone()) {
try { f.get(); }
catch (CancellationException ignore) {}
catch (ExecutionException ignore) {}
catch (CancellationException | ExecutionException ignore) {}
}
}
return futures;
@ -283,8 +282,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
Future<T> f = futures.get(j);
if (!f.isDone()) {
try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
catch (CancellationException ignore) {}
catch (ExecutionException ignore) {}
catch (CancellationException | ExecutionException ignore) {}
catch (TimeoutException timedOut) {
break timedOut;
}

View file

@ -717,12 +717,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
*/
static Class<?> comparableClassFor(Object x) {
if (x instanceof Comparable) {
Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
Class<?> c; Type[] ts, as; ParameterizedType p;
if ((c = x.getClass()) == String.class) // bypass checks
return c;
if ((ts = c.getGenericInterfaces()) != null) {
for (int i = 0; i < ts.length; ++i) {
if (((t = ts[i]) instanceof ParameterizedType) &&
for (Type t : ts) {
if ((t instanceof ParameterizedType) &&
((p = (ParameterizedType)t).getRawType() ==
Comparable.class) &&
(as = p.getActualTypeArguments()) != null &&
@ -2328,15 +2328,15 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* @param check if <0, don't check resize, if <= 1 only check if uncontended
*/
private final void addCount(long x, int check) {
CounterCell[] as; long b, s;
if ((as = counterCells) != null ||
CounterCell[] cs; long b, s;
if ((cs = counterCells) != null ||
!U.compareAndSetLong(this, BASECOUNT, b = baseCount, s = b + x)) {
CounterCell a; long v; int m;
CounterCell c; long v; int m;
boolean uncontended = true;
if (as == null || (m = as.length - 1) < 0 ||
(a = as[ThreadLocalRandom.getProbe() & m]) == null ||
if (cs == null || (m = cs.length - 1) < 0 ||
(c = cs[ThreadLocalRandom.getProbe() & m]) == null ||
!(uncontended =
U.compareAndSetLong(a, CELLVALUE, v = a.value, v + x))) {
U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))) {
fullAddCount(x, uncontended);
return;
}
@ -2574,13 +2574,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
final long sumCount() {
CounterCell[] as = counterCells; CounterCell a;
CounterCell[] cs = counterCells;
long sum = baseCount;
if (as != null) {
for (int i = 0; i < as.length; ++i) {
if ((a = as[i]) != null)
sum += a.value;
}
if (cs != null) {
for (CounterCell c : cs)
if (c != null)
sum += c.value;
}
return sum;
}
@ -2595,9 +2594,9 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
boolean collide = false; // True if last slot nonempty
for (;;) {
CounterCell[] as; CounterCell a; int n; long v;
if ((as = counterCells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
CounterCell[] cs; CounterCell c; int n; long v;
if ((cs = counterCells) != null && (n = cs.length) > 0) {
if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
CounterCell r = new CounterCell(x); // Optimistic create
if (cellsBusy == 0 &&
@ -2623,21 +2622,17 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
else if (U.compareAndSetLong(a, CELLVALUE, v = a.value, v + x))
else if (U.compareAndSetLong(c, CELLVALUE, v = c.value, v + x))
break;
else if (counterCells != as || n >= NCPU)
else if (counterCells != cs || n >= NCPU)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 &&
U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
try {
if (counterCells == as) {// Expand table unless stale
CounterCell[] rs = new CounterCell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
counterCells = rs;
}
if (counterCells == cs) // Expand table unless stale
counterCells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
@ -2646,11 +2641,11 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
h = ThreadLocalRandom.advanceProbe(h);
}
else if (cellsBusy == 0 && counterCells == as &&
else if (cellsBusy == 0 && counterCells == cs &&
U.compareAndSetInt(this, CELLSBUSY, 0, 1)) {
boolean init = false;
try { // Initialize table
if (counterCells == as) {
if (counterCells == cs) {
CounterCell[] rs = new CounterCell[2];
rs[h & 1] = new CounterCell(x);
counterCells = rs;

View file

@ -2204,9 +2204,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}
@ -2331,9 +2329,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}
@ -2453,9 +2449,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
if (k == null) // pass by markers and headers
return true;
int c = cpr(cmp, k, hi);
if (c > 0 || (c == 0 && !hiInclusive))
return false;
return true;
return c < 0 || (c == 0 && hiInclusive);
}
/**

View file

@ -309,9 +309,7 @@ public class ConcurrentSkipListSet<E>
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}

View file

@ -508,7 +508,7 @@ public class CopyOnWriteArrayList<E>
public boolean remove(Object o) {
Object[] snapshot = getArray();
int index = indexOf(o, snapshot, 0, snapshot.length);
return (index < 0) ? false : remove(o, snapshot, index);
return index >= 0 && remove(o, snapshot, index);
}
/**
@ -587,8 +587,8 @@ public class CopyOnWriteArrayList<E>
*/
public boolean addIfAbsent(E e) {
Object[] snapshot = getArray();
return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
addIfAbsent(e, snapshot);
return indexOf(e, snapshot, 0, snapshot.length) < 0
&& addIfAbsent(e, snapshot);
}
/**
@ -980,13 +980,10 @@ public class CopyOnWriteArrayList<E>
List<?> list = (List<?>)o;
Iterator<?> it = list.iterator();
Object[] elements = getArray();
for (int i = 0, len = elements.length; i < len; i++)
if (!it.hasNext() || !Objects.equals(elements[i], it.next()))
for (Object element : getArray())
if (!it.hasNext() || !Objects.equals(element, it.next()))
return false;
if (it.hasNext())
return false;
return true;
return !it.hasNext();
}
/**

View file

@ -1353,17 +1353,16 @@ public class LinkedBlockingDeque<E>
@SuppressWarnings("unchecked")
private boolean bulkRemove(Predicate<? super E> filter) {
boolean removed = false;
Node<E> p = null;
final ReentrantLock lock = this.lock;
Node<E> p = null;
Node<E>[] nodes = null;
int n, len = 0;
do {
// 1. Extract batch of up to 64 elements while holding the lock.
long deathRow = 0; // "bitset" of size 64
lock.lock();
try {
if (nodes == null) {
if (p == null) p = first;
if (nodes == null) { // first batch; initialize
p = first;
for (Node<E> q = p; q != null; q = succ(q))
if (q.item != null && ++len == 64)
break;
@ -1376,6 +1375,7 @@ public class LinkedBlockingDeque<E>
}
// 2. Run the filter on the elements while lock is free.
long deathRow = 0L; // "bitset" of size 64
for (int i = 0; i < n; i++) {
final E e;
if ((e = nodes[i].item) != null && filter.test(e))
@ -1393,6 +1393,7 @@ public class LinkedBlockingDeque<E>
unlink(q);
removed = true;
}
nodes[i] = null; // help GC
}
} finally {
lock.unlock();

View file

@ -1060,11 +1060,10 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
int n, len = 0;
do {
// 1. Extract batch of up to 64 elements while holding the lock.
long deathRow = 0; // "bitset" of size 64
fullyLock();
try {
if (nodes == null) {
if (p == null) p = head.next;
if (nodes == null) { // first batch; initialize
p = head.next;
for (Node<E> q = p; q != null; q = succ(q))
if (q.item != null && ++len == 64)
break;
@ -1077,6 +1076,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
}
// 2. Run the filter on the elements while lock is free.
long deathRow = 0L; // "bitset" of size 64
for (int i = 0; i < n; i++) {
final E e;
if ((e = nodes[i].item) != null && filter.test(e))
@ -1095,6 +1095,7 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
unlink(q, ancestor);
removed = true;
}
nodes[i] = null; // help GC
}
} finally {
fullyUnlock();

View file

@ -772,9 +772,8 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
Node first = null;
restartFromHead: for (;;) {
Node h = head, p = h;
for (; p != null;) {
final Object item;
if ((item = p.item) != null) {
while (p != null) {
if (p.item != null) {
if (p.isData) {
first = p;
break;
@ -1602,8 +1601,7 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
// Read in elements until trailing null sentinel found
Node h = null, t = null;
for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
Node newNode = new Node((E) item);
Node newNode = new Node(item);
if (h == null)
h = t = newNode;
else

View file

@ -269,8 +269,8 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
if (a.getClass() != Object[].class)
a = Arrays.copyOf(a, n, Object[].class);
if (screen && (n == 1 || this.comparator != null)) {
for (int i = 0; i < n; ++i)
if (a[i] == null)
for (Object elt : a)
if (elt == null)
throw new NullPointerException();
}
this.queue = a;

View file

@ -753,8 +753,10 @@ public class SubmissionPublisher<T> implements Publisher<T>,
else
pred.next = next;
}
else
else {
subs.add(b.subscriber);
pred = b;
}
}
}
return subs;

View file

@ -67,7 +67,7 @@ import jdk.internal.misc.VM;
* {@code ThreadLocalRandom.current().nextX(...)} (where
* {@code X} is {@code Int}, {@code Long}, etc).
* When all usages are of this form, it is never possible to
* accidently share a {@code ThreadLocalRandom} across multiple threads.
* accidentally share a {@code ThreadLocalRandom} across multiple threads.
*
* <p>This class also provides additional commonly used bounded random
* generation methods.

View file

@ -264,13 +264,12 @@ import java.util.concurrent.locks.ReentrantLock;
* assist in storage reclamation when large numbers of queued tasks
* become cancelled.</dd>
*
* <dt>Finalization</dt>
* <dt>Reclamation</dt>
*
* <dd>A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
* that unused threads eventually die, by setting appropriate
* has no remaining threads may be reclaimed (garbage collected)
* without being explicity shutdown. You can configure a pool to allow
* all unused threads to eventually die by setting appropriate
* keep-alive times, using a lower bound of zero core threads and/or
* setting {@link #allowCoreThreadTimeOut(boolean)}. </dd>
*
@ -361,7 +360,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* time, but need not hit each state. The transitions are:
*
* RUNNING -> SHUTDOWN
* On invocation of shutdown(), perhaps implicitly in finalize()
* On invocation of shutdown()
* (RUNNING or SHUTDOWN) -> STOP
* On invocation of shutdownNow()
* SHUTDOWN -> TIDYING
@ -581,9 +580,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
private static final RuntimePermission shutdownPerm =
new RuntimePermission("modifyThread");
/** The context to be used when executing the finalizer, or null. */
private final AccessControlContext acc;
/**
* Class Worker mainly maintains interrupt control state for
* threads running tasks, along with other minor bookkeeping.
@ -1300,9 +1296,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = (System.getSecurityManager() == null)
? null
: AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
@ -1469,33 +1462,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
}
/**
* Invokes {@code shutdown} when this executor is no longer
* referenced and it has no threads.
*
* <p>This method is invoked with privileges that are restricted by
* the security context of the caller that invokes the constructor.
*
* @deprecated The {@code finalize} method has been deprecated.
* Subclasses that override {@code finalize} in order to perform cleanup
* should be modified to use alternative cleanup mechanisms and
* to remove the overriding {@code finalize} method.
* When overriding the {@code finalize} method, its implementation must explicitly
* ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
* See the specification for {@link Object#finalize()} for further
* information about migration options.
*/
@Deprecated(since="9")
protected void finalize() {
SecurityManager sm = System.getSecurityManager();
if (sm == null || acc == null) {
shutdown();
} else {
PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
AccessController.doPrivileged(pa, acc);
}
}
/**
* Sets the thread factory used to create new threads.
*

View file

@ -320,7 +320,9 @@ public abstract class AbstractQueuedLongSynchronizer
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
// or signal, so no further action is necessary, although with
// a possibility that a cancelled node may transiently remain
// reachable.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
@ -912,13 +914,13 @@ public abstract class AbstractQueuedLongSynchronizer
* at any time, a {@code true} return does not guarantee that any
* other thread will ever acquire.
*
* <p>In this implementation, this operation returns in
* constant time.
*
* @return {@code true} if there may be other threads waiting to acquire
*/
public final boolean hasQueuedThreads() {
return head != tail;
for (Node p = tail, h = head; p != h && p != null; p = p.prev)
if (p.waitStatus <= 0)
return true;
return false;
}
/**
@ -1067,17 +1069,21 @@ public abstract class AbstractQueuedLongSynchronizer
* @since 1.7
*/
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
Node h, s;
if ((h = head) != null) {
if ((s = h.next) == null || s.waitStatus > 0) {
s = null; // traverse in case of concurrent cancellation
for (Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)
s = p;
}
}
if (s != null && s.thread != Thread.currentThread())
return true;
}
return false;
}
// Instrumentation and monitoring methods
/**

View file

@ -800,7 +800,9 @@ public abstract class AbstractQueuedSynchronizer
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
// or signal, so no further action is necessary, although with
// a possibility that a cancelled node may transiently remain
// reachable.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
@ -1392,13 +1394,13 @@ public abstract class AbstractQueuedSynchronizer
* at any time, a {@code true} return does not guarantee that any
* other thread will ever acquire.
*
* <p>In this implementation, this operation returns in
* constant time.
*
* @return {@code true} if there may be other threads waiting to acquire
*/
public final boolean hasQueuedThreads() {
return head != tail;
for (Node p = tail, h = head; p != h && p != null; p = p.prev)
if (p.waitStatus <= 0)
return true;
return false;
}
/**
@ -1547,17 +1549,21 @@ public abstract class AbstractQueuedSynchronizer
* @since 1.7
*/
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
Node h, s;
if ((h = head) != null) {
if ((s = h.next) == null || s.waitStatus > 0) {
s = null; // traverse in case of concurrent cancellation
for (Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)
s = p;
}
}
if (s != null && s.thread != Thread.currentThread())
return true;
}
return false;
}
// Instrumentation and monitoring methods
/**

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, 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
@ -953,6 +953,12 @@ public final class Pattern
*/
private int flags;
/**
* The temporary pattern flags used during compiling. The flags might be turn
* on and off by embedded flag.
*/
private transient int flags0;
/**
* Boolean indicating this Pattern is compiled; this is necessary in order
* to lazily compile deserialized Patterns.
@ -1137,7 +1143,7 @@ public final class Pattern
* @return The match flags specified when this pattern was compiled
*/
public int flags() {
return flags;
return flags0;
}
/**
@ -1369,6 +1375,9 @@ public final class Pattern
// Read in all fields
s.defaultReadObject();
// reset the flags
flags0 = flags;
// Initialize counts
capturingGroupCount = 1;
localCount = 0;
@ -1400,6 +1409,9 @@ public final class Pattern
if ((flags & UNICODE_CHARACTER_CLASS) != 0)
flags |= UNICODE_CASE;
// 'flags' for compiling
flags0 = flags;
// Reset group index count
capturingGroupCount = 1;
localCount = 0;
@ -1841,7 +1853,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
* Indicates whether a particular flag is set or not.
*/
private boolean has(int f) {
return (flags & f) != 0;
return (flags0 & f) != 0;
}
/**
@ -2718,7 +2730,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
ch == 0x53 || ch == 0x73 || //S and s
ch == 0x4b || ch == 0x6b || //K and k
ch == 0xc5 || ch == 0xe5))) { //A+ring
bits.add(ch, flags());
bits.add(ch, flags0);
return null;
}
return single(ch);
@ -2931,7 +2943,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
boolean capturingGroup = false;
Node head = null;
Node tail = null;
int save = flags;
int save = flags0;
int saveTCNCount = topClosureNodes.size();
root = null;
int ch = next();
@ -3032,7 +3044,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
}
accept(')', "Unclosed group");
flags = save;
flags0 = save;
// Check for quantifiers
Node node = closure(head);
@ -3135,28 +3147,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
for (;;) {
switch (ch) {
case 'i':
flags |= CASE_INSENSITIVE;
flags0 |= CASE_INSENSITIVE;
break;
case 'm':
flags |= MULTILINE;
flags0 |= MULTILINE;
break;
case 's':
flags |= DOTALL;
flags0 |= DOTALL;
break;
case 'd':
flags |= UNIX_LINES;
flags0 |= UNIX_LINES;
break;
case 'u':
flags |= UNICODE_CASE;
flags0 |= UNICODE_CASE;
break;
case 'c':
flags |= CANON_EQ;
flags0 |= CANON_EQ;
break;
case 'x':
flags |= COMMENTS;
flags0 |= COMMENTS;
break;
case 'U':
flags |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
flags0 |= (UNICODE_CHARACTER_CLASS | UNICODE_CASE);
break;
case '-': // subFlag then fall through
ch = next();
@ -3178,28 +3190,28 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
for (;;) {
switch (ch) {
case 'i':
flags &= ~CASE_INSENSITIVE;
flags0 &= ~CASE_INSENSITIVE;
break;
case 'm':
flags &= ~MULTILINE;
flags0 &= ~MULTILINE;
break;
case 's':
flags &= ~DOTALL;
flags0 &= ~DOTALL;
break;
case 'd':
flags &= ~UNIX_LINES;
flags0 &= ~UNIX_LINES;
break;
case 'u':
flags &= ~UNICODE_CASE;
flags0 &= ~UNICODE_CASE;
break;
case 'c':
flags &= ~CANON_EQ;
flags0 &= ~CANON_EQ;
break;
case 'x':
flags &= ~COMMENTS;
flags0 &= ~COMMENTS;
break;
case 'U':
flags &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
flags0 &= ~(UNICODE_CHARACTER_CLASS | UNICODE_CASE);
break;
default:
return;