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