8223593: Refactor code for reallocating storage
Reviewed-by: prappo, plevart, rriggs, smarks
This commit is contained in:
parent
54d0b2a8d6
commit
218204b1a3
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2019, 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
|
||||
@ -26,6 +26,7 @@
|
||||
package java.io;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* A <code>BufferedInputStream</code> adds
|
||||
@ -53,14 +54,6 @@ class BufferedInputStream extends FilterInputStream {
|
||||
|
||||
private static int DEFAULT_BUFFER_SIZE = 8192;
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* As this class is used early during bootstrap, it's motivated to use
|
||||
* Unsafe.compareAndSetObject instead of AtomicReferenceFieldUpdater
|
||||
@ -220,7 +213,7 @@ class BufferedInputStream extends FilterInputStream {
|
||||
byte[] buffer = getBufIfOpen();
|
||||
if (markpos < 0)
|
||||
pos = 0; /* no mark: throw away the buffer */
|
||||
else if (pos >= buffer.length) /* no room left in buffer */
|
||||
else if (pos >= buffer.length) { /* no room left in buffer */
|
||||
if (markpos > 0) { /* can throw away early part of the buffer */
|
||||
int sz = pos - markpos;
|
||||
System.arraycopy(buffer, markpos, buffer, 0, sz);
|
||||
@ -229,11 +222,10 @@ class BufferedInputStream extends FilterInputStream {
|
||||
} else if (buffer.length >= marklimit) {
|
||||
markpos = -1; /* buffer got too big, invalidate mark */
|
||||
pos = 0; /* drop buffer contents */
|
||||
} else if (buffer.length >= MAX_BUFFER_SIZE) {
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
} else { /* grow buffer */
|
||||
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
|
||||
pos * 2 : MAX_BUFFER_SIZE;
|
||||
int nsz = ArraysSupport.newLength(pos,
|
||||
1, /* minimum growth */
|
||||
pos /* preferred growth */);
|
||||
if (nsz > marklimit)
|
||||
nsz = marklimit;
|
||||
byte[] nbuf = new byte[nsz];
|
||||
@ -248,6 +240,7 @@ class BufferedInputStream extends FilterInputStream {
|
||||
}
|
||||
buffer = nbuf;
|
||||
}
|
||||
}
|
||||
count = pos;
|
||||
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
|
||||
if (n > 0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2019, 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
|
||||
@ -29,6 +29,8 @@ import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* This class implements an output stream in which the data is
|
||||
* written into a byte array. The buffer automatically grows as data
|
||||
@ -84,48 +86,20 @@ public class ByteArrayOutputStream extends OutputStream {
|
||||
* at least the number of elements specified by the minimum
|
||||
* capacity argument.
|
||||
*
|
||||
* @param minCapacity the desired minimum capacity
|
||||
* @throws OutOfMemoryError if {@code minCapacity < 0}. This is
|
||||
* interpreted as a request for the unsatisfiably large capacity
|
||||
* @param minCapacity the desired minimum capacity.
|
||||
* @throws OutOfMemoryError if {@code minCapacity < 0} and
|
||||
* {@code minCapacity - buf.length > 0}. This is interpreted as a
|
||||
* request for the unsatisfiably large capacity.
|
||||
* {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.
|
||||
*/
|
||||
private void ensureCapacity(int minCapacity) {
|
||||
// overflow-conscious code
|
||||
if (minCapacity - buf.length > 0)
|
||||
grow(minCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Increases the capacity to ensure that it can hold at least the
|
||||
* number of elements specified by the minimum capacity argument.
|
||||
*
|
||||
* @param minCapacity the desired minimum capacity
|
||||
*/
|
||||
private void grow(int minCapacity) {
|
||||
// overflow-conscious code
|
||||
int oldCapacity = buf.length;
|
||||
int newCapacity = oldCapacity << 1;
|
||||
if (newCapacity - minCapacity < 0)
|
||||
newCapacity = minCapacity;
|
||||
if (newCapacity - MAX_ARRAY_SIZE > 0)
|
||||
newCapacity = hugeCapacity(minCapacity);
|
||||
buf = Arrays.copyOf(buf, newCapacity);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||
Integer.MAX_VALUE :
|
||||
MAX_ARRAY_SIZE;
|
||||
int minGrowth = minCapacity - oldCapacity;
|
||||
if (minGrowth > 0) {
|
||||
buf = Arrays.copyOf(buf, ArraysSupport.newLength(oldCapacity,
|
||||
minGrowth, oldCapacity /* preferred growth */));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,7 @@ import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
import static java.lang.String.LATIN1;
|
||||
import static java.lang.String.UTF16;
|
||||
@ -42,14 +43,6 @@ import static java.lang.String.checkOffset;
|
||||
|
||||
final class StringLatin1 {
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
public static char charAt(byte[] value, int index) {
|
||||
if (index < 0 || index >= value.length) {
|
||||
throw new StringIndexOutOfBoundsException(index);
|
||||
@ -353,15 +346,7 @@ final class StringLatin1 {
|
||||
i += targLen;
|
||||
while ((j = indexOf(value, valLen, targ, targLen, i)) > 0) {
|
||||
if (++p == pos.length) {
|
||||
int cap = p + (p >> 1);
|
||||
// overflow-conscious code
|
||||
if (cap - MAX_ARRAY_SIZE > 0) {
|
||||
if (p == MAX_ARRAY_SIZE) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
cap = MAX_ARRAY_SIZE;
|
||||
}
|
||||
pos = Arrays.copyOf(pos, cap);
|
||||
pos = Arrays.copyOf(pos, ArraysSupport.newLength(p, 1, p >> 1));
|
||||
}
|
||||
pos[p] = j;
|
||||
i = j + targLen;
|
||||
|
@ -33,6 +33,7 @@ import java.util.function.IntConsumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.DontInline;
|
||||
|
||||
@ -649,15 +650,7 @@ final class StringUTF16 {
|
||||
: indexOf(value, valLen, targ, targLen, i))) > 0)
|
||||
{
|
||||
if (++p == pos.length) {
|
||||
int cap = p + (p >> 1);
|
||||
// overflow-conscious code
|
||||
if (cap - MAX_ARRAY_SIZE > 0) {
|
||||
if (p == MAX_ARRAY_SIZE) {
|
||||
throw new OutOfMemoryError();
|
||||
}
|
||||
cap = MAX_ARRAY_SIZE;
|
||||
}
|
||||
pos = Arrays.copyOf(pos, cap);
|
||||
pos = Arrays.copyOf(pos, ArraysSupport.newLength(p, 1, p >> 1));
|
||||
}
|
||||
pos[p] = j;
|
||||
i = j + targLen;
|
||||
@ -1554,15 +1547,6 @@ final class StringUTF16 {
|
||||
|
||||
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
|
||||
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
// Used by trusted callers. Assumes all necessary bounds checks have
|
||||
// been done by the caller.
|
||||
|
||||
|
@ -77,6 +77,7 @@ import java.util.function.BiPredicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import sun.nio.ch.FileChannelImpl;
|
||||
import sun.nio.fs.AbstractFileSystemProvider;
|
||||
|
||||
@ -3196,14 +3197,6 @@ public final class Files {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
private static final jdk.internal.access.JavaLangAccess JLA =
|
||||
jdk.internal.access.SharedSecrets.getJavaLangAccess();
|
||||
|
||||
@ -3240,13 +3233,10 @@ public final class Files {
|
||||
break;
|
||||
|
||||
// one more byte was read; need to allocate a larger buffer
|
||||
if (capacity <= MAX_BUFFER_SIZE - capacity) {
|
||||
capacity = Math.max(capacity << 1, BUFFER_SIZE);
|
||||
} else {
|
||||
if (capacity == MAX_BUFFER_SIZE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
capacity = MAX_BUFFER_SIZE;
|
||||
}
|
||||
capacity = Math.max(ArraysSupport.newLength(capacity,
|
||||
1, /* minimum growth */
|
||||
capacity /* preferred growth */),
|
||||
BUFFER_SIZE);
|
||||
buf = Arrays.copyOf(buf, capacity);
|
||||
buf[nread++] = (byte)n;
|
||||
}
|
||||
@ -3283,7 +3273,7 @@ public final class Files {
|
||||
if (sbc instanceof FileChannelImpl)
|
||||
((FileChannelImpl) sbc).setUninterruptible();
|
||||
long size = sbc.size();
|
||||
if (size > (long) MAX_BUFFER_SIZE)
|
||||
if (size > (long) Integer.MAX_VALUE)
|
||||
throw new OutOfMemoryError("Required array size too large");
|
||||
return read(in, (int)size);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2019, 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,6 +25,8 @@
|
||||
|
||||
package java.util;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* This class provides a skeletal implementation of the {@code Collection}
|
||||
* interface, to minimize the effort required to implement this interface. <p>
|
||||
@ -203,14 +205,6 @@ public abstract class AbstractCollection<E> implements Collection<E> {
|
||||
return it.hasNext() ? finishToArray(r, it) : r;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Reallocates the array being used within toArray when the iterator
|
||||
* returned more elements than expected, and finishes filling it from
|
||||
@ -223,29 +217,19 @@ public abstract class AbstractCollection<E> implements Collection<E> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
|
||||
int i = r.length;
|
||||
int len = r.length;
|
||||
int i = len;
|
||||
while (it.hasNext()) {
|
||||
int cap = r.length;
|
||||
if (i == cap) {
|
||||
int newCap = cap + (cap >> 1) + 1;
|
||||
// overflow-conscious code
|
||||
if (newCap - MAX_ARRAY_SIZE > 0)
|
||||
newCap = hugeCapacity(cap + 1);
|
||||
r = Arrays.copyOf(r, newCap);
|
||||
if (i == len) {
|
||||
len = ArraysSupport.newLength(len,
|
||||
1, /* minimum growth */
|
||||
(len >> 1) + 1 /* preferred growth */);
|
||||
r = Arrays.copyOf(r, len);
|
||||
}
|
||||
r[i++] = (T)it.next();
|
||||
}
|
||||
// trim if overallocated
|
||||
return (i == r.length) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError
|
||||
("Required array size too large");
|
||||
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||
Integer.MAX_VALUE :
|
||||
MAX_ARRAY_SIZE;
|
||||
return (i == len) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
// Modification Operations
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2019, 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
|
||||
@ -29,6 +29,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* Resizable-array implementation of the {@code List} interface. Implements
|
||||
@ -218,14 +219,6 @@ public class ArrayList<E> extends AbstractList<E>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Increases the capacity to ensure that it can hold at least the
|
||||
* number of elements specified by the minimum capacity argument.
|
||||
@ -234,47 +227,21 @@ public class ArrayList<E> extends AbstractList<E>
|
||||
* @throws OutOfMemoryError if minCapacity is less than zero
|
||||
*/
|
||||
private Object[] grow(int minCapacity) {
|
||||
return elementData = Arrays.copyOf(elementData,
|
||||
newCapacity(minCapacity));
|
||||
int oldCapacity = elementData.length;
|
||||
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
|
||||
int newCapacity = ArraysSupport.newLength(oldCapacity,
|
||||
minCapacity - oldCapacity, /* minimum growth */
|
||||
oldCapacity >> 1 /* preferred growth */);
|
||||
return elementData = Arrays.copyOf(elementData, newCapacity);
|
||||
} else {
|
||||
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
|
||||
}
|
||||
}
|
||||
|
||||
private Object[] grow() {
|
||||
return grow(size + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a capacity at least as large as the given minimum capacity.
|
||||
* Returns the current capacity increased by 50% if that suffices.
|
||||
* Will not return a capacity greater than MAX_ARRAY_SIZE unless
|
||||
* the given minimum capacity is greater than MAX_ARRAY_SIZE.
|
||||
*
|
||||
* @param minCapacity the desired minimum capacity
|
||||
* @throws OutOfMemoryError if minCapacity is less than zero
|
||||
*/
|
||||
private int newCapacity(int minCapacity) {
|
||||
// overflow-conscious code
|
||||
int oldCapacity = elementData.length;
|
||||
int newCapacity = oldCapacity + (oldCapacity >> 1);
|
||||
if (newCapacity - minCapacity <= 0) {
|
||||
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
|
||||
return Math.max(DEFAULT_CAPACITY, minCapacity);
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return minCapacity;
|
||||
}
|
||||
return (newCapacity - MAX_ARRAY_SIZE <= 0)
|
||||
? newCapacity
|
||||
: hugeCapacity(minCapacity);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return (minCapacity > MAX_ARRAY_SIZE)
|
||||
? Integer.MAX_VALUE
|
||||
: MAX_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this list.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2019, 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
|
||||
@ -28,6 +28,7 @@ package java.util;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* An unbounded priority {@linkplain Queue queue} based on a priority heap.
|
||||
@ -281,14 +282,6 @@ public class PriorityQueue<E> extends AbstractQueue<E>
|
||||
heapify();
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate.
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Increases the capacity of the array.
|
||||
*
|
||||
@ -297,23 +290,13 @@ public class PriorityQueue<E> extends AbstractQueue<E>
|
||||
private void grow(int minCapacity) {
|
||||
int oldCapacity = queue.length;
|
||||
// Double size if small; else grow by 50%
|
||||
int newCapacity = oldCapacity + ((oldCapacity < 64) ?
|
||||
(oldCapacity + 2) :
|
||||
(oldCapacity >> 1));
|
||||
// overflow-conscious code
|
||||
if (newCapacity - MAX_ARRAY_SIZE > 0)
|
||||
newCapacity = hugeCapacity(minCapacity);
|
||||
int newCapacity = ArraysSupport.newLength(oldCapacity,
|
||||
minCapacity - oldCapacity, /* minimum growth */
|
||||
oldCapacity < 64 ? oldCapacity + 2 : oldCapacity >> 1
|
||||
/* preferred growth */);
|
||||
queue = Arrays.copyOf(queue, newCapacity);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||
Integer.MAX_VALUE :
|
||||
MAX_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element into this priority queue.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2019, 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
|
||||
@ -32,6 +32,8 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* The {@code Vector} class implements a growable array of
|
||||
* objects. Like an array, it contains components that can be
|
||||
@ -241,14 +243,6 @@ public class Vector<E>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* OutOfMemoryError: Requested array size exceeds VM limit
|
||||
*/
|
||||
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Increases the capacity to ensure that it can hold at least the
|
||||
* number of elements specified by the minimum capacity argument.
|
||||
@ -257,45 +251,18 @@ public class Vector<E>
|
||||
* @throws OutOfMemoryError if minCapacity is less than zero
|
||||
*/
|
||||
private Object[] grow(int minCapacity) {
|
||||
return elementData = Arrays.copyOf(elementData,
|
||||
newCapacity(minCapacity));
|
||||
int oldCapacity = elementData.length;
|
||||
int newCapacity = ArraysSupport.newLength(oldCapacity,
|
||||
minCapacity - oldCapacity, /* minimum growth */
|
||||
capacityIncrement > 0 ? capacityIncrement : oldCapacity
|
||||
/* preferred growth */);
|
||||
return elementData = Arrays.copyOf(elementData, newCapacity);
|
||||
}
|
||||
|
||||
private Object[] grow() {
|
||||
return grow(elementCount + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a capacity at least as large as the given minimum capacity.
|
||||
* Will not return a capacity greater than MAX_ARRAY_SIZE unless
|
||||
* the given minimum capacity is greater than MAX_ARRAY_SIZE.
|
||||
*
|
||||
* @param minCapacity the desired minimum capacity
|
||||
* @throws OutOfMemoryError if minCapacity is less than zero
|
||||
*/
|
||||
private int newCapacity(int minCapacity) {
|
||||
// overflow-conscious code
|
||||
int oldCapacity = elementData.length;
|
||||
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
|
||||
capacityIncrement : oldCapacity);
|
||||
if (newCapacity - minCapacity <= 0) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return minCapacity;
|
||||
}
|
||||
return (newCapacity - MAX_ARRAY_SIZE <= 0)
|
||||
? newCapacity
|
||||
: hugeCapacity(minCapacity);
|
||||
}
|
||||
|
||||
private static int hugeCapacity(int minCapacity) {
|
||||
if (minCapacity < 0) // overflow
|
||||
throw new OutOfMemoryError();
|
||||
return (minCapacity > MAX_ARRAY_SIZE) ?
|
||||
Integer.MAX_VALUE :
|
||||
MAX_ARRAY_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of this vector. If the new size is greater than the
|
||||
* current size, new {@code null} items are added to the end of
|
||||
|
@ -43,6 +43,7 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
|
||||
/**
|
||||
* A compiled representation of a regular expression.
|
||||
@ -2315,13 +2316,15 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
}
|
||||
}
|
||||
|
||||
private void append(int ch, int len) {
|
||||
if (len >= buffer.length) {
|
||||
int[] tmp = new int[len+len];
|
||||
System.arraycopy(buffer, 0, tmp, 0, len);
|
||||
buffer = tmp;
|
||||
private void append(int ch, int index) {
|
||||
int len = buffer.length;
|
||||
if (index - len >= 0) {
|
||||
len = ArraysSupport.newLength(len,
|
||||
1 + index - len, /* minimum growth */
|
||||
len /* preferred growth */);
|
||||
buffer = Arrays.copyOf(buffer, len);
|
||||
}
|
||||
buffer[len] = ch;
|
||||
buffer[index] = ch;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -28,7 +28,9 @@ import jdk.internal.HotSpotIntrinsicCandidate;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Utility methods to find a mismatch between two primitive arrays.
|
||||
* Utility methods to work with arrays. This includes a set of methods
|
||||
* to find a mismatch between two primitive arrays. Also included is
|
||||
* a method to calculate the new length of an array to be reallocated.
|
||||
*
|
||||
* <p>Array equality and lexicographical comparison can be built on top of
|
||||
* array mismatch functionality.
|
||||
@ -571,4 +573,54 @@ public class ArraysSupport {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum length of array to allocate (unless necessary).
|
||||
* Some VMs reserve some header words in an array.
|
||||
* Attempts to allocate larger arrays may result in
|
||||
* {@code OutOfMemoryError: Requested array size exceeds VM limit}
|
||||
*/
|
||||
public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
|
||||
|
||||
/**
|
||||
* Calculates a new array length given an array's current length, a preferred
|
||||
* growth value, and a minimum growth value. If the preferred growth value
|
||||
* is less than the minimum growth value, the minimum growth value is used in
|
||||
* its place. If the sum of the current length and the preferred growth
|
||||
* value does not exceed {@link #MAX_ARRAY_LENGTH}, that sum is returned.
|
||||
* If the sum of the current length and the minimum growth value does not
|
||||
* exceed {@code MAX_ARRAY_LENGTH}, then {@code MAX_ARRAY_LENGTH} is returned.
|
||||
* If the sum does not overflow an int, then {@code Integer.MAX_VALUE} is
|
||||
* returned. Otherwise, {@code OutOfMemoryError} is thrown.
|
||||
*
|
||||
* @param oldLength current length of the array (must be non negative)
|
||||
* @param minGrowth minimum required growth of the array length (must be
|
||||
* positive)
|
||||
* @param prefGrowth preferred growth of the array length (ignored, if less
|
||||
* then {@code minGrowth})
|
||||
* @return the new length of the array
|
||||
* @throws OutOfMemoryError if increasing {@code oldLength} by
|
||||
* {@code minGrowth} overflows.
|
||||
*/
|
||||
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
|
||||
// assert oldLength >= 0
|
||||
// assert minGrowth > 0
|
||||
|
||||
int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
|
||||
if (newLength - MAX_ARRAY_LENGTH <= 0) {
|
||||
return newLength;
|
||||
}
|
||||
return hugeLength(oldLength, minGrowth);
|
||||
}
|
||||
|
||||
private static int hugeLength(int oldLength, int minGrowth) {
|
||||
int minLength = oldLength + minGrowth;
|
||||
if (minLength < 0) { // overflow
|
||||
throw new OutOfMemoryError("Required array length too large");
|
||||
}
|
||||
if (minLength <= MAX_ARRAY_LENGTH) {
|
||||
return MAX_ARRAY_LENGTH;
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user