1 /* 2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.internal.util; 26 27 import jdk.internal.HotSpotIntrinsicCandidate; 28 import jdk.internal.misc.Unsafe; 29 30 /** 31 * Utility methods to work with arrays. 32 * This includes a set of methods to find a mismatch between two primitive arrays 33 * and a method to calculate the new size of an array to be reallocated 34 * 35 * <p>Array equality and lexicographical comparison can be built on top of 36 * array mismatch functionality. 37 * 38 * <p>The mismatch method implementation, {@link #vectorizedMismatch}, leverages 39 * vector-based techniques to access and compare the contents of two arrays. 40 * The Java implementation uses {@code Unsafe.getLongUnaligned} to access the 41 * content of an array, thus access is supported on platforms that do not 42 * support unaligned access. For a byte[] array, 8 bytes (64 bits) can be 43 * accessed and compared as a unit rather than individually, which increases 44 * the performance when the method is compiled by the HotSpot VM. On supported 45 * platforms the mismatch implementation is intrinsified to leverage SIMD 46 * instructions. So for a byte[] array, 16 bytes (128 bits), 32 bytes 47 * (256 bits), and perhaps in the future even 64 bytes (512 bits), platform 48 * permitting, can be accessed and compared as a unit, which further increases 49 * the performance over the Java implementation. 50 * 51 * <p>None of the mismatch methods perform array bounds checks. It is the 52 * responsibility of the caller (direct or otherwise) to perform such checks 53 * before calling this method. 54 */ 55 public class ArraysSupport { 56 static final Unsafe U = Unsafe.getUnsafe(); 57 58 private static final boolean BIG_ENDIAN = U.isBigEndian(); 59 60 public static final int LOG2_ARRAY_BOOLEAN_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BOOLEAN_INDEX_SCALE); 61 public static final int LOG2_ARRAY_BYTE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_BYTE_INDEX_SCALE); 62 public static final int LOG2_ARRAY_CHAR_INDEX_SCALE = exactLog2(Unsafe.ARRAY_CHAR_INDEX_SCALE); 63 public static final int LOG2_ARRAY_SHORT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_SHORT_INDEX_SCALE); 64 public static final int LOG2_ARRAY_INT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_INT_INDEX_SCALE); 65 public static final int LOG2_ARRAY_LONG_INDEX_SCALE = exactLog2(Unsafe.ARRAY_LONG_INDEX_SCALE); 66 public static final int LOG2_ARRAY_FLOAT_INDEX_SCALE = exactLog2(Unsafe.ARRAY_FLOAT_INDEX_SCALE); 67 public static final int LOG2_ARRAY_DOUBLE_INDEX_SCALE = exactLog2(Unsafe.ARRAY_DOUBLE_INDEX_SCALE); 68 69 private static final int LOG2_BYTE_BIT_SIZE = exactLog2(Byte.SIZE); 70 71 private static int exactLog2(int scale) { 72 if ((scale & (scale - 1)) != 0) 73 throw new Error("data type scale not a power of two"); 74 return Integer.numberOfTrailingZeros(scale); 75 } 76 77 private ArraysSupport() {} 78 79 /** 80 * Find the relative index of the first mismatching pair of elements in two 81 * primitive arrays of the same component type. Pairs of elements will be 82 * tested in order relative to given offsets into both arrays. 83 * 84 * <p>This method does not perform type checks or bounds checks. It is the 85 * responsibility of the caller to perform such checks before calling this 86 * method. 87 * 88 * <p>The given offsets, in bytes, need not be aligned according to the 89 * given log<sub>2</sub> size the array elements. More specifically, an 90 * offset modulus the size need not be zero. 91 * 92 * @param a the first array to be tested for mismatch, or {@code null} for 93 * direct memory access 94 * @param aOffset the relative offset, in bytes, from the base address of 95 * the first array to test from, otherwise if the first array is 96 * {@code null}, an absolute address pointing to the first element to test. 97 * @param b the second array to be tested for mismatch, or {@code null} for 98 * direct memory access 99 * @param bOffset the relative offset, in bytes, from the base address of 100 * the second array to test from, otherwise if the second array is 101 * {@code null}, an absolute address pointing to the first element to test. 102 * @param length the number of array elements to test 103 * @param log2ArrayIndexScale log<sub>2</sub> of the array index scale, that 104 * corresponds to the size, in bytes, of an array element. 105 * @return if a mismatch is found a relative index, between 0 (inclusive) 106 * and {@code length} (exclusive), of the first mismatching pair of elements 107 * in the two arrays. Otherwise, if a mismatch is not found the bitwise 108 * compliment of the number of remaining pairs of elements to be checked in 109 * the tail of the two arrays. 110 */ 111 @HotSpotIntrinsicCandidate 112 public static int vectorizedMismatch(Object a, long aOffset, 113 Object b, long bOffset, 114 int length, 115 int log2ArrayIndexScale) { 116 // assert a.getClass().isArray(); 117 // assert b.getClass().isArray(); 118 // assert 0 <= length <= sizeOf(a) 119 // assert 0 <= length <= sizeOf(b) 120 // assert 0 <= log2ArrayIndexScale <= 3 121 122 int log2ValuesPerWidth = LOG2_ARRAY_LONG_INDEX_SCALE - log2ArrayIndexScale; 123 int wi = 0; 124 for (; wi < length >> log2ValuesPerWidth; wi++) { 125 long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE; 126 long av = U.getLongUnaligned(a, aOffset + bi); 127 long bv = U.getLongUnaligned(b, bOffset + bi); 128 if (av != bv) { 129 long x = av ^ bv; 130 int o = BIG_ENDIAN 131 ? Long.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale) 132 : Long.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale); 133 return (wi << log2ValuesPerWidth) + o; 134 } 135 } 136 137 // Calculate the tail of remaining elements to check 138 int tail = length - (wi << log2ValuesPerWidth); 139 140 if (log2ArrayIndexScale < LOG2_ARRAY_INT_INDEX_SCALE) { 141 int wordTail = 1 << (LOG2_ARRAY_INT_INDEX_SCALE - log2ArrayIndexScale); 142 // Handle 4 bytes or 2 chars in the tail using int width 143 if (tail >= wordTail) { 144 long bi = ((long) wi) << LOG2_ARRAY_LONG_INDEX_SCALE; 145 int av = U.getIntUnaligned(a, aOffset + bi); 146 int bv = U.getIntUnaligned(b, bOffset + bi); 147 if (av != bv) { 148 int x = av ^ bv; 149 int o = BIG_ENDIAN 150 ? Integer.numberOfLeadingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale) 151 : Integer.numberOfTrailingZeros(x) >> (LOG2_BYTE_BIT_SIZE + log2ArrayIndexScale); 152 return (wi << log2ValuesPerWidth) + o; 153 } 154 tail -= wordTail; 155 } 156 return ~tail; 157 } 158 else { 159 return ~tail; 160 } 161 } 162 163 // Booleans 164 // Each boolean element takes up one byte 165 166 public static int mismatch(boolean[] a, 167 boolean[] b, 168 int length) { 169 int i = 0; 170 if (length > 7) { 171 if (a[0] != b[0]) 172 return 0; 173 i = vectorizedMismatch( 174 a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, 175 b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET, 176 length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE); 177 if (i >= 0) 178 return i; 179 i = length - ~i; 180 } 181 for (; i < length; i++) { 182 if (a[i] != b[i]) 183 return i; 184 } 185 return -1; 186 } 187 188 public static int mismatch(boolean[] a, int aFromIndex, 189 boolean[] b, int bFromIndex, 190 int length) { 191 int i = 0; 192 if (length > 7) { 193 if (a[aFromIndex] != b[bFromIndex]) 194 return 0; 195 int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex; 196 int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex; 197 i = vectorizedMismatch( 198 a, aOffset, 199 b, bOffset, 200 length, LOG2_ARRAY_BOOLEAN_INDEX_SCALE); 201 if (i >= 0) 202 return i; 203 i = length - ~i; 204 } 205 for (; i < length; i++) { 206 if (a[aFromIndex + i] != b[bFromIndex + i]) 207 return i; 208 } 209 return -1; 210 } 211 212 213 // Bytes 214 215 /** 216 * Find the index of a mismatch between two arrays. 217 * 218 * <p>This method does not perform bounds checks. It is the responsibility 219 * of the caller to perform such bounds checks before calling this method. 220 * 221 * @param a the first array to be tested for a mismatch 222 * @param b the second array to be tested for a mismatch 223 * @param length the number of bytes from each array to check 224 * @return the index of a mismatch between the two arrays, otherwise -1 if 225 * no mismatch. The index will be within the range of (inclusive) 0 to 226 * (exclusive) the smaller of the two array lengths. 227 */ 228 public static int mismatch(byte[] a, 229 byte[] b, 230 int length) { 231 // ISSUE: defer to index receiving methods if performance is good 232 // assert length <= a.length 233 // assert length <= b.length 234 235 int i = 0; 236 if (length > 7) { 237 if (a[0] != b[0]) 238 return 0; 239 i = vectorizedMismatch( 240 a, Unsafe.ARRAY_BYTE_BASE_OFFSET, 241 b, Unsafe.ARRAY_BYTE_BASE_OFFSET, 242 length, LOG2_ARRAY_BYTE_INDEX_SCALE); 243 if (i >= 0) 244 return i; 245 // Align to tail 246 i = length - ~i; 247 // assert i >= 0 && i <= 7; 248 } 249 // Tail < 8 bytes 250 for (; i < length; i++) { 251 if (a[i] != b[i]) 252 return i; 253 } 254 return -1; 255 } 256 257 /** 258 * Find the relative index of a mismatch between two arrays starting from 259 * given indexes. 260 * 261 * <p>This method does not perform bounds checks. It is the responsibility 262 * of the caller to perform such bounds checks before calling this method. 263 * 264 * @param a the first array to be tested for a mismatch 265 * @param aFromIndex the index of the first element (inclusive) in the first 266 * array to be compared 267 * @param b the second array to be tested for a mismatch 268 * @param bFromIndex the index of the first element (inclusive) in the 269 * second array to be compared 270 * @param length the number of bytes from each array to check 271 * @return the relative index of a mismatch between the two arrays, 272 * otherwise -1 if no mismatch. The index will be within the range of 273 * (inclusive) 0 to (exclusive) the smaller of the two array bounds. 274 */ 275 public static int mismatch(byte[] a, int aFromIndex, 276 byte[] b, int bFromIndex, 277 int length) { 278 // assert 0 <= aFromIndex < a.length 279 // assert 0 <= aFromIndex + length <= a.length 280 // assert 0 <= bFromIndex < b.length 281 // assert 0 <= bFromIndex + length <= b.length 282 // assert length >= 0 283 284 int i = 0; 285 if (length > 7) { 286 if (a[aFromIndex] != b[bFromIndex]) 287 return 0; 288 int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex; 289 int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex; 290 i = vectorizedMismatch( 291 a, aOffset, 292 b, bOffset, 293 length, LOG2_ARRAY_BYTE_INDEX_SCALE); 294 if (i >= 0) 295 return i; 296 i = length - ~i; 297 } 298 for (; i < length; i++) { 299 if (a[aFromIndex + i] != b[bFromIndex + i]) 300 return i; 301 } 302 return -1; 303 } 304 305 306 // Chars 307 308 public static int mismatch(char[] a, 309 char[] b, 310 int length) { 311 int i = 0; 312 if (length > 3) { 313 if (a[0] != b[0]) 314 return 0; 315 i = vectorizedMismatch( 316 a, Unsafe.ARRAY_CHAR_BASE_OFFSET, 317 b, Unsafe.ARRAY_CHAR_BASE_OFFSET, 318 length, LOG2_ARRAY_CHAR_INDEX_SCALE); 319 if (i >= 0) 320 return i; 321 i = length - ~i; 322 } 323 for (; i < length; i++) { 324 if (a[i] != b[i]) 325 return i; 326 } 327 return -1; 328 } 329 330 public static int mismatch(char[] a, int aFromIndex, 331 char[] b, int bFromIndex, 332 int length) { 333 int i = 0; 334 if (length > 3) { 335 if (a[aFromIndex] != b[bFromIndex]) 336 return 0; 337 int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE); 338 int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE); 339 i = vectorizedMismatch( 340 a, aOffset, 341 b, bOffset, 342 length, LOG2_ARRAY_CHAR_INDEX_SCALE); 343 if (i >= 0) 344 return i; 345 i = length - ~i; 346 } 347 for (; i < length; i++) { 348 if (a[aFromIndex + i] != b[bFromIndex + i]) 349 return i; 350 } 351 return -1; 352 } 353 354 355 // Shorts 356 357 public static int mismatch(short[] a, 358 short[] b, 359 int length) { 360 int i = 0; 361 if (length > 3) { 362 if (a[0] != b[0]) 363 return 0; 364 i = vectorizedMismatch( 365 a, Unsafe.ARRAY_SHORT_BASE_OFFSET, 366 b, Unsafe.ARRAY_SHORT_BASE_OFFSET, 367 length, LOG2_ARRAY_SHORT_INDEX_SCALE); 368 if (i >= 0) 369 return i; 370 i = length - ~i; 371 } 372 for (; i < length; i++) { 373 if (a[i] != b[i]) 374 return i; 375 } 376 return -1; 377 } 378 379 public static int mismatch(short[] a, int aFromIndex, 380 short[] b, int bFromIndex, 381 int length) { 382 int i = 0; 383 if (length > 3) { 384 if (a[aFromIndex] != b[bFromIndex]) 385 return 0; 386 int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE); 387 int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE); 388 i = vectorizedMismatch( 389 a, aOffset, 390 b, bOffset, 391 length, LOG2_ARRAY_SHORT_INDEX_SCALE); 392 if (i >= 0) 393 return i; 394 i = length - ~i; 395 } 396 for (; i < length; i++) { 397 if (a[aFromIndex + i] != b[bFromIndex + i]) 398 return i; 399 } 400 return -1; 401 } 402 403 404 // Ints 405 406 public static int mismatch(int[] a, 407 int[] b, 408 int length) { 409 int i = 0; 410 if (length > 1) { 411 if (a[0] != b[0]) 412 return 0; 413 i = vectorizedMismatch( 414 a, Unsafe.ARRAY_INT_BASE_OFFSET, 415 b, Unsafe.ARRAY_INT_BASE_OFFSET, 416 length, LOG2_ARRAY_INT_INDEX_SCALE); 417 if (i >= 0) 418 return i; 419 i = length - ~i; 420 } 421 for (; i < length; i++) { 422 if (a[i] != b[i]) 423 return i; 424 } 425 return -1; 426 } 427 428 public static int mismatch(int[] a, int aFromIndex, 429 int[] b, int bFromIndex, 430 int length) { 431 int i = 0; 432 if (length > 1) { 433 if (a[aFromIndex] != b[bFromIndex]) 434 return 0; 435 int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE); 436 int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE); 437 i = vectorizedMismatch( 438 a, aOffset, 439 b, bOffset, 440 length, LOG2_ARRAY_INT_INDEX_SCALE); 441 if (i >= 0) 442 return i; 443 i = length - ~i; 444 } 445 for (; i < length; i++) { 446 if (a[aFromIndex + i] != b[bFromIndex + i]) 447 return i; 448 } 449 return -1; 450 } 451 452 453 // Floats 454 455 public static int mismatch(float[] a, 456 float[] b, 457 int length) { 458 return mismatch(a, 0, b, 0, length); 459 } 460 461 public static int mismatch(float[] a, int aFromIndex, 462 float[] b, int bFromIndex, 463 int length) { 464 int i = 0; 465 if (length > 1) { 466 if (Float.floatToRawIntBits(a[aFromIndex]) == Float.floatToRawIntBits(b[bFromIndex])) { 467 int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE); 468 int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE); 469 i = vectorizedMismatch( 470 a, aOffset, 471 b, bOffset, 472 length, LOG2_ARRAY_FLOAT_INDEX_SCALE); 473 } 474 // Mismatched 475 if (i >= 0) { 476 // Check if mismatch is not associated with two NaN values 477 if (!Float.isNaN(a[aFromIndex + i]) || !Float.isNaN(b[bFromIndex + i])) 478 return i; 479 480 // Mismatch on two different NaN values that are normalized to match 481 // Fall back to slow mechanism 482 // ISSUE: Consider looping over vectorizedMismatch adjusting ranges 483 // However, requires that returned value be relative to input ranges 484 i++; 485 } 486 // Matched 487 else { 488 i = length - ~i; 489 } 490 } 491 for (; i < length; i++) { 492 if (Float.floatToIntBits(a[aFromIndex + i]) != Float.floatToIntBits(b[bFromIndex + i])) 493 return i; 494 } 495 return -1; 496 } 497 498 // 64 bit sizes 499 500 // Long 501 502 public static int mismatch(long[] a, 503 long[] b, 504 int length) { 505 if (length == 0) { 506 return -1; 507 } 508 if (a[0] != b[0]) 509 return 0; 510 int i = vectorizedMismatch( 511 a, Unsafe.ARRAY_LONG_BASE_OFFSET, 512 b, Unsafe.ARRAY_LONG_BASE_OFFSET, 513 length, LOG2_ARRAY_LONG_INDEX_SCALE); 514 return i >= 0 ? i : -1; 515 } 516 517 public static int mismatch(long[] a, int aFromIndex, 518 long[] b, int bFromIndex, 519 int length) { 520 if (length == 0) { 521 return -1; 522 } 523 if (a[aFromIndex] != b[bFromIndex]) 524 return 0; 525 int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE); 526 int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE); 527 int i = vectorizedMismatch( 528 a, aOffset, 529 b, bOffset, 530 length, LOG2_ARRAY_LONG_INDEX_SCALE); 531 return i >= 0 ? i : -1; 532 } 533 534 535 // Double 536 537 public static int mismatch(double[] a, 538 double[] b, 539 int length) { 540 return mismatch(a, 0, b, 0, length); 541 } 542 543 public static int mismatch(double[] a, int aFromIndex, 544 double[] b, int bFromIndex, 545 int length) { 546 if (length == 0) { 547 return -1; 548 } 549 int i = 0; 550 if (Double.doubleToRawLongBits(a[aFromIndex]) == Double.doubleToRawLongBits(b[bFromIndex])) { 551 int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE); 552 int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE); 553 i = vectorizedMismatch( 554 a, aOffset, 555 b, bOffset, 556 length, LOG2_ARRAY_DOUBLE_INDEX_SCALE); 557 } 558 if (i >= 0) { 559 // Check if mismatch is not associated with two NaN values 560 if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i])) 561 return i; 562 563 // Mismatch on two different NaN values that are normalized to match 564 // Fall back to slow mechanism 565 // ISSUE: Consider looping over vectorizedMismatch adjusting ranges 566 // However, requires that returned value be relative to input ranges 567 i++; 568 for (; i < length; i++) { 569 if (Double.doubleToLongBits(a[aFromIndex + i]) != Double.doubleToLongBits(b[bFromIndex + i])) 570 return i; 571 } 572 } 573 574 return -1; 575 } 576 577 /** 578 * The maximum size of array to allocate (unless necessary). 579 * Some VMs reserve some header words in an array. 580 * Attempts to allocate larger arrays may result in 581 * OutOfMemoryError: Requested array size exceeds VM limit 582 */ 583 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 584 585 /** 586 * Calculates new size of an array to be reallocated. 587 * 588 * The result will be at least {@code oldCapacity + growAtLeastBy}. 589 * The result can be greater (normally, up to 590 * {@code oldCapacity + preferredGrowBy}). 591 * This function will not return values greater than 592 * {@link #MAX_ARRAY_SIZE} unless necessary. 593 * 594 * @param oldCapacity current size of the array 595 * @param growAtLeastBy minimum required growth of the array size 596 * @param preferredGrowBy preferred growth of the array size 597 * @return the new size of the array 598 * @throws OutOfMemoryError if increasing {@code oldCapacity) by 599 * {@code growAtLeastBy} overflows. 600 */ 601 public static int newCapacity(int oldCapacity, 602 int growAtLeastBy, 603 int preferredGrowBy) { 604 assert oldCapacity >= 0; 605 assert growAtLeastBy > 0; 606 607 int newCapacity = oldCapacity + preferredGrowBy; 608 if (preferredGrowBy < growAtLeastBy) { 609 newCapacity = oldCapacity + growAtLeastBy; 610 } 611 return (newCapacity - MAX_ARRAY_SIZE > 0) 612 ? hugeCapacity(oldCapacity + growAtLeastBy) : newCapacity; 613 } 614 615 private static int hugeCapacity(int minCapacity) { 616 if (minCapacity < 0) { // overflow 617 throw new OutOfMemoryError("Required array size too large"); 618 } 619 return (minCapacity > MAX_ARRAY_SIZE) 620 ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 621 } 622 }