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  */
25 
26 package jdk.nashorn.internal.objects;
27 
28 import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
29 
30 import java.lang.invoke.MethodHandle;
31 import java.lang.invoke.MethodHandles;
32 import java.nio.ByteBuffer;
33 import java.nio.ShortBuffer;
34 import jdk.nashorn.internal.objects.annotations.Attribute;
35 import jdk.nashorn.internal.objects.annotations.Constructor;
36 import jdk.nashorn.internal.objects.annotations.Function;
37 import jdk.nashorn.internal.objects.annotations.Property;
38 import jdk.nashorn.internal.objects.annotations.ScriptClass;
39 import jdk.nashorn.internal.objects.annotations.Where;
40 import jdk.nashorn.internal.runtime.JSType;
41 import jdk.nashorn.internal.runtime.PropertyMap;
42 import jdk.nashorn.internal.runtime.ScriptObject;
43 import jdk.nashorn.internal.runtime.arrays.ArrayData;
44 import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
45 
46 /**
47  * Int16 array for the TypedArray extension
48  */
49 @ScriptClass("Int16Array")
50 public final class NativeInt16Array extends ArrayBufferView {
51 
52     // initialized by nasgen
53     @SuppressWarnings("unused")
54     private static PropertyMap $nasgenmap$;
55 
56     /**
57      * The size in bytes of each element in the array.
58      */
59     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
60     public static final int BYTES_PER_ELEMENT = 2;
61 
62     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
63         @Override
64         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
65             return new NativeInt16Array(buffer, byteOffset, length);
66         }
67 
68         @Override
69         public Int16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
70             return new Int16ArrayData(nb.asShortBuffer(), start, end);
71         }
72 
73         @Override
74         public String getClassName() {
75             return "Int16Array";
76         }
77     };
78 
79     private static final class Int16ArrayData extends TypedArrayData<ShortBuffer> {
80 
81         private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "getElem", int.class, int.class).methodHandle();
82         private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
83 
Int16ArrayData(final ShortBuffer nb, final int start, final int end)84         private Int16ArrayData(final ShortBuffer nb, final int start, final int end) {
85             super(((ShortBuffer)nb.position(start).limit(end)).slice(), end - start);
86         }
87 
88         @Override
getGetElem()89         protected MethodHandle getGetElem() {
90             return GET_ELEM;
91         }
92 
93         @Override
getSetElem()94         protected MethodHandle getSetElem() {
95             return SET_ELEM;
96         }
97 
98         @Override
getElementType()99         public Class<?> getElementType() {
100             return int.class;
101         }
102 
103         @Override
getBoxedElementType()104         public Class<?> getBoxedElementType() {
105             return Integer.class;
106         }
107 
getElem(final int index)108         private int getElem(final int index) {
109             try {
110                 return nb.get(index);
111             } catch (final IndexOutOfBoundsException e) {
112                 throw new ClassCastException(); //force relink - this works for unoptimistic too
113             }
114         }
115 
setElem(final int index, final int elem)116         private void setElem(final int index, final int elem) {
117             try {
118                 if (index < nb.limit()) {
119                     nb.put(index, (short) elem);
120                 }
121             } catch (final IndexOutOfBoundsException e) {
122                 throw new ClassCastException();
123             }
124         }
125 
126         @Override
getInt(final int index)127         public int getInt(final int index) {
128             return getElem(index);
129         }
130 
131         @Override
getIntOptimistic(final int index, final int programPoint)132         public int getIntOptimistic(final int index, final int programPoint) {
133             return getElem(index);
134         }
135 
136         @Override
getDouble(final int index)137         public double getDouble(final int index) {
138             return getInt(index);
139         }
140 
141         @Override
getDoubleOptimistic(final int index, final int programPoint)142         public double getDoubleOptimistic(final int index, final int programPoint) {
143             return getElem(index);
144         }
145 
146         @Override
getObject(final int index)147         public Object getObject(final int index) {
148             return getInt(index);
149         }
150 
151         @Override
set(final int index, final Object value, final boolean strict)152         public ArrayData set(final int index, final Object value, final boolean strict) {
153             return set(index, JSType.toInt32(value), strict);
154         }
155 
156         @Override
set(final int index, final int value, final boolean strict)157         public ArrayData set(final int index, final int value, final boolean strict) {
158             setElem(index, value);
159             return this;
160         }
161 
162         @Override
set(final int index, final double value, final boolean strict)163         public ArrayData set(final int index, final double value, final boolean strict) {
164             return set(index, (int)value, strict);
165         }
166     }
167 
168     /**
169      * Constructor
170      *
171      * @param newObj is this typed array instantiated with the new operator
172      * @param self   self reference
173      * @param args   args
174      *
175      * @return new typed array
176      */
177     @Constructor(arity = 1)
constructor(final boolean newObj, final Object self, final Object... args)178     public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
179         return (NativeInt16Array)constructorImpl(newObj, args, FACTORY);
180     }
181 
NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength)182     NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
183         super(buffer, byteOffset, byteLength);
184     }
185 
186     @Override
factory()187     protected Factory factory() {
188         return FACTORY;
189     }
190 
191     /**
192      * Set values
193      * @param self   self reference
194      * @param array  multiple values of array's type to set
195      * @param offset optional start index, interpreted  0 if undefined
196      * @return undefined
197      */
198     @Function(attributes = Attribute.NOT_ENUMERABLE)
set(final Object self, final Object array, final Object offset)199     protected static Object set(final Object self, final Object array, final Object offset) {
200         return ArrayBufferView.setImpl(self, array, offset);
201     }
202 
203     /**
204      * Returns a new TypedArray view of the ArrayBuffer store for this TypedArray,
205      * referencing the elements at begin, inclusive, up to end, exclusive. If either
206      * begin or end is negative, it refers to an index from the end of the array,
207      * as opposed to from the beginning.
208      * <p>
209      * If end is unspecified, the subarray contains all elements from begin to the end
210      * of the TypedArray. The range specified by the begin and end values is clamped to
211      * the valid index range for the current array. If the computed length of the new
212      * TypedArray would be negative, it is clamped to zero.
213      * <p>
214      * The returned TypedArray will be of the same type as the array on which this
215      * method is invoked.
216      *
217      * @param self self reference
218      * @param begin begin position
219      * @param end end position
220      *
221      * @return sub array
222      */
223     @Function(attributes = Attribute.NOT_ENUMERABLE)
subarray(final Object self, final Object begin, final Object end)224     protected static NativeInt16Array subarray(final Object self, final Object begin, final Object end) {
225         return (NativeInt16Array)ArrayBufferView.subarrayImpl(self, begin, end);
226     }
227 
228     @Override
getPrototype(final Global global)229     protected ScriptObject getPrototype(final Global global) {
230         return global.getInt16ArrayPrototype();
231     }
232 }
233