< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java

Print this page




  35 import java.util.Iterator;
  36 import java.util.List;
  37 import jdk.dynalink.CallSiteDescriptor;
  38 import jdk.dynalink.linker.GuardedInvocation;
  39 import jdk.dynalink.linker.LinkRequest;
  40 import jdk.nashorn.internal.codegen.CompilerConstants;
  41 import jdk.nashorn.internal.codegen.types.Type;
  42 import jdk.nashorn.internal.objects.Global;
  43 import jdk.nashorn.internal.runtime.JSType;
  44 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  45 import jdk.nashorn.internal.runtime.ScriptRuntime;
  46 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
  47 
  48 /**
  49  * ArrayData - abstraction for wrapping array elements
  50  */
  51 public abstract class ArrayData {
  52     /** Minimum chunk size for underlying arrays */
  53     protected static final int CHUNK_SIZE = 32;
  54 
  55     /** Mask for getting a chunk */
  56     protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
  57 
  58     /** Untouched data - still link callsites as IntArrayData, but expands to
  59      *  a proper ArrayData when we try to write to it */
  60     public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
  61 
  62     /**
  63      * Length of the array data. Not necessarily length of the wrapped array.
  64      * This is private to ensure that no one in a subclass is able to touch the length
  65      * without going through {@link #setLength}. This is used to implement
  66      * {@link LengthNotWritableFilter}s, ensuring that there are no ways past
  67      * a {@link #setLength} function replaced by a nop
  68      */
  69     private long length;
  70 
  71     /**
  72      * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
  73      * of the wrong type
  74      */
  75     protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
  76 
  77     /**


 147         public ArrayData shiftRight(final int by) {
 148             return this; //always empty or we wouldn't be of this class
 149         }
 150 
 151         @Override
 152         public ArrayData shrink(final long newLength) {
 153             return this;
 154         }
 155 
 156         @Override
 157         public ArrayData set(final int index, final Object value, final boolean strict) {
 158             return toRealArrayData(index).set(index, value, strict);
 159         }
 160 
 161         @Override
 162         public ArrayData set(final int index, final int value, final boolean strict) {
 163             return toRealArrayData(index).set(index, value, strict);
 164         }
 165 
 166         @Override
 167         public ArrayData set(final int index, final long value, final boolean strict) {
 168             return toRealArrayData(index).set(index, value, strict);
 169         }
 170 
 171         @Override
 172         public ArrayData set(final int index, final double value, final boolean strict) {
 173             return toRealArrayData(index).set(index, value, strict);
 174         }
 175 
 176         @Override
 177         public int getInt(final int index) {
 178             throw new ArrayIndexOutOfBoundsException(index); //empty
 179         }
 180 
 181         @Override
 182         public long getLong(final int index) {
 183             throw new ArrayIndexOutOfBoundsException(index); //empty
 184         }
 185 
 186         @Override
 187         public double getDouble(final int index) {
 188             throw new ArrayIndexOutOfBoundsException(index); //empty
 189         }
 190 
 191         @Override
 192         public Object getObject(final int index) {
 193             throw new ArrayIndexOutOfBoundsException(index); //empty
 194         }
 195 
 196         @Override
 197         public boolean has(final int index) {
 198             return false; //empty
 199         }
 200 
 201         @Override
 202         public Object pop() {
 203             return ScriptRuntime.UNDEFINED;
 204         }
 205 
 206         @Override


 271      */
 272     protected static void throwUnwarranted(final ArrayData data, final int programPoint, final int index) {
 273         throw new UnwarrantedOptimismException(data.getObject(index), programPoint);
 274     }
 275 
 276     /**
 277      * Align an array size up to the nearest array chunk size
 278      * @param size size required
 279      * @return size given, always &gt;= size
 280      */
 281     protected static int alignUp(final int size) {
 282         return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
 283     }
 284 
 285     /**
 286      * Factory method for unspecified array with given length - start as int array data
 287      *
 288      * @param length the initial length
 289      * @return ArrayData
 290      */
 291     public static ArrayData allocate(final int length) {
 292         if (length == 0) {
 293             return new IntArrayData();
 294         } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
 295             return new SparseArrayData(EMPTY_ARRAY, length);
 296         } else {
 297             return new DeletedRangeArrayFilter(new IntArrayData(length), 0, length - 1);
 298         }
 299     }
 300 
 301     /**
 302      * Factory method for unspecified given an array object
 303      *
 304      * @param  array the array
 305      * @return ArrayData wrapping this array
 306      */
 307     public static ArrayData allocate(final Object array) {
 308         final Class<?> clazz = array.getClass();
 309 
 310         if (clazz == int[].class) {
 311             return new IntArrayData((int[])array, ((int[])array).length);
 312         } else if (clazz == long[].class) {
 313             return new LongArrayData((long[])array, ((long[])array).length);
 314         } else if (clazz == double[].class) {
 315             return new NumberArrayData((double[])array, ((double[])array).length);
 316         } else {
 317             return new ObjectArrayData((Object[])array, ((Object[])array).length);
 318         }
 319     }
 320 
 321     /**
 322      * Allocate an ArrayData wrapping a given array
 323      *
 324      * @param array the array to use for initial elements
 325      * @return the ArrayData
 326      */
 327     public static ArrayData allocate(final int[] array) {
 328          return new IntArrayData(array, array.length);
 329     }
 330 
 331     /**
 332      * Allocate an ArrayData wrapping a given array
 333      *
 334      * @param array the array to use for initial elements
 335      * @return the ArrayData
 336      */
 337     public static ArrayData allocate(final long[] array) {
 338         return new LongArrayData(array, array.length);
 339     }
 340 
 341     /**
 342      * Allocate an ArrayData wrapping a given array
 343      *
 344      * @param array the array to use for initial elements
 345      * @return the ArrayData
 346      */
 347     public static ArrayData allocate(final double[] array) {
 348         return new NumberArrayData(array, array.length);
 349     }
 350 
 351     /**
 352      * Allocate an ArrayData wrapping a given array
 353      *
 354      * @param array the array to use for initial elements
 355      * @return the ArrayData
 356      */
 357     public static ArrayData allocate(final Object[] array) {
 358         return new ObjectArrayData(array, array.length);
 359     }
 360 
 361     /**
 362      * Allocate an ArrayData wrapping a given nio ByteBuffer
 363      *
 364      * @param buf the nio ByteBuffer to wrap
 365      * @return the ArrayData
 366      */


 520      * Set an object value at a given index
 521      *
 522      * @param index the index
 523      * @param value the value
 524      * @param strict are we in strict mode
 525      * @return new array data (or same)
 526      */
 527     public abstract ArrayData set(final int index, final Object value, final boolean strict);
 528 
 529     /**
 530      * Set an int value at a given index
 531      *
 532      * @param index the index
 533      * @param value the value
 534      * @param strict are we in strict mode
 535      * @return new array data (or same)
 536      */
 537     public abstract ArrayData set(final int index, final int value, final boolean strict);
 538 
 539     /**
 540      * Set a long value at a given index
 541      *
 542      * @param index the index
 543      * @param value the value
 544      * @param strict are we in strict mode
 545      * @return new array data (or same)
 546      */
 547     public abstract ArrayData set(final int index, final long value, final boolean strict);
 548 
 549     /**
 550      * Set an double value at a given index
 551      *
 552      * @param index the index
 553      * @param value the value
 554      * @param strict are we in strict mode
 555      * @return new array data (or same)
 556      */
 557     public abstract ArrayData set(final int index, final double value, final boolean strict);
 558 
 559     /**
 560      * Set an empty value at a given index. Should only affect Object array.
 561      *
 562      * @param index the index
 563      * @return new array data (or same)
 564      */
 565     public ArrayData setEmpty(final int index) {
 566         // Do nothing.
 567         return this;
 568     }
 569 


 592      * {@link UnwarrantedOptimismException}, this type is used as the actual type of the return value.
 593      * @return the optimistic type of this array data.
 594      */
 595     public Type getOptimisticType() {
 596         return Type.OBJECT;
 597     }
 598 
 599     /**
 600      * Get optimistic int - default is that it's impossible. Overridden
 601      * by arrays that actually represents ints
 602      *
 603      * @param index        the index
 604      * @param programPoint program point
 605      * @return the value
 606      */
 607     public int getIntOptimistic(final int index, final int programPoint) {
 608         throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
 609     }
 610 
 611     /**
 612      * Get a long value from a given index
 613      *
 614      * @param index the index
 615      * @return the value
 616      */
 617     public abstract long getLong(final int index);
 618 
 619     /**
 620      * Get optimistic long - default is that it's impossible. Overridden
 621      * by arrays that actually represents longs or narrower
 622      *
 623      * @param index        the index
 624      * @param programPoint program point
 625      * @return the value
 626      */
 627     public long getLongOptimistic(final int index, final int programPoint) {
 628         throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
 629     }
 630 
 631     /**
 632      * Get a double value from a given index
 633      *
 634      * @param index the index
 635      * @return the value
 636      */
 637     public abstract double getDouble(final int index);
 638 
 639     /**
 640      * Get optimistic double - default is that it's impossible. Overridden
 641      * by arrays that actually represents doubles or narrower
 642      *
 643      * @param index        the index
 644      * @param programPoint program point
 645      * @return the value
 646      */
 647     public double getDoubleOptimistic(final int index, final int programPoint) {
 648         throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
 649     }
 650 
 651     /**


 804      * @param start start index of splice operation
 805      * @param removed number of removed elements
 806      * @param added number of added elements
 807      * @throws UnsupportedOperationException if fast splice is not supported for the class or arguments.
 808      * @return new arraydata, but this never happens because we always throw an exception
 809      */
 810     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
 811         throw new UnsupportedOperationException();
 812     }
 813 
 814     static Class<?> widestType(final Object... items) {
 815         assert items.length > 0;
 816 
 817         Class<?> widest = Integer.class;
 818 
 819         for (final Object item : items) {
 820             if (item == null) {
 821                 return Object.class;
 822             }
 823             final Class<?> itemClass = item.getClass();
 824             if (itemClass == Long.class) {
 825                 if (widest == Integer.class) {
 826                     widest = Long.class;
 827                 }
 828             } else if (itemClass == Double.class || itemClass == Float.class) {
 829                 if (widest == Integer.class || widest == Long.class) {
 830                     widest = Double.class;
 831                 }
 832             } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) {
 833                 return Object.class;
 834             }
 835         }
 836 
 837         return widest;
 838     }
 839 
 840     /**
 841      * Return a list of keys in the array for the iterators
 842      * @return iterator key list
 843      */
 844     protected List<Long> computeIteratorKeys() {
 845         final List<Long> keys = new ArrayList<>();
 846 
 847         final long len = length();
 848         for (long i = 0L; i < len; i = nextIndex(i)) {
 849             if (has((int)i)) {




  35 import java.util.Iterator;
  36 import java.util.List;
  37 import jdk.dynalink.CallSiteDescriptor;
  38 import jdk.dynalink.linker.GuardedInvocation;
  39 import jdk.dynalink.linker.LinkRequest;
  40 import jdk.nashorn.internal.codegen.CompilerConstants;
  41 import jdk.nashorn.internal.codegen.types.Type;
  42 import jdk.nashorn.internal.objects.Global;
  43 import jdk.nashorn.internal.runtime.JSType;
  44 import jdk.nashorn.internal.runtime.PropertyDescriptor;
  45 import jdk.nashorn.internal.runtime.ScriptRuntime;
  46 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
  47 
  48 /**
  49  * ArrayData - abstraction for wrapping array elements
  50  */
  51 public abstract class ArrayData {
  52     /** Minimum chunk size for underlying arrays */
  53     protected static final int CHUNK_SIZE = 32;
  54 



  55     /** Untouched data - still link callsites as IntArrayData, but expands to
  56      *  a proper ArrayData when we try to write to it */
  57     public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
  58 
  59     /**
  60      * Length of the array data. Not necessarily length of the wrapped array.
  61      * This is private to ensure that no one in a subclass is able to touch the length
  62      * without going through {@link #setLength}. This is used to implement
  63      * {@link LengthNotWritableFilter}s, ensuring that there are no ways past
  64      * a {@link #setLength} function replaced by a nop
  65      */
  66     private long length;
  67 
  68     /**
  69      * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
  70      * of the wrong type
  71      */
  72     protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
  73 
  74     /**


 144         public ArrayData shiftRight(final int by) {
 145             return this; //always empty or we wouldn't be of this class
 146         }
 147 
 148         @Override
 149         public ArrayData shrink(final long newLength) {
 150             return this;
 151         }
 152 
 153         @Override
 154         public ArrayData set(final int index, final Object value, final boolean strict) {
 155             return toRealArrayData(index).set(index, value, strict);
 156         }
 157 
 158         @Override
 159         public ArrayData set(final int index, final int value, final boolean strict) {
 160             return toRealArrayData(index).set(index, value, strict);
 161         }
 162 
 163         @Override





 164         public ArrayData set(final int index, final double value, final boolean strict) {
 165             return toRealArrayData(index).set(index, value, strict);
 166         }
 167 
 168         @Override
 169         public int getInt(final int index) {
 170             throw new ArrayIndexOutOfBoundsException(index); //empty
 171         }
 172 
 173         @Override





 174         public double getDouble(final int index) {
 175             throw new ArrayIndexOutOfBoundsException(index); //empty
 176         }
 177 
 178         @Override
 179         public Object getObject(final int index) {
 180             throw new ArrayIndexOutOfBoundsException(index); //empty
 181         }
 182 
 183         @Override
 184         public boolean has(final int index) {
 185             return false; //empty
 186         }
 187 
 188         @Override
 189         public Object pop() {
 190             return ScriptRuntime.UNDEFINED;
 191         }
 192 
 193         @Override


 258      */
 259     protected static void throwUnwarranted(final ArrayData data, final int programPoint, final int index) {
 260         throw new UnwarrantedOptimismException(data.getObject(index), programPoint);
 261     }
 262 
 263     /**
 264      * Align an array size up to the nearest array chunk size
 265      * @param size size required
 266      * @return size given, always &gt;= size
 267      */
 268     protected static int alignUp(final int size) {
 269         return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
 270     }
 271 
 272     /**
 273      * Factory method for unspecified array with given length - start as int array data
 274      *
 275      * @param length the initial length
 276      * @return ArrayData
 277      */
 278     public static ArrayData allocate(final long length) {
 279         if (length == 0L) {
 280             return new IntArrayData();
 281         } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
 282             return new SparseArrayData(EMPTY_ARRAY, length);
 283         } else {
 284             return new DeletedRangeArrayFilter(new IntArrayData((int) length), 0, length - 1);
 285         }
 286     }
 287 
 288     /**
 289      * Factory method for unspecified given an array object
 290      *
 291      * @param  array the array
 292      * @return ArrayData wrapping this array
 293      */
 294     public static ArrayData allocate(final Object array) {
 295         final Class<?> clazz = array.getClass();
 296 
 297         if (clazz == int[].class) {
 298             return new IntArrayData((int[])array, ((int[])array).length);


 299         } else if (clazz == double[].class) {
 300             return new NumberArrayData((double[])array, ((double[])array).length);
 301         } else {
 302             return new ObjectArrayData((Object[])array, ((Object[])array).length);
 303         }
 304     }
 305 
 306     /**
 307      * Allocate an ArrayData wrapping a given array
 308      *
 309      * @param array the array to use for initial elements
 310      * @return the ArrayData
 311      */
 312     public static ArrayData allocate(final int[] array) {
 313          return new IntArrayData(array, array.length);
 314     }
 315 
 316     /**
 317      * Allocate an ArrayData wrapping a given array
 318      *
 319      * @param array the array to use for initial elements
 320      * @return the ArrayData
 321      */










 322     public static ArrayData allocate(final double[] array) {
 323         return new NumberArrayData(array, array.length);
 324     }
 325 
 326     /**
 327      * Allocate an ArrayData wrapping a given array
 328      *
 329      * @param array the array to use for initial elements
 330      * @return the ArrayData
 331      */
 332     public static ArrayData allocate(final Object[] array) {
 333         return new ObjectArrayData(array, array.length);
 334     }
 335 
 336     /**
 337      * Allocate an ArrayData wrapping a given nio ByteBuffer
 338      *
 339      * @param buf the nio ByteBuffer to wrap
 340      * @return the ArrayData
 341      */


 495      * Set an object value at a given index
 496      *
 497      * @param index the index
 498      * @param value the value
 499      * @param strict are we in strict mode
 500      * @return new array data (or same)
 501      */
 502     public abstract ArrayData set(final int index, final Object value, final boolean strict);
 503 
 504     /**
 505      * Set an int value at a given index
 506      *
 507      * @param index the index
 508      * @param value the value
 509      * @param strict are we in strict mode
 510      * @return new array data (or same)
 511      */
 512     public abstract ArrayData set(final int index, final int value, final boolean strict);
 513 
 514     /**










 515      * Set an double value at a given index
 516      *
 517      * @param index the index
 518      * @param value the value
 519      * @param strict are we in strict mode
 520      * @return new array data (or same)
 521      */
 522     public abstract ArrayData set(final int index, final double value, final boolean strict);
 523 
 524     /**
 525      * Set an empty value at a given index. Should only affect Object array.
 526      *
 527      * @param index the index
 528      * @return new array data (or same)
 529      */
 530     public ArrayData setEmpty(final int index) {
 531         // Do nothing.
 532         return this;
 533     }
 534 


 557      * {@link UnwarrantedOptimismException}, this type is used as the actual type of the return value.
 558      * @return the optimistic type of this array data.
 559      */
 560     public Type getOptimisticType() {
 561         return Type.OBJECT;
 562     }
 563 
 564     /**
 565      * Get optimistic int - default is that it's impossible. Overridden
 566      * by arrays that actually represents ints
 567      *
 568      * @param index        the index
 569      * @param programPoint program point
 570      * @return the value
 571      */
 572     public int getIntOptimistic(final int index, final int programPoint) {
 573         throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
 574     }
 575 
 576     /**




















 577      * Get a double value from a given index
 578      *
 579      * @param index the index
 580      * @return the value
 581      */
 582     public abstract double getDouble(final int index);
 583 
 584     /**
 585      * Get optimistic double - default is that it's impossible. Overridden
 586      * by arrays that actually represents doubles or narrower
 587      *
 588      * @param index        the index
 589      * @param programPoint program point
 590      * @return the value
 591      */
 592     public double getDoubleOptimistic(final int index, final int programPoint) {
 593         throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
 594     }
 595 
 596     /**


 749      * @param start start index of splice operation
 750      * @param removed number of removed elements
 751      * @param added number of added elements
 752      * @throws UnsupportedOperationException if fast splice is not supported for the class or arguments.
 753      * @return new arraydata, but this never happens because we always throw an exception
 754      */
 755     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
 756         throw new UnsupportedOperationException();
 757     }
 758 
 759     static Class<?> widestType(final Object... items) {
 760         assert items.length > 0;
 761 
 762         Class<?> widest = Integer.class;
 763 
 764         for (final Object item : items) {
 765             if (item == null) {
 766                 return Object.class;
 767             }
 768             final Class<?> itemClass = item.getClass();
 769             if (itemClass == Double.class || itemClass == Float.class || itemClass == Long.class) {
 770                 if (widest == Integer.class) {




 771                     widest = Double.class;
 772                 }
 773             } else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) {
 774                 return Object.class;
 775             }
 776         }
 777 
 778         return widest;
 779     }
 780 
 781     /**
 782      * Return a list of keys in the array for the iterators
 783      * @return iterator key list
 784      */
 785     protected List<Long> computeIteratorKeys() {
 786         final List<Long> keys = new ArrayList<>();
 787 
 788         final long len = length();
 789         for (long i = 0L; i < len; i = nextIndex(i)) {
 790             if (has((int)i)) {


< prev index next >