src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java

Thu, 05 Feb 2015 14:47:28 +0100

author
hannesw
date
Thu, 05 Feb 2015 14:47:28 +0100
changeset 1229
f8da39d33117
parent 1220
a95fa1375c4e
child 1374
2937f5b9e985
permissions
-rw-r--r--

8068872: Nashorn JSON.parse drops numeric keys
Reviewed-by: attila, lagergren

jlaskey@3 1 /*
jlaskey@7 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jlaskey@3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jlaskey@3 4 *
jlaskey@3 5 * This code is free software; you can redistribute it and/or modify it
jlaskey@3 6 * under the terms of the GNU General Public License version 2 only, as
jlaskey@3 7 * published by the Free Software Foundation. Oracle designates this
jlaskey@3 8 * particular file as subject to the "Classpath" exception as provided
jlaskey@3 9 * by Oracle in the LICENSE file that accompanied this code.
jlaskey@3 10 *
jlaskey@3 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jlaskey@3 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jlaskey@3 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jlaskey@3 14 * version 2 for more details (a copy is included in the LICENSE file that
jlaskey@3 15 * accompanied this code).
jlaskey@3 16 *
jlaskey@3 17 * You should have received a copy of the GNU General Public License version
jlaskey@3 18 * 2 along with this work; if not, write to the Free Software Foundation,
jlaskey@3 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jlaskey@3 20 *
jlaskey@3 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jlaskey@3 22 * or visit www.oracle.com if you need additional information or have any
jlaskey@3 23 * questions.
jlaskey@3 24 */
jlaskey@3 25
jlaskey@3 26 package jdk.nashorn.internal.runtime.arrays;
jlaskey@3 27
attila@963 28 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
attila@963 29 import static jdk.nashorn.internal.lookup.Lookup.MH;
attila@1220 30
attila@963 31 import java.lang.invoke.MethodHandle;
attila@963 32 import java.lang.invoke.MethodHandles;
jlaskey@3 33 import java.util.Arrays;
jlaskey@3 34 import jdk.nashorn.internal.runtime.JSType;
jlaskey@3 35 import jdk.nashorn.internal.runtime.ScriptRuntime;
jlaskey@3 36
jlaskey@3 37 /**
jlaskey@3 38 * Implementation of {@link ArrayData} as soon as a long has been
jlaskey@3 39 * written to the array
jlaskey@3 40 */
lagergren@1028 41 final class LongArrayData extends ContinuousArrayData implements IntOrLongElements {
jlaskey@3 42 /**
jlaskey@3 43 * The wrapped array
jlaskey@3 44 */
jlaskey@3 45 private long[] array;
jlaskey@3 46
jlaskey@3 47 /**
jlaskey@3 48 * Constructor
jlaskey@3 49 * @param array an int array
jlaskey@3 50 * @param length a length, not necessarily array.length
jlaskey@3 51 */
jlaskey@3 52 LongArrayData(final long array[], final int length) {
jlaskey@3 53 super(length);
hannesw@482 54 assert array.length >= length;
lagergren@1071 55 this.array = array;
jlaskey@3 56 }
jlaskey@3 57
jlaskey@3 58 @Override
lagergren@1071 59 public final Class<?> getElementType() {
lagergren@1028 60 return long.class;
lagergren@1028 61 }
lagergren@1028 62
lagergren@1028 63 @Override
lagergren@1071 64 public final Class<?> getBoxedElementType() {
lagergren@1071 65 return Long.class;
lagergren@1071 66 }
lagergren@1071 67
lagergren@1071 68 @Override
lagergren@1071 69 public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
lagergren@1071 70 return otherData instanceof IntElements ? this : otherData;
lagergren@1071 71 }
lagergren@1071 72
lagergren@1071 73 @Override
lagergren@1071 74 public final int getElementWeight() {
lagergren@1071 75 return 2;
lagergren@1071 76 }
lagergren@1071 77
lagergren@1071 78 @Override
lagergren@1071 79 public LongArrayData copy() {
lagergren@1095 80 return new LongArrayData(array.clone(), (int)length());
hannesw@482 81 }
hannesw@482 82
hannesw@482 83 @Override
jlaskey@3 84 public Object[] asObjectArray() {
hannesw@1060 85 return toObjectArray(true);
jlaskey@3 86 }
jlaskey@3 87
hannesw@1060 88 private Object[] toObjectArray(final boolean trim) {
lagergren@1095 89 assert length() <= array.length : "length exceeds internal array size";
lagergren@1095 90 final int len = (int)length();
lagergren@1095 91 final Object[] oarray = new Object[trim ? len : array.length];
hannesw@442 92
lagergren@1095 93 for (int index = 0; index < len; index++) {
jlaskey@3 94 oarray[index] = Long.valueOf(array[index]);
jlaskey@3 95 }
jlaskey@3 96
jlaskey@3 97 return oarray;
jlaskey@3 98 }
jlaskey@3 99
jlaskey@3 100 @Override
jlaskey@3 101 public Object asArrayOfType(final Class<?> componentType) {
attila@963 102 if (componentType == long.class) {
lagergren@1095 103 final int len = (int)length();
lagergren@1095 104 return array.length == len ? array.clone() : Arrays.copyOf(array, len);
jlaskey@3 105 }
jlaskey@3 106 return super.asArrayOfType(componentType);
jlaskey@3 107 }
jlaskey@3 108
hannesw@1060 109 private double[] toDoubleArray() {
lagergren@1095 110 assert length() <= array.length : "length exceeds internal array size";
lagergren@1095 111 final int len = (int)length();
jlaskey@3 112 final double[] darray = new double[array.length];
hannesw@442 113
lagergren@1095 114 for (int index = 0; index < len; index++) {
jlaskey@3 115 darray[index] = array[index];
jlaskey@3 116 }
jlaskey@3 117
jlaskey@3 118 return darray;
jlaskey@3 119 }
jlaskey@3 120
jlaskey@3 121 @Override
lagergren@1071 122 public ContinuousArrayData convert(final Class<?> type) {
hannesw@633 123 if (type == Integer.class || type == Long.class) {
jlaskey@3 124 return this;
hannesw@442 125 }
lagergren@1095 126 final int len = (int)length();
hannesw@442 127 if (type == Double.class) {
hannesw@1060 128 return new NumberArrayData(toDoubleArray(), len);
jlaskey@3 129 }
hannesw@1060 130 return new ObjectArrayData(toObjectArray(false), len);
jlaskey@3 131 }
jlaskey@3 132
jlaskey@3 133 @Override
jlaskey@3 134 public void shiftLeft(final int by) {
jlaskey@3 135 System.arraycopy(array, by, array, 0, array.length - by);
jlaskey@3 136 }
jlaskey@3 137
jlaskey@3 138 @Override
jlaskey@3 139 public ArrayData shiftRight(final int by) {
lagergren@1095 140 final ArrayData newData = ensure(by + length() - 1);
jlaskey@3 141 if (newData != this) {
jlaskey@3 142 newData.shiftRight(by);
jlaskey@3 143 return newData;
jlaskey@3 144 }
jlaskey@3 145 System.arraycopy(array, 0, array, by, array.length - by);
jlaskey@3 146
jlaskey@3 147 return this;
jlaskey@3 148 }
jlaskey@3 149
jlaskey@3 150 @Override
jlaskey@3 151 public ArrayData ensure(final long safeIndex) {
attila@963 152 if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
jlaskey@3 153 return new SparseArrayData(this, safeIndex + 1);
jlaskey@3 154 }
attila@963 155 final int alen = array.length;
attila@963 156 if (safeIndex >= alen) {
attila@963 157 final int newLength = ArrayData.nextSize((int)safeIndex);
jlaskey@3 158 array = Arrays.copyOf(array, newLength);
jlaskey@3 159 }
hannesw@1229 160 if (safeIndex >= length()) {
hannesw@1229 161 setLength(safeIndex + 1);
hannesw@1229 162 }
jlaskey@3 163 return this;
jlaskey@3 164 }
jlaskey@3 165
jlaskey@3 166 @Override
jlaskey@3 167 public ArrayData shrink(final long newLength) {
lagergren@1071 168 Arrays.fill(array, (int)newLength, array.length, 0L);
jlaskey@3 169 return this;
jlaskey@3 170 }
jlaskey@3 171
jlaskey@3 172 @Override
jlaskey@3 173 public ArrayData set(final int index, final Object value, final boolean strict) {
hannesw@442 174 if (value instanceof Long || value instanceof Integer) {
hannesw@442 175 return set(index, ((Number)value).longValue(), strict);
hannesw@442 176 } else if (value == ScriptRuntime.UNDEFINED) {
hannesw@442 177 return new UndefinedArrayFilter(this).set(index, value, strict);
jlaskey@3 178 }
jlaskey@3 179
jlaskey@3 180 final ArrayData newData = convert(value == null ? Object.class : value.getClass());
jlaskey@3 181 return newData.set(index, value, strict);
jlaskey@3 182 }
jlaskey@3 183
jlaskey@3 184 @Override
jlaskey@3 185 public ArrayData set(final int index, final int value, final boolean strict) {
jlaskey@3 186 array[index] = value;
lagergren@1095 187 setLength(Math.max(index + 1, length()));
jlaskey@3 188 return this;
jlaskey@3 189 }
jlaskey@3 190
jlaskey@3 191 @Override
jlaskey@3 192 public ArrayData set(final int index, final long value, final boolean strict) {
jlaskey@3 193 array[index] = value;
lagergren@1095 194 setLength(Math.max(index + 1, length()));
jlaskey@3 195 return this;
jlaskey@3 196 }
jlaskey@3 197
jlaskey@3 198 @Override
jlaskey@3 199 public ArrayData set(final int index, final double value, final boolean strict) {
jlaskey@3 200 if (JSType.isRepresentableAsLong(value)) {
jlaskey@3 201 array[index] = (long)value;
lagergren@1095 202 setLength(Math.max(index + 1, length()));
jlaskey@3 203 return this;
jlaskey@3 204 }
jlaskey@3 205 return convert(Double.class).set(index, value, strict);
jlaskey@3 206 }
jlaskey@3 207
attila@963 208 private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
attila@963 209 private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
attila@963 210
attila@963 211 @SuppressWarnings("unused")
attila@963 212 private long getElem(final int index) {
attila@963 213 if (has(index)) {
attila@963 214 return array[index];
attila@963 215 }
attila@963 216 throw new ClassCastException();
attila@963 217 }
attila@963 218
attila@963 219 @SuppressWarnings("unused")
attila@963 220 private void setElem(final int index, final long elem) {
attila@963 221 if (hasRoomFor(index)) {
attila@963 222 array[index] = elem;
attila@963 223 return;
attila@963 224 }
attila@963 225 throw new ClassCastException();
attila@963 226 }
attila@963 227
attila@963 228 @Override
attila@963 229 public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
attila@963 230 if (returnType == int.class) {
attila@963 231 return null;
attila@963 232 }
attila@963 233 return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
attila@963 234 }
attila@963 235
attila@963 236 @Override
attila@963 237 public MethodHandle getElementSetter(final Class<?> elementType) {
attila@963 238 return elementType == int.class || elementType == long.class ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
attila@963 239 }
attila@963 240
attila@963 241 @Override
jlaskey@3 242 public int getInt(final int index) {
jlaskey@3 243 return (int)array[index];
jlaskey@3 244 }
jlaskey@3 245
jlaskey@3 246 @Override
jlaskey@3 247 public long getLong(final int index) {
jlaskey@3 248 return array[index];
jlaskey@3 249 }
jlaskey@3 250
jlaskey@3 251 @Override
attila@963 252 public long getLongOptimistic(final int index, final int programPoint) {
attila@963 253 return array[index];
attila@963 254 }
attila@963 255
attila@963 256 @Override
jlaskey@3 257 public double getDouble(final int index) {
jlaskey@3 258 return array[index];
jlaskey@3 259 }
jlaskey@3 260
jlaskey@3 261 @Override
attila@963 262 public double getDoubleOptimistic(final int index, final int programPoint) {
attila@963 263 return array[index];
attila@963 264 }
attila@963 265
attila@963 266 @Override
jlaskey@3 267 public Object getObject(final int index) {
jlaskey@3 268 return array[index];
jlaskey@3 269 }
jlaskey@3 270
jlaskey@3 271 @Override
jlaskey@3 272 public boolean has(final int index) {
lagergren@1095 273 return 0 <= index && index < length();
jlaskey@3 274 }
jlaskey@3 275
jlaskey@3 276 @Override
jlaskey@3 277 public ArrayData delete(final int index) {
jlaskey@3 278 return new DeletedRangeArrayFilter(this, index, index);
jlaskey@3 279 }
jlaskey@3 280
jlaskey@3 281 @Override
jlaskey@3 282 public ArrayData delete(final long fromIndex, final long toIndex) {
jlaskey@3 283 return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
jlaskey@3 284 }
jlaskey@3 285
jlaskey@3 286 @Override
jlaskey@3 287 public Object pop() {
lagergren@1095 288 final int len = (int)length();
lagergren@1095 289 if (len == 0) {
jlaskey@3 290 return ScriptRuntime.UNDEFINED;
jlaskey@3 291 }
jlaskey@3 292
lagergren@1095 293 final int newLength = len - 1;
jlaskey@3 294 final long elem = array[newLength];
jlaskey@3 295 array[newLength] = 0;
jlaskey@3 296 setLength(newLength);
jlaskey@3 297
jlaskey@3 298 return elem;
jlaskey@3 299 }
jlaskey@3 300
jlaskey@3 301 @Override
jlaskey@3 302 public ArrayData slice(final long from, final long to) {
lagergren@1095 303 final long start = from < 0 ? from + length() : from;
jlaskey@3 304 final long newLength = to - start;
jlaskey@3 305 return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
jlaskey@3 306 }
hannesw@633 307
hannesw@633 308 @Override
hannesw@633 309 public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
lagergren@1095 310 final long oldLength = length();
hannesw@633 311 final long newLength = oldLength - removed + added;
hannesw@633 312 if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
hannesw@633 313 throw new UnsupportedOperationException();
hannesw@633 314 }
attila@963 315 final ArrayData returnValue = removed == 0 ?
hannesw@633 316 EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
hannesw@633 317
hannesw@633 318 if (newLength != oldLength) {
hannesw@633 319 final long[] newArray;
hannesw@633 320
hannesw@633 321 if (newLength > array.length) {
hannesw@633 322 newArray = new long[ArrayData.nextSize((int)newLength)];
hannesw@633 323 System.arraycopy(array, 0, newArray, 0, start);
hannesw@633 324 } else {
hannesw@633 325 newArray = array;
hannesw@633 326 }
hannesw@633 327
hannesw@633 328 System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed));
hannesw@633 329 array = newArray;
hannesw@633 330 setLength(newLength);
hannesw@633 331 }
hannesw@633 332
hannesw@633 333 return returnValue;
hannesw@633 334 }
lagergren@1028 335
lagergren@1028 336 @Override
lagergren@1028 337 public long fastPush(final int arg) {
lagergren@1028 338 return fastPush((long)arg);
lagergren@1028 339 }
lagergren@1028 340
lagergren@1028 341 @Override
lagergren@1028 342 public long fastPush(final long arg) {
lagergren@1095 343 final int len = (int)length();
lagergren@1028 344 if (len == array.length) {
lagergren@1028 345 array = Arrays.copyOf(array, nextSize(len));
lagergren@1028 346 }
lagergren@1028 347 array[len] = arg;
lagergren@1095 348 return increaseLength();
lagergren@1028 349 }
lagergren@1028 350
lagergren@1028 351 @Override
lagergren@1028 352 public long fastPopLong() {
lagergren@1095 353 if (length() == 0) {
lagergren@1095 354 throw new ClassCastException(); //undefined result
lagergren@1028 355 }
lagergren@1095 356 final int newLength = (int)decreaseLength();
lagergren@1028 357 final long elem = array[newLength];
lagergren@1028 358 array[newLength] = 0;
lagergren@1028 359 return elem;
lagergren@1028 360 }
lagergren@1028 361
lagergren@1028 362 @Override
lagergren@1028 363 public double fastPopDouble() {
lagergren@1028 364 return fastPopLong();
lagergren@1028 365 }
lagergren@1028 366
lagergren@1028 367 @Override
lagergren@1028 368 public Object fastPopObject() {
lagergren@1028 369 return fastPopLong();
lagergren@1028 370 }
lagergren@1071 371
lagergren@1071 372 @Override
lagergren@1071 373 public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
lagergren@1095 374 final int otherLength = (int)otherData.length();
lagergren@1095 375 final int thisLength = (int)length();
lagergren@1071 376 assert otherLength > 0 && thisLength > 0;
lagergren@1071 377
lagergren@1071 378 final long[] otherArray = ((LongArrayData)otherData).array;
lagergren@1071 379 final int newLength = otherLength + thisLength;
lagergren@1071 380 final long[] newArray = new long[ArrayData.alignUp(newLength)];
lagergren@1071 381
lagergren@1071 382 System.arraycopy(array, 0, newArray, 0, thisLength);
lagergren@1071 383 System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
lagergren@1071 384
lagergren@1071 385 return new LongArrayData(newArray, newLength);
lagergren@1071 386 }
lagergren@1071 387
lagergren@1071 388 @Override
lagergren@1071 389 public String toString() {
lagergren@1095 390 assert length() <= array.length : length() + " > " + array.length;
lagergren@1071 391
lagergren@1071 392 final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
lagergren@1071 393 append(": [");
lagergren@1095 394 final int len = (int)length();
lagergren@1095 395 for (int i = 0; i < len; i++) {
lagergren@1071 396 sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
lagergren@1095 397 if (i + 1 < len) {
lagergren@1071 398 sb.append(", ");
lagergren@1071 399 }
lagergren@1071 400 }
lagergren@1071 401 sb.append(']');
lagergren@1071 402
lagergren@1071 403 return sb.toString();
lagergren@1071 404 }
jlaskey@3 405 }

mercurial