UndefinedArrayFilter.java revision 953:221a84ef44c0
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
26package jdk.nashorn.internal.runtime.arrays;
27
28import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
29
30import java.lang.reflect.Array;
31import jdk.nashorn.internal.runtime.BitVector;
32import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
33
34/**
35 * This filter handles the presence of undefined array elements.
36 */
37final class UndefinedArrayFilter extends ArrayFilter {
38    /** Bit vector tracking undefines. */
39    private final BitVector undefined;
40
41    UndefinedArrayFilter(final ArrayData underlying) {
42        super(underlying);
43
44        this.undefined = new BitVector(underlying.length());
45    }
46
47    @Override
48    public ArrayData copy() {
49        final UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
50        copy.getUndefined().copy(undefined);
51        return copy;
52    }
53
54    @Override
55    public Object[] asObjectArray() {
56        final Object[] value = super.asObjectArray();
57
58        for (int i = 0; i < value.length; i++) {
59            if (undefined.isSet(i)) {
60                value[i] = UNDEFINED;
61            }
62        }
63
64        return value;
65    }
66
67    @Override
68    public Object asArrayOfType(final Class<?> componentType) {
69        final Object value = super.asArrayOfType(componentType);
70        final Object undefValue = convertUndefinedValue(componentType);
71        final int l = Array.getLength(value);
72        for (int i = 0; i < l; i++) {
73            if (undefined.isSet(i)) {
74                Array.set(value, i,undefValue);
75            }
76        }
77
78        return value;
79    }
80
81    @Override
82    public void shiftLeft(final int by) {
83        super.shiftLeft(by);
84        undefined.shiftLeft(by, length());
85    }
86
87    @Override
88    public ArrayData shiftRight(final int by) {
89        super.shiftRight(by);
90        undefined.shiftRight(by, length());
91
92        return this;
93    }
94
95    @Override
96    public ArrayData ensure(final long safeIndex) {
97        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
98            return new SparseArrayData(this, safeIndex + 1);
99        }
100
101        super.ensure(safeIndex);
102        undefined.resize(length());
103
104        return this;
105    }
106
107    @Override
108    public ArrayData shrink(final long newLength) {
109        super.shrink(newLength);
110        undefined.resize(length());
111
112        return this;
113    }
114
115    @Override
116    public ArrayData set(final int index, final Object value, final boolean strict) {
117        undefined.clear(index);
118
119        if (value == UNDEFINED) {
120            undefined.set(index);
121            return this;
122        }
123
124        return super.set(index, value, strict);
125    }
126
127    @Override
128    public ArrayData set(final int index, final int value, final boolean strict) {
129        undefined.clear(index);
130
131        return super.set(index, value, strict);
132    }
133
134    @Override
135    public ArrayData set(final int index, final long value, final boolean strict) {
136        undefined.clear(index);
137
138        return super.set(index, value, strict);
139    }
140
141    @Override
142    public ArrayData set(final int index, final double value, final boolean strict) {
143        undefined.clear(index);
144
145        return super.set(index, value, strict);
146    }
147
148    @Override
149    public int getInt(final int index) {
150        if (undefined.isSet(index)) {
151            return 0;
152        }
153
154        return super.getInt(index);
155    }
156
157    @Override
158    public int getIntOptimistic(final int index, final int programPoint) {
159        if (undefined.isSet(index)) {
160            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
161        }
162
163        return super.getIntOptimistic(index, programPoint);
164    }
165
166    @Override
167    public long getLong(final int index) {
168        if (undefined.isSet(index)) {
169            return 0L;
170        }
171
172        return super.getLong(index);
173    }
174
175    @Override
176    public long getLongOptimistic(final int index, final int programPoint) {
177        if (undefined.isSet(index)) {
178            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
179        }
180
181        return super.getLongOptimistic(index, programPoint);
182    }
183
184    @Override
185    public double getDouble(final int index) {
186        if (undefined.isSet(index)) {
187            return Double.NaN;
188        }
189
190        return super.getDouble(index);
191    }
192
193    @Override
194    public double getDoubleOptimistic(final int index, final int programPoint) {
195        if (undefined.isSet(index)) {
196            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
197        }
198
199        return super.getDoubleOptimistic(index, programPoint);
200    }
201
202    @Override
203    public Object getObject(final int index) {
204        if (undefined.isSet(index)) {
205            return UNDEFINED;
206        }
207
208        return super.getObject(index);
209    }
210
211    @Override
212    public ArrayData delete(final int index) {
213        undefined.clear(index);
214
215        return super.delete(index);
216    }
217
218    @Override
219    public Object pop() {
220        final long index = length() - 1;
221
222        if (super.has((int)index)) {
223            final boolean isUndefined = undefined.isSet(index);
224            final Object value = super.pop();
225
226            return isUndefined ? UNDEFINED : value;
227        }
228
229        return super.pop();
230    }
231
232    @Override
233    public ArrayData slice(final long from, final long to) {
234        final ArrayData newArray = underlying.slice(from, to);
235        final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
236        newFilter.getUndefined().copy(undefined);
237        newFilter.getUndefined().shiftLeft(from, newFilter.length());
238
239        return newFilter;
240    }
241
242    private BitVector getUndefined() {
243        return undefined;
244    }
245}
246