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.runtime.arrays;
27
28 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
29 import java.lang.reflect.Array;
30 import jdk.nashorn.internal.runtime.BitVector;
31 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
32
33 /**
34 * This filter handles the presence of undefined array elements.
35 */
36 final 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 }
--- EOF ---