1 /* 2 * Copyright (c) 1997, 2024, 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 26 package org.openjdk.bench.valhalla.sandbox.corelibs; 27 28 import java.util.Arrays; 29 import java.util.ConcurrentModificationException; 30 import java.util.Objects; 31 import java.util.NoSuchElementException; 32 import java.util.function.Consumer; 33 import java.util.function.IntConsumer; 34 import java.util.function.Predicate; 35 import java.util.function.UnaryOperator; 36 37 /** 38 * Resizable-array implementation like {@code ArrayList<PrimitiveInt>}. 39 */ 40 public class ArrayListPrimitiveInt 41 // extends AbstractList<E> 42 // implements List<int>, RandomAccess, Cloneable, java.io.Serializable 43 { 44 @java.io.Serial 45 private static final long serialVersionUID = 8683452581122892189L; 46 47 /** 48 * Default initial capacity. 49 */ 50 private static final int DEFAULT_CAPACITY = 10; 51 52 /** 53 * Shared empty array instance used for empty instances. 54 */ 55 private static final PrimitiveInt[] EMPTY_ELEMENTDATA = {}; 56 57 /** 58 * Shared empty array instance used for default sized empty instances. We 59 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when 60 * first element is added. 61 */ 62 private static final PrimitiveInt[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new PrimitiveInt[0]; 63 64 /** 65 * The array buffer into which the elements of the ArrayList are stored. 66 * The capacity of the ArrayList is the length of this array buffer. Any 67 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 68 * will be expanded to DEFAULT_CAPACITY when the first element is added. 69 */ 70 transient PrimitiveInt[] elementData; // non-private to simplify nested class access 71 72 protected transient int modCount = 0; 73 74 /** 75 * The size of the ArrayList (the number of elements it contains). 76 * 77 * @serial 78 */ 79 private int size; 80 81 /** 82 * Constructs an empty list with the specified initial capacity. 83 * 84 * @param initialCapacity the initial capacity of the list 85 * @throws IllegalArgumentException if the specified initial capacity 86 * is negative 87 */ 88 public ArrayListPrimitiveInt(int initialCapacity) { 89 if (initialCapacity > 0) { 90 this.elementData = new PrimitiveInt[initialCapacity]; 91 } else if (initialCapacity == 0) { 92 this.elementData = EMPTY_ELEMENTDATA; 93 } else { 94 throw new IllegalArgumentException("Illegal Capacity: "+ 95 initialCapacity); 96 } 97 } 98 99 /** 100 * Constructs an empty list with an initial capacity of ten. 101 */ 102 public ArrayListPrimitiveInt() { 103 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 104 } 105 106 /** 107 * Trims the capacity of this {@code ArrayList} instance to be the 108 * list's current size. An application can use this operation to minimize 109 * the storage of an {@code ArrayList} instance. 110 */ 111 public void trimToSize() { 112 modCount++; 113 if (size < elementData.length) { 114 elementData = (size == 0) 115 ? EMPTY_ELEMENTDATA 116 : (PrimitiveInt[])Arrays.copyOf(elementData, size); 117 } 118 } 119 120 /** 121 * Increases the capacity of this {@code ArrayList} instance, if 122 * necessary, to ensure that it can hold at least the number of elements 123 * specified by the minimum capacity argument. 124 * 125 * @param minCapacity the desired minimum capacity 126 */ 127 public void ensureCapacity(int minCapacity) { 128 if (minCapacity > elementData.length 129 && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 130 && minCapacity <= DEFAULT_CAPACITY)) { 131 modCount++; 132 grow(minCapacity); 133 } 134 } 135 136 /** 137 * Increases the capacity to ensure that it can hold at least the 138 * number of elements specified by the minimum capacity argument. 139 * 140 * @param minCapacity the desired minimum capacity 141 * @throws OutOfMemoryError if minCapacity is less than zero 142 */ 143 private PrimitiveInt[] grow(int minCapacity) { 144 int oldCapacity = elementData.length; 145 if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 146 int newCapacity = newLength(oldCapacity, 147 minCapacity - oldCapacity, /* minimum growth */ 148 oldCapacity >> 1 /* preferred growth */); 149 return elementData = (PrimitiveInt[])Arrays.copyOf(elementData, newCapacity); 150 } else { 151 return elementData = new PrimitiveInt[Math.max(DEFAULT_CAPACITY, minCapacity)]; 152 } 153 } 154 155 private PrimitiveInt[] grow() { 156 return grow(size + 1); 157 } 158 159 /** 160 * Returns the number of elements in this list. 161 * 162 * @return the number of elements in this list 163 */ 164 public int size() { 165 return size; 166 } 167 168 /** 169 * Returns {@code true} if this list contains no elements. 170 * 171 * @return {@code true} if this list contains no elements 172 */ 173 public boolean isEmpty() { 174 return size == 0; 175 } 176 177 /** 178 * Returns {@code true} if this list contains the specified element. 179 * More formally, returns {@code true} if and only if this list contains 180 * at least one element {@code e} such that 181 * {@code Objects.equals(o, e)}. 182 * 183 * @param o element whose presence in this list is to be tested 184 * @return {@code true} if this list contains the specified element 185 */ 186 public boolean contains(PrimitiveInt o) { 187 return indexOf(o) >= 0; 188 } 189 190 /** 191 * Returns the index of the first occurrence of the specified element 192 * in this list, or -1 if this list does not contain the element. 193 * More formally, returns the lowest index {@code i} such that 194 * {@code Objects.equals(o, get(i))}, 195 * or -1 if there is no such index. 196 */ 197 public int indexOf(PrimitiveInt o) { 198 return indexOfRange(o, 0, size); 199 } 200 201 int indexOfRange(PrimitiveInt o, int start, int end) { 202 PrimitiveInt[] es = elementData; 203 { 204 for (int i = start; i < end; i++) { 205 if (o == es[i]) { 206 return i; 207 } 208 } 209 } 210 return -1; 211 } 212 213 /** 214 * Returns the index of the last occurrence of the specified element 215 * in this list, or -1 if this list does not contain the element. 216 * More formally, returns the highest index {@code i} such that 217 * {@code Objects.equals(o, get(i))}, 218 * or -1 if there is no such index. 219 */ 220 public int lastIndexOf(PrimitiveInt o) { 221 return lastIndexOfRange(o, 0, size); 222 } 223 224 int lastIndexOfRange(PrimitiveInt o, int start, int end) { 225 PrimitiveInt[] es = elementData; 226 { 227 for (int i = end - 1; i >= start; i--) { 228 if (o == es[i]) { 229 return i; 230 } 231 } 232 } 233 return -1; 234 } 235 236 /** 237 * Returns an array containing all of the elements in this list 238 * in proper sequence (from first to last element). 239 * 240 * <p>The returned array will be "safe" in that no references to it are 241 * maintained by this list. (In other words, this method must allocate 242 * a new array). The caller is thus free to modify the returned array. 243 * 244 * <p>This method acts as bridge between array-based and collection-based 245 * APIs. 246 * 247 * @return an array containing all of the elements in this list in 248 * proper sequence 249 */ 250 public PrimitiveInt[] toArray() { 251 return (PrimitiveInt[])Arrays.copyOf(elementData, size); 252 } 253 254 /** 255 * Returns an array containing all of the elements in this list in proper 256 * sequence (from first to last element); the runtime type of the returned 257 * array is that of the specified array. If the list fits in the 258 * specified array, it is returned therein. Otherwise, a new array is 259 * allocated with the runtime type of the specified array and the size of 260 * this list. 261 * 262 * <p>If the list fits in the specified array with room to spare 263 * (i.e., the array has more elements than the list), the element in 264 * the array immediately following the end of the collection is set to 265 * {@code null}. (This is useful in determining the length of the 266 * list <i>only</i> if the caller knows that the list does not contain 267 * any null elements.) 268 * 269 * @param a the array into which the elements of the list are to 270 * be stored, if it is big enough; otherwise, a new array of the 271 * same runtime type is allocated for this purpose. 272 * @return an array containing the elements of the list 273 * @throws ArrayStoreException if the runtime type of the specified array 274 * is not a supertype of the runtime type of every element in 275 * this list 276 * @throws NullPointerException if the specified array is null 277 */ 278 // @SuppressWarnings("unchecked") 279 // public <T> T[] toArray(T[] a) { 280 // if (a.length < size) 281 // // Make a new array of a's runtime type, but my contents: 282 // return (T[]) Arrays.copyOf(elementData, size, a.getClass()); 283 // System.arraycopy(elementData, 0, a, 0, size); 284 // if (a.length > size) 285 // a[size] = null; 286 // return a; 287 // } 288 289 // Positional Access Operations 290 291 @SuppressWarnings("unchecked") 292 PrimitiveInt elementData(int index) { 293 return (PrimitiveInt) elementData[index]; 294 } 295 296 @SuppressWarnings("unchecked") 297 static PrimitiveInt elementAt(PrimitiveInt[] es, int index) { 298 return es[index]; 299 } 300 301 /** 302 * Returns the element at the specified position in this list. 303 * 304 * @param index index of the element to return 305 * @return the element at the specified position in this list 306 * @throws IndexOutOfBoundsException {@inheritDoc} 307 */ 308 public PrimitiveInt get(int index) { 309 Objects.checkIndex(index, size); 310 return elementData(index); 311 } 312 313 /** 314 * Replaces the element at the specified position in this list with 315 * the specified element. 316 * 317 * @param index index of the element to replace 318 * @param element element to be stored at the specified position 319 * @return the element previously at the specified position 320 * @throws IndexOutOfBoundsException {@inheritDoc} 321 */ 322 public PrimitiveInt set(int index, PrimitiveInt element) { 323 Objects.checkIndex(index, size); 324 PrimitiveInt oldValue = elementData(index); 325 elementData[index] = element; 326 return oldValue; 327 } 328 329 /** 330 * This helper method split out from add(int) to keep method 331 * bytecode size under 35 (the -XX:MaxInlineSize default value), 332 * which helps when add(int) is called in a C1-compiled loop. 333 */ 334 private void add(PrimitiveInt e, PrimitiveInt[] elementData, int s) { 335 if (s == elementData.length) 336 elementData = grow(); 337 elementData[s] = e; 338 size = s + 1; 339 } 340 341 /** 342 * Appends the specified element to the end of this list. 343 * 344 * @param e element to be appended to this list 345 * @return {@code true} (as specified by {@link Collection#add}) 346 */ 347 public boolean add(PrimitiveInt e) { 348 modCount++; 349 add(e, elementData, size); 350 return true; 351 } 352 353 /** 354 * Inserts the specified element at the specified position in this 355 * list. Shifts the element currently at that position (if any) and 356 * any subsequent elements to the right (adds one to their indices). 357 * 358 * @param index index at which the specified element is to be inserted 359 * @param element element to be inserted 360 * @throws IndexOutOfBoundsException {@inheritDoc} 361 */ 362 public void add(int index, PrimitiveInt element) { 363 rangeCheckForAdd(index); 364 modCount++; 365 final int s; 366 PrimitiveInt[] elementData; 367 if ((s = size) == (elementData = this.elementData).length) 368 elementData = grow(); 369 System.arraycopy(elementData, index, 370 elementData, index + 1, 371 s - index); 372 elementData[index] = element; 373 size = s + 1; 374 } 375 376 /** 377 * Removes the element at the specified position in this list. 378 * Shifts any subsequent elements to the left (subtracts one from their 379 * indices). 380 * 381 * @param index the index of the element to be removed 382 * @return the element that was removed from the list 383 * @throws IndexOutOfBoundsException {@inheritDoc} 384 */ 385 public PrimitiveInt remove(int index) { 386 Objects.checkIndex(index, size); 387 final PrimitiveInt[] es = elementData; 388 389 PrimitiveInt oldValue = (PrimitiveInt) es[index]; 390 fastRemove(es, index); 391 392 return oldValue; 393 } 394 395 /** 396 * {@inheritDoc} 397 */ 398 public boolean equals(Object o) { 399 if (o == this) { 400 return true; 401 } 402 403 if (!(o instanceof ArrayListPrimitiveInt)) { 404 return false; 405 } 406 407 final int expectedModCount = modCount; 408 // ArrayList can be subclassed and given arbitrary behavior, but we can 409 // still deal with the common case where o is ArrayList precisely 410 boolean equal = equalsArrayList((ArrayListPrimitiveInt) o); 411 412 checkForComodification(expectedModCount); 413 return equal; 414 } 415 416 private boolean equalsArrayList(ArrayListPrimitiveInt other) { 417 final int otherModCount = other.modCount; 418 final int s = size; 419 boolean equal; 420 if (equal = (s == other.size)) { 421 final PrimitiveInt[] otherEs = other.elementData; 422 final PrimitiveInt[] es = elementData; 423 if (s > es.length || s > otherEs.length) { 424 throw new ConcurrentModificationException(); 425 } 426 for (int i = 0; i < s; i++) { 427 if (es[i] != otherEs[i]) { 428 equal = false; 429 break; 430 } 431 } 432 } 433 other.checkForComodification(otherModCount); 434 return equal; 435 } 436 437 private void checkForComodification(final int expectedModCount) { 438 if (modCount != expectedModCount) { 439 throw new ConcurrentModificationException(); 440 } 441 } 442 443 /** 444 * {@inheritDoc} 445 */ 446 public int hashCode() { 447 int expectedModCount = modCount; 448 int hash = hashCodeRange(0, size); 449 checkForComodification(expectedModCount); 450 return hash; 451 } 452 453 int hashCodeRange(int from, int to) { 454 final PrimitiveInt[] es = elementData; 455 if (to > es.length) { 456 throw new ConcurrentModificationException(); 457 } 458 int hashCode = 1; 459 for (int i = from; i < to; i++) { 460 PrimitiveInt e = es[i]; 461 hashCode = 31 * hashCode + e.hashCode(); 462 } 463 return hashCode; 464 } 465 466 /** 467 * Removes the first occurrence of the specified element from this list, 468 * if it is present. If the list does not contain the element, it is 469 * unchanged. More formally, removes the element with the lowest index 470 * {@code i} such that 471 * {@code Objects.equals(o, get(i))} 472 * (if such an element exists). Returns {@code true} if this list 473 * contained the specified element (or equivalently, if this list 474 * changed as a result of the call). 475 * 476 * @param o element to be removed from this list, if present 477 * @return {@code true} if this list contained the specified element 478 */ 479 public boolean removeC(PrimitiveInt o) { 480 final PrimitiveInt[] es = elementData; 481 final int size = this.size; 482 int i = 0; 483 found: 484 { 485 // if (o == null) { 486 // for (; i < size; i++) 487 // if (es[i] == null) 488 // break found; 489 // } else 490 { 491 for (; i < size; i++) 492 if (o == es[i]) 493 break found; 494 } 495 return false; 496 } 497 fastRemove(es, i); 498 return true; 499 } 500 501 /** 502 * Private remove method that skips bounds checking and does not 503 * return the value removed. 504 */ 505 private void fastRemove(PrimitiveInt[] es, int i) { 506 modCount++; 507 final int newSize; 508 if ((newSize = size - 1) > i) 509 System.arraycopy(es, i + 1, es, i, newSize - i); 510 es[size = newSize] = new PrimitiveInt(); 511 } 512 513 /** 514 * Removes all of the elements from this list. The list will 515 * be empty after this call returns. 516 */ 517 public void clear() { 518 modCount++; 519 final PrimitiveInt[] es = elementData; 520 for (int to = size, i = size = 0; i < to; i++) 521 es[i] = new PrimitiveInt(); 522 } 523 524 /** 525 * Removes from this list all of the elements whose index is between 526 * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. 527 * Shifts any succeeding elements to the left (reduces their index). 528 * This call shortens the list by {@code (toIndex - fromIndex)} elements. 529 * (If {@code toIndex==fromIndex}, this operation has no effect.) 530 * 531 * @throws IndexOutOfBoundsException if {@code fromIndex} or 532 * {@code toIndex} is out of range 533 * ({@code fromIndex < 0 || 534 * toIndex > size() || 535 * toIndex < fromIndex}) 536 */ 537 protected void removeRange(int fromIndex, int toIndex) { 538 if (fromIndex > toIndex) { 539 throw new IndexOutOfBoundsException( 540 outOfBoundsMsg(fromIndex, toIndex)); 541 } 542 modCount++; 543 shiftTailOverGap(elementData, fromIndex, toIndex); 544 } 545 546 /** Erases the gap from lo to hi, by sliding down following elements. */ 547 private void shiftTailOverGap(PrimitiveInt[] es, int lo, int hi) { 548 System.arraycopy(es, hi, es, lo, size - hi); 549 for (int to = size, i = (size -= hi - lo); i < to; i++) 550 es[i] = new PrimitiveInt(); 551 } 552 553 /** 554 * A version of rangeCheck used by add and addAll. 555 */ 556 private void rangeCheckForAdd(int index) { 557 if (index > size || index < 0) 558 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); 559 } 560 561 /** 562 * Constructs an IndexOutOfBoundsException detail message. 563 * Of the many possible refactorings of the error handling code, 564 * this "outlining" performs best with both server and client VMs. 565 */ 566 private String outOfBoundsMsg(int index) { 567 return "Index: "+index+", Size: "+size; 568 } 569 570 /** 571 * A version used in checking (fromIndex > toIndex) condition 572 */ 573 private static String outOfBoundsMsg(int fromIndex, int toIndex) { 574 return "From Index: " + fromIndex + " > To Index: " + toIndex; 575 } 576 577 /** 578 * Returns an iterator over the elements in this list in proper sequence. 579 * 580 * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>. 581 * 582 * @return an iterator over the elements in this list in proper sequence 583 */ 584 public PrimitiveIntItr iterator() { 585 return new PrimitiveIntItr(); 586 } 587 588 /** 589 * An optimized version of AbstractList.Itr 590 */ 591 private class PrimitiveIntItr { 592 int cursor; // index of next element to return 593 int lastRet = -1; // index of last element returned; -1 if no such 594 int expectedModCount = modCount; 595 596 // prevent creating a synthetic constructor 597 PrimitiveIntItr() {} 598 599 public boolean hasNext() { 600 return cursor != size; 601 } 602 603 @SuppressWarnings("unchecked") 604 public PrimitiveInt next() { 605 checkForComodification(); 606 int i = cursor; 607 if (i >= size) 608 throw new NoSuchElementException(); 609 PrimitiveInt[] elementData = ArrayListPrimitiveInt.this.elementData; 610 if (i >= elementData.length) 611 throw new ConcurrentModificationException(); 612 cursor = i + 1; 613 return (PrimitiveInt) elementData[lastRet = i]; 614 } 615 616 public void remove() { 617 if (lastRet < 0) 618 throw new IllegalStateException(); 619 checkForComodification(); 620 621 try { 622 ArrayListPrimitiveInt.this.remove(lastRet); 623 cursor = lastRet; 624 lastRet = -1; 625 expectedModCount = modCount; 626 } catch (IndexOutOfBoundsException ex) { 627 throw new ConcurrentModificationException(); 628 } 629 } 630 631 public void forEachRemaining(Consumer<? super PrimitiveInt> action) { 632 Objects.requireNonNull(action); 633 final int size = ArrayListPrimitiveInt.this.size; 634 int i = cursor; 635 if (i < size) { 636 final PrimitiveInt[] es = elementData; 637 if (i >= es.length) 638 throw new ConcurrentModificationException(); 639 for (; i < size && modCount == expectedModCount; i++) 640 action.accept(elementAt(es, i)); 641 // update once at end to reduce heap write traffic 642 cursor = i; 643 lastRet = i - 1; 644 checkForComodification(); 645 } 646 } 647 648 final void checkForComodification() { 649 if (modCount != expectedModCount) 650 throw new ConcurrentModificationException(); 651 } 652 } 653 654 static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8; 655 656 static int newLength(int oldLength, int minGrowth, int prefGrowth) { 657 // assert oldLength >= 0 658 // assert minGrowth > 0 659 660 int newLength = Math.max(minGrowth, prefGrowth) + oldLength; 661 if (newLength - MAX_ARRAY_LENGTH <= 0) { 662 return newLength; 663 } 664 return hugeLength(oldLength, minGrowth); 665 } 666 667 private static int hugeLength(int oldLength, int minGrowth) { 668 int minLength = oldLength + minGrowth; 669 if (minLength < 0) { // overflow 670 throw new OutOfMemoryError("Required array length too large"); 671 } 672 if (minLength <= MAX_ARRAY_LENGTH) { 673 return MAX_ARRAY_LENGTH; 674 } 675 return Integer.MAX_VALUE; 676 } 677 678 }