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