src/jdk/nashorn/internal/objects/ArrayBufferView.java

Fri, 21 Dec 2012 16:36:24 -0400

author
jlaskey
date
Fri, 21 Dec 2012 16:36:24 -0400
changeset 3
da1e581c933b
child 7
5a1b0714df0e
permissions
-rw-r--r--

8005403: Open-source Nashorn
Reviewed-by: attila, hannesw, lagergren, sundar
Contributed-by: james.laskey@oracle.com, akhil.arora@oracle.com, andreas.woess@jku.at, attila.szegedi@oracle.com, hannes.wallnoefer@oracle.com, henry.jen@oracle.com, marcus.lagergren@oracle.com, pavel.semenov@oracle.com, pavel.stepanov@oracle.com, petr.hejl@oracle.com, petr.pisl@oracle.com, sundararajan.athijegannathan@oracle.com

jlaskey@3 1 /*
jlaskey@3 2 * Copyright (c) 2010, 2012, 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.objects;
jlaskey@3 27
jlaskey@3 28 import jdk.nashorn.internal.objects.annotations.Attribute;
jlaskey@3 29 import jdk.nashorn.internal.objects.annotations.Getter;
jlaskey@3 30 import jdk.nashorn.internal.objects.annotations.ScriptClass;
jlaskey@3 31 import jdk.nashorn.internal.runtime.JSType;
jlaskey@3 32 import jdk.nashorn.internal.runtime.ScriptObject;
jlaskey@3 33 import jdk.nashorn.internal.runtime.ScriptRuntime;
jlaskey@3 34 import jdk.nashorn.internal.runtime.arrays.ArrayData;
jlaskey@3 35
jlaskey@3 36 @ScriptClass("ArrayBufferView")
jlaskey@3 37 abstract class ArrayBufferView extends ScriptObject {
jlaskey@3 38
jlaskey@3 39 ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
jlaskey@3 40 checkConstructorArgs(buffer, byteOffset, elementLength);
jlaskey@3 41 this.setProto(getPrototype());
jlaskey@3 42 this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
jlaskey@3 43 }
jlaskey@3 44
jlaskey@3 45 private void checkConstructorArgs(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
jlaskey@3 46 if (byteOffset < 0 || elementLength < 0) {
jlaskey@3 47 throw new RuntimeException("byteOffset or length must not be negative");
jlaskey@3 48 }
jlaskey@3 49 if (byteOffset + elementLength * bytesPerElement() > buffer.getByteLength()) {
jlaskey@3 50 throw new RuntimeException("byteOffset + byteLength out of range");
jlaskey@3 51 }
jlaskey@3 52 if (byteOffset % bytesPerElement() != 0) {
jlaskey@3 53 throw new RuntimeException("byteOffset must be a multiple of the element size");
jlaskey@3 54 }
jlaskey@3 55 }
jlaskey@3 56
jlaskey@3 57 private int bytesPerElement() {
jlaskey@3 58 return factory().bytesPerElement;
jlaskey@3 59 }
jlaskey@3 60
jlaskey@3 61 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
jlaskey@3 62 public static Object BYTES_PER_ELEMENT(final Object self) {
jlaskey@3 63 return ((ArrayBufferView)self).bytesPerElement();
jlaskey@3 64 }
jlaskey@3 65
jlaskey@3 66 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
jlaskey@3 67 public static Object buffer(final Object self) {
jlaskey@3 68 return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
jlaskey@3 69 }
jlaskey@3 70
jlaskey@3 71 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
jlaskey@3 72 public static Object byteOffset(final Object self) {
jlaskey@3 73 return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).byteOffset;
jlaskey@3 74 }
jlaskey@3 75
jlaskey@3 76 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
jlaskey@3 77 public static Object byteLength(final Object self) {
jlaskey@3 78 final ArrayBufferView view = (ArrayBufferView)self;
jlaskey@3 79 return ((ArrayDataImpl)view.getArray()).elementLength * view.bytesPerElement();
jlaskey@3 80 }
jlaskey@3 81
jlaskey@3 82 @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
jlaskey@3 83 public static Object length(final Object self) {
jlaskey@3 84 return ((ArrayBufferView)self).elementLength();
jlaskey@3 85 }
jlaskey@3 86
jlaskey@3 87 @Override
jlaskey@3 88 public final Object getLength() {
jlaskey@3 89 return elementLength();
jlaskey@3 90 }
jlaskey@3 91
jlaskey@3 92 private int elementLength() {
jlaskey@3 93 return ((ArrayDataImpl)getArray()).elementLength;
jlaskey@3 94 }
jlaskey@3 95
jlaskey@3 96 protected static abstract class ArrayDataImpl extends ArrayData {
jlaskey@3 97 protected final NativeArrayBuffer buffer;
jlaskey@3 98 protected final int byteOffset;
jlaskey@3 99 private final int elementLength;
jlaskey@3 100
jlaskey@3 101 protected ArrayDataImpl(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
jlaskey@3 102 super(elementLength);
jlaskey@3 103 this.buffer = buffer;
jlaskey@3 104 this.byteOffset = byteOffset;
jlaskey@3 105 this.elementLength = elementLength;
jlaskey@3 106 }
jlaskey@3 107
jlaskey@3 108 @Override
jlaskey@3 109 public Object[] asObjectArray() {
jlaskey@3 110 final Object[] array = new Object[elementLength];
jlaskey@3 111 for (int i = 0; i < elementLength; i++) {
jlaskey@3 112 array[i] = getObjectImpl(i);
jlaskey@3 113 }
jlaskey@3 114 return array;
jlaskey@3 115 }
jlaskey@3 116
jlaskey@3 117 @Override
jlaskey@3 118 public ArrayData ensure(final long safeIndex) {
jlaskey@3 119 return this;
jlaskey@3 120 }
jlaskey@3 121
jlaskey@3 122 @Override
jlaskey@3 123 public void setLength(final long length) {
jlaskey@3 124 //empty?
jlaskey@3 125 //TODO is this right?
jlaskey@3 126 }
jlaskey@3 127
jlaskey@3 128 @Override
jlaskey@3 129 public ArrayData shrink(final long newLength) {
jlaskey@3 130 return this;
jlaskey@3 131 }
jlaskey@3 132
jlaskey@3 133 @Override
jlaskey@3 134 public ArrayData set(final int index, final Object value, final boolean strict) {
jlaskey@3 135 if (has(index)) {
jlaskey@3 136 setImpl(index, value);
jlaskey@3 137 }
jlaskey@3 138 return this;
jlaskey@3 139 }
jlaskey@3 140
jlaskey@3 141 @Override
jlaskey@3 142 public ArrayData set(final int index, final int value, final boolean strict) {
jlaskey@3 143 if (has(index)) {
jlaskey@3 144 setImpl(index, value);
jlaskey@3 145 }
jlaskey@3 146 return this;
jlaskey@3 147 }
jlaskey@3 148
jlaskey@3 149 @Override
jlaskey@3 150 public ArrayData set(final int index, final long value, final boolean strict) {
jlaskey@3 151 if (has(index)) {
jlaskey@3 152 setImpl(index, value);
jlaskey@3 153 }
jlaskey@3 154 return this;
jlaskey@3 155 }
jlaskey@3 156
jlaskey@3 157 @Override
jlaskey@3 158 public ArrayData set(final int index, final double value, final boolean strict) {
jlaskey@3 159 if (has(index)) {
jlaskey@3 160 setImpl(index, value);
jlaskey@3 161 }
jlaskey@3 162 return this;
jlaskey@3 163 }
jlaskey@3 164
jlaskey@3 165 @Override
jlaskey@3 166 public int getInt(final int index) {
jlaskey@3 167 return getIntImpl(index);
jlaskey@3 168 }
jlaskey@3 169
jlaskey@3 170 @Override
jlaskey@3 171 public long getLong(final int index) {
jlaskey@3 172 return getLongImpl(index);
jlaskey@3 173 }
jlaskey@3 174
jlaskey@3 175 @Override
jlaskey@3 176 public double getDouble(final int index) {
jlaskey@3 177 return getDoubleImpl(index);
jlaskey@3 178 }
jlaskey@3 179
jlaskey@3 180 @Override
jlaskey@3 181 public Object getObject(final int index) {
jlaskey@3 182 return getObjectImpl(index);
jlaskey@3 183 }
jlaskey@3 184
jlaskey@3 185 @Override
jlaskey@3 186 public boolean has(final int index) {
jlaskey@3 187 return index >= 0 && index < elementLength;
jlaskey@3 188 }
jlaskey@3 189
jlaskey@3 190 @Override
jlaskey@3 191 public boolean canDelete(final int index, final boolean strict) {
jlaskey@3 192 return false;
jlaskey@3 193 }
jlaskey@3 194
jlaskey@3 195 @Override
jlaskey@3 196 public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
jlaskey@3 197 return false;
jlaskey@3 198 }
jlaskey@3 199
jlaskey@3 200 @Override
jlaskey@3 201 public ArrayData delete(final int index) {
jlaskey@3 202 return this;
jlaskey@3 203 }
jlaskey@3 204
jlaskey@3 205 @Override
jlaskey@3 206 public ArrayData delete(final long fromIndex, final long toIndex) {
jlaskey@3 207 return this;
jlaskey@3 208 }
jlaskey@3 209
jlaskey@3 210 @Override
jlaskey@3 211 protected ArrayData convert(final Class<?> type) {
jlaskey@3 212 return this;
jlaskey@3 213 }
jlaskey@3 214
jlaskey@3 215 @Override
jlaskey@3 216 public void shiftLeft(final int by) {
jlaskey@3 217 throw new UnsupportedOperationException();
jlaskey@3 218 }
jlaskey@3 219
jlaskey@3 220 @Override
jlaskey@3 221 public ArrayData shiftRight(final int by) {
jlaskey@3 222 throw new UnsupportedOperationException();
jlaskey@3 223 }
jlaskey@3 224
jlaskey@3 225 @Override
jlaskey@3 226 public Object pop() {
jlaskey@3 227 throw new UnsupportedOperationException();
jlaskey@3 228 }
jlaskey@3 229
jlaskey@3 230 @Override
jlaskey@3 231 public ArrayData slice(final long from, final long to) {
jlaskey@3 232 throw new UnsupportedOperationException();
jlaskey@3 233 }
jlaskey@3 234
jlaskey@3 235 protected abstract int getIntImpl(int key);
jlaskey@3 236
jlaskey@3 237 protected long getLongImpl(final int key) {
jlaskey@3 238 return getIntImpl(key);
jlaskey@3 239 }
jlaskey@3 240
jlaskey@3 241 protected double getDoubleImpl(final int key) {
jlaskey@3 242 return getIntImpl(key);
jlaskey@3 243 }
jlaskey@3 244
jlaskey@3 245 protected Object getObjectImpl(final int key) {
jlaskey@3 246 return getIntImpl(key);
jlaskey@3 247 }
jlaskey@3 248
jlaskey@3 249 protected abstract void setImpl(int key, int value);
jlaskey@3 250
jlaskey@3 251 protected void setImpl(final int key, final long value) {
jlaskey@3 252 setImpl(key, (int)value);
jlaskey@3 253 }
jlaskey@3 254
jlaskey@3 255 protected void setImpl(final int key, final double value) {
jlaskey@3 256 setImpl(key, JSType.toInt32(value));
jlaskey@3 257 }
jlaskey@3 258
jlaskey@3 259 protected void setImpl(final int key, final Object value) {
jlaskey@3 260 setImpl(key, JSType.toInt32(value));
jlaskey@3 261 }
jlaskey@3 262
jlaskey@3 263 protected abstract int byteIndex(int index);
jlaskey@3 264 }
jlaskey@3 265
jlaskey@3 266 protected static abstract class Factory {
jlaskey@3 267 final int bytesPerElement;
jlaskey@3 268
jlaskey@3 269 public Factory(final int bytesPerElement) {
jlaskey@3 270 this.bytesPerElement = bytesPerElement;
jlaskey@3 271 }
jlaskey@3 272
jlaskey@3 273 public final ArrayBufferView construct(final int elementLength) {
jlaskey@3 274 return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength);
jlaskey@3 275 }
jlaskey@3 276
jlaskey@3 277 public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength);
jlaskey@3 278
jlaskey@3 279 public abstract ArrayData createArrayData(NativeArrayBuffer buffer, int byteOffset, int elementLength);
jlaskey@3 280 }
jlaskey@3 281
jlaskey@3 282 protected abstract Factory factory();
jlaskey@3 283
jlaskey@3 284 protected abstract ScriptObject getPrototype();
jlaskey@3 285
jlaskey@3 286 protected boolean isFloatArray() {
jlaskey@3 287 return false;
jlaskey@3 288 }
jlaskey@3 289
jlaskey@3 290 protected static ArrayBufferView constructorImpl(final Object[] args, final Factory factory) {
jlaskey@3 291 final Object arg0 = args.length != 0 ? args[0] : 0;
jlaskey@3 292 final ArrayBufferView dst;
jlaskey@3 293 final int length;
jlaskey@3 294 if (arg0 instanceof NativeArrayBuffer) {
jlaskey@3 295 // Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length)
jlaskey@3 296 final NativeArrayBuffer buffer = (NativeArrayBuffer) arg0;
jlaskey@3 297 final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
jlaskey@3 298 if (args.length > 2) {
jlaskey@3 299 length = JSType.toInt32(args[2]);
jlaskey@3 300 } else {
jlaskey@3 301 if ((buffer.getByteLength() - byteOffset) % factory.bytesPerElement != 0) {
jlaskey@3 302 throw new RuntimeException("buffer.byteLength - byteOffset must be a multiple of the element size");
jlaskey@3 303 }
jlaskey@3 304 length = (buffer.getByteLength() - byteOffset) / factory.bytesPerElement;
jlaskey@3 305 }
jlaskey@3 306 return factory.construct(buffer, byteOffset, length);
jlaskey@3 307 } else if (arg0 instanceof ArrayBufferView) {
jlaskey@3 308 // Constructor(TypedArray array)
jlaskey@3 309 length = ((ArrayBufferView)arg0).elementLength();
jlaskey@3 310 dst = factory.construct(length);
jlaskey@3 311 } else if (arg0 instanceof NativeArray) {
jlaskey@3 312 // Constructor(type[] array)
jlaskey@3 313 length = (int) (((NativeArray) arg0).getArray().length() & 0x7fff_ffff);
jlaskey@3 314 dst = factory.construct(length);
jlaskey@3 315 } else {
jlaskey@3 316 // Constructor(unsigned long length)
jlaskey@3 317 length = JSType.toInt32(arg0);
jlaskey@3 318 return factory.construct(length);
jlaskey@3 319 }
jlaskey@3 320
jlaskey@3 321 copyElements(dst, length, (ScriptObject)arg0, 0);
jlaskey@3 322 return dst;
jlaskey@3 323 }
jlaskey@3 324
jlaskey@3 325 protected static Object setImpl(final Object self, final Object array, final Object offset0) {
jlaskey@3 326 final ArrayBufferView dest = ((ArrayBufferView)self);
jlaskey@3 327 final int length;
jlaskey@3 328 if (array instanceof ArrayBufferView) {
jlaskey@3 329 // void set(TypedArray array, optional unsigned long offset)
jlaskey@3 330 length = ((ArrayBufferView)array).elementLength();
jlaskey@3 331 } else if (array instanceof NativeArray) {
jlaskey@3 332 // void set(type[] array, optional unsigned long offset)
jlaskey@3 333 length = (int) (((NativeArray) array).getArray().length() & 0x7fff_ffff);
jlaskey@3 334 } else {
jlaskey@3 335 throw new RuntimeException("argument is not of array type");
jlaskey@3 336 }
jlaskey@3 337
jlaskey@3 338 final ScriptObject source = (ScriptObject) array;
jlaskey@3 339 final int offset = JSType.toInt32(offset0); // default=0
jlaskey@3 340
jlaskey@3 341 if (dest.elementLength() < length + offset || offset < 0) {
jlaskey@3 342 throw new RuntimeException("offset or array length out of bounds");
jlaskey@3 343 }
jlaskey@3 344
jlaskey@3 345 copyElements(dest, length, source, offset);
jlaskey@3 346
jlaskey@3 347 return ScriptRuntime.UNDEFINED;
jlaskey@3 348 }
jlaskey@3 349
jlaskey@3 350 private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
jlaskey@3 351 if (!dest.isFloatArray()) {
jlaskey@3 352 for (int i = 0, j = offset; i < length; i++, j++) {
jlaskey@3 353 dest.set(j, source.getInt(i), false);
jlaskey@3 354 }
jlaskey@3 355 } else {
jlaskey@3 356 for (int i = 0, j = offset; i < length; i++, j++) {
jlaskey@3 357 dest.set(j, source.getDouble(i), false);
jlaskey@3 358 }
jlaskey@3 359 }
jlaskey@3 360 }
jlaskey@3 361
jlaskey@3 362 protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
jlaskey@3 363 final ArrayBufferView arrayView = ((ArrayBufferView)self);
jlaskey@3 364 final int elementLength = arrayView.elementLength();
jlaskey@3 365 final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
jlaskey@3 366 final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
jlaskey@3 367 final ArrayDataImpl arrayData = (ArrayDataImpl)arrayView.getArray();
jlaskey@3 368 return arrayView.factory().construct(arrayData.buffer, arrayData.byteIndex(begin), Math.max(end - begin, 0));
jlaskey@3 369 }
jlaskey@3 370 }

mercurial