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

Mon, 17 Mar 2014 18:02:00 +0530

author
sundar
date
Mon, 17 Mar 2014 18:02:00 +0530
changeset 771
5ab19753ce4a
parent 766
06ee95f094b4
child 774
b6d77b47cf7f
permissions
-rw-r--r--

8037400: Remove getInitialMap getters and GlobalObject interface
Reviewed-by: lagergren, jlaskey, attila

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

mercurial