UndefinedArrayFilter.java revision 1571:fd97b9047199
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 double value, final boolean strict) {
132        undefined.clear(index);
133
134        return super.set(index, value, strict);
135    }
136
137    @Override
138    public int getInt(final int index) {
139        if (undefined.isSet(index)) {
140            return 0;
141        }
142
143        return super.getInt(index);
144    }
145
146    @Override
147    public int getIntOptimistic(final int index, final int programPoint) {
148        if (undefined.isSet(index)) {
149            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
150        }
151
152        return super.getIntOptimistic(index, programPoint);
153    }
154
155    @Override
156    public double getDouble(final int index) {
157        if (undefined.isSet(index)) {
158            return Double.NaN;
159        }
160
161        return super.getDouble(index);
162    }
163
164    @Override
165    public double getDoubleOptimistic(final int index, final int programPoint) {
166        if (undefined.isSet(index)) {
167            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
168        }
169
170        return super.getDoubleOptimistic(index, programPoint);
171    }
172
173    @Override
174    public Object getObject(final int index) {
175        if (undefined.isSet(index)) {
176            return UNDEFINED;
177        }
178
179        return super.getObject(index);
180    }
181
182    @Override
183    public ArrayData delete(final int index) {
184        undefined.clear(index);
185
186        return super.delete(index);
187    }
188
189    @Override
190    public Object pop() {
191        final long index = length() - 1;
192
193        if (super.has((int)index)) {
194            final boolean isUndefined = undefined.isSet(index);
195            final Object value = super.pop();
196
197            return isUndefined ? UNDEFINED : value;
198        }
199
200        return super.pop();
201    }
202
203    @Override
204    public ArrayData slice(final long from, final long to) {
205        final ArrayData newArray = underlying.slice(from, to);
206        final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
207        newFilter.getUndefined().copy(undefined);
208        newFilter.getUndefined().shiftLeft(from, newFilter.length());
209
210        return newFilter;
211    }
212
213    private BitVector getUndefined() {
214        return undefined;
215    }
216}
217