UndefinedArrayFilter.java revision 1101:be3f5ca1edbf
1231990Smp/*
259243Sobrien * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
359243Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
459243Sobrien *
559243Sobrien * This code is free software; you can redistribute it and/or modify it
659243Sobrien * under the terms of the GNU General Public License version 2 only, as
759243Sobrien * published by the Free Software Foundation.  Oracle designates this
859243Sobrien * particular file as subject to the "Classpath" exception as provided
959243Sobrien * by Oracle in the LICENSE file that accompanied this code.
1059243Sobrien *
1159243Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT
1259243Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1359243Sobrien * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1459243Sobrien * version 2 for more details (a copy is included in the LICENSE file that
1559243Sobrien * accompanied this code).
1659243Sobrien *
17100616Smp * You should have received a copy of the GNU General Public License version
1859243Sobrien * 2 along with this work; if not, write to the Free Software Foundation,
1959243Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2059243Sobrien *
2159243Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2259243Sobrien * or visit www.oracle.com if you need additional information or have any
2359243Sobrien * questions.
2459243Sobrien */
2559243Sobrien
2659243Sobrienpackage jdk.nashorn.internal.runtime.arrays;
2759243Sobrien
2859243Sobrienimport static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
2959243Sobrienimport java.lang.reflect.Array;
3059243Sobrienimport jdk.nashorn.internal.runtime.BitVector;
3159243Sobrienimport jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
3259243Sobrien
3359243Sobrien/**
3459243Sobrien * This filter handles the presence of undefined array elements.
35231990Smp */
3659243Sobrienfinal class UndefinedArrayFilter extends ArrayFilter {
3759243Sobrien    /** Bit vector tracking undefines. */
3859243Sobrien    private final BitVector undefined;
3959243Sobrien
4059243Sobrien    UndefinedArrayFilter(final ArrayData underlying) {
4169408Sache        super(underlying);
4259243Sobrien        this.undefined = new BitVector(underlying.length());
43167465Smp    }
44167465Smp
4569408Sache    @Override
4659243Sobrien    public ArrayData copy() {
4759243Sobrien        final UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
4859243Sobrien        copy.getUndefined().copy(undefined);
4959243Sobrien        return copy;
5059243Sobrien    }
5159243Sobrien
5259243Sobrien    @Override
5359243Sobrien    public Object[] asObjectArray() {
5459243Sobrien        final Object[] value = super.asObjectArray();
5559243Sobrien
5659243Sobrien        for (int i = 0; i < value.length; i++) {
5759243Sobrien            if (undefined.isSet(i)) {
58145479Smp                value[i] = UNDEFINED;
59145479Smp            }
60145479Smp        }
61145479Smp
62145479Smp        return value;
63145479Smp    }
64167465Smp
6559243Sobrien    @Override
66167465Smp    public Object asArrayOfType(final Class<?> componentType) {
67167465Smp        final Object value = super.asArrayOfType(componentType);
68167465Smp        final Object undefValue = convertUndefinedValue(componentType);
6959243Sobrien        final int l = Array.getLength(value);
70167465Smp        for (int i = 0; i < l; i++) {
71167465Smp            if (undefined.isSet(i)) {
72167465Smp                Array.set(value, i,undefValue);
7359243Sobrien            }
74167465Smp        }
75167465Smp
7659243Sobrien        return value;
77167465Smp    }
78167465Smp
7959243Sobrien    @Override
8059243Sobrien    public void shiftLeft(final int by) {
8159243Sobrien        super.shiftLeft(by);
8259243Sobrien        undefined.shiftLeft(by, length());
8359243Sobrien    }
8459243Sobrien
8559243Sobrien    @Override
86167465Smp    public ArrayData shiftRight(final int by) {
87167465Smp        super.shiftRight(by);
88167465Smp        undefined.shiftRight(by, length());
8961524Sobrien        return this;
9061524Sobrien    }
9161524Sobrien
9261524Sobrien    @Override
9361524Sobrien    public ArrayData ensure(final long safeIndex) {
9459243Sobrien        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= length()) {
9559243Sobrien            return new SparseArrayData(this, safeIndex + 1);
9659243Sobrien        }
9759243Sobrien
9859243Sobrien        super.ensure(safeIndex);
99167465Smp        undefined.resize(length());
10059243Sobrien
101167465Smp        return this;
102167465Smp    }
103167465Smp
104145479Smp    @Override
105145479Smp    public ArrayData shrink(final long newLength) {
10659243Sobrien        super.shrink(newLength);
10759243Sobrien        undefined.resize(length());
10859243Sobrien        return this;
109167465Smp    }
110167465Smp
11159243Sobrien    @Override
112167465Smp    public ArrayData set(final int index, final Object value, final boolean strict) {
11359243Sobrien        undefined.clear(index);
114167465Smp
11559243Sobrien        if (value == UNDEFINED) {
11659243Sobrien            undefined.set(index);
11759243Sobrien            return this;
11859243Sobrien        }
11959243Sobrien
12059243Sobrien        return super.set(index, value, strict);
121231990Smp    }
12259243Sobrien
12359243Sobrien    @Override
12459243Sobrien    public ArrayData set(final int index, final int value, final boolean strict) {
125167465Smp        undefined.clear(index);
12659243Sobrien
127167465Smp        return super.set(index, value, strict);
12859243Sobrien    }
12959243Sobrien
130167465Smp    @Override
13159243Sobrien    public ArrayData set(final int index, final long value, final boolean strict) {
13259243Sobrien        undefined.clear(index);
13359243Sobrien
13459243Sobrien        return super.set(index, value, strict);
13559243Sobrien    }
136167465Smp
137167465Smp    @Override
13859243Sobrien    public ArrayData set(final int index, final double value, final boolean strict) {
139167465Smp        undefined.clear(index);
14059243Sobrien
14159243Sobrien        return super.set(index, value, strict);
14259243Sobrien    }
143167465Smp
14459243Sobrien    @Override
145167465Smp    public int getInt(final int index) {
14659243Sobrien        if (undefined.isSet(index)) {
14759243Sobrien            return 0;
14859243Sobrien        }
14959243Sobrien
150167465Smp        return super.getInt(index);
15159243Sobrien    }
15259243Sobrien
15359243Sobrien    @Override
15459243Sobrien    public int getIntOptimistic(final int index, final int programPoint) {
15559243Sobrien        if (undefined.isSet(index)) {
15659243Sobrien            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
15759243Sobrien        }
15859243Sobrien
15959243Sobrien        return super.getIntOptimistic(index, programPoint);
16059243Sobrien    }
16159243Sobrien
162167465Smp    @Override
16359243Sobrien    public long getLong(final int index) {
16459243Sobrien        if (undefined.isSet(index)) {
16559243Sobrien            return 0L;
166167465Smp        }
16759243Sobrien
16859243Sobrien        return super.getLong(index);
16959243Sobrien    }
170167465Smp
17159243Sobrien    @Override
17259243Sobrien    public long getLongOptimistic(final int index, final int programPoint) {
17359243Sobrien        if (undefined.isSet(index)) {
17459243Sobrien            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
17559243Sobrien        }
17659243Sobrien
177231990Smp        return super.getLongOptimistic(index, programPoint);
17859243Sobrien    }
179167465Smp
180167465Smp    @Override
181167465Smp    public double getDouble(final int index) {
182167465Smp        if (undefined.isSet(index)) {
18359243Sobrien            return Double.NaN;
18459243Sobrien        }
18559243Sobrien
18659243Sobrien        return super.getDouble(index);
187167465Smp    }
18859243Sobrien
18959243Sobrien    @Override
19059243Sobrien    public double getDoubleOptimistic(final int index, final int programPoint) {
19159243Sobrien        if (undefined.isSet(index)) {
19259243Sobrien            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
193167465Smp        }
19459243Sobrien
195167465Smp        return super.getDoubleOptimistic(index, programPoint);
19659243Sobrien    }
19759243Sobrien
19859243Sobrien    @Override
19959243Sobrien    public Object getObject(final int index) {
20059243Sobrien        if (undefined.isSet(index)) {
201167465Smp            return UNDEFINED;
202167465Smp        }
203167465Smp
204167465Smp        return super.getObject(index);
205167465Smp    }
206167465Smp
20759243Sobrien    @Override
20859243Sobrien    public ArrayData delete(final int index) {
209167465Smp        undefined.clear(index);
210167465Smp
211167465Smp        return super.delete(index);
21259243Sobrien    }
21359243Sobrien
21459243Sobrien    @Override
21559243Sobrien    public Object pop() {
21659243Sobrien        final long index = length() - 1;
21759243Sobrien
21859243Sobrien        if (super.has((int)index)) {
21959243Sobrien            final boolean isUndefined = undefined.isSet(index);
22059243Sobrien            final Object value = super.pop();
22159243Sobrien
22259243Sobrien            return isUndefined ? UNDEFINED : value;
22359243Sobrien        }
224167465Smp
225167465Smp        return super.pop();
226167465Smp    }
227167465Smp
22859243Sobrien    @Override
229167465Smp    public ArrayData slice(final long from, final long to) {
23059243Sobrien        final ArrayData newArray = underlying.slice(from, to);
23159243Sobrien        final UndefinedArrayFilter newFilter = new UndefinedArrayFilter(newArray);
23259243Sobrien        newFilter.getUndefined().copy(undefined);
23359243Sobrien        newFilter.getUndefined().shiftLeft(from, newFilter.length());
23459243Sobrien
23559243Sobrien        return newFilter;
23659243Sobrien    }
23759243Sobrien
238100616Smp    private BitVector getUndefined() {
239100616Smp        return undefined;
24059243Sobrien    }
24159243Sobrien}
24259243Sobrien