diff options
Diffstat (limited to 'infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java')
-rw-r--r-- | infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java new file mode 100644 index 0000000..a9636a3 --- /dev/null +++ b/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java @@ -0,0 +1,388 @@ +/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Rhino code, released + * May 6, 1999. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1997-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Igor Bukanov + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU General Public License Version 2 or later (the "GPL"), in which + * case the provisions of the GPL are applicable instead of those above. If + * you wish to allow use of your version of this file only under the terms of + * the GPL and not to allow others to use your version of this file under the + * MPL, indicate your decision by deleting the provisions above and replacing + * them with the notice and other provisions required by the GPL. If you do + * not delete the provisions above, a recipient may use your version of this + * file under either the MPL or the GPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.javascript; + +import java.io.Serializable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** +Implementation of resizable array with focus on minimizing memory usage by storing few initial array elements in object fields. Can also be used as a stack. +*/ + +public class ObjArray implements Serializable +{ + static final long serialVersionUID = 4174889037736658296L; + + public ObjArray() { } + + public final boolean isSealed() + { + return sealed; + } + + public final void seal() + { + sealed = true; + } + + public final boolean isEmpty() + { + return size == 0; + } + + public final int size() + { + return size; + } + + public final void setSize(int newSize) + { + if (newSize < 0) throw new IllegalArgumentException(); + if (sealed) throw onSeledMutation(); + int N = size; + if (newSize < N) { + for (int i = newSize; i != N; ++i) { + setImpl(i, null); + } + } else if (newSize > N) { + if (newSize > FIELDS_STORE_SIZE) { + ensureCapacity(newSize); + } + } + size = newSize; + } + + public final Object get(int index) + { + if (!(0 <= index && index < size)) throw onInvalidIndex(index, size); + return getImpl(index); + } + + public final void set(int index, Object value) + { + if (!(0 <= index && index < size)) throw onInvalidIndex(index, size); + if (sealed) throw onSeledMutation(); + setImpl(index, value); + } + + private Object getImpl(int index) + { + switch (index) { + case 0: return f0; + case 1: return f1; + case 2: return f2; + case 3: return f3; + case 4: return f4; + } + return data[index - FIELDS_STORE_SIZE]; + } + + private void setImpl(int index, Object value) + { + switch (index) { + case 0: f0 = value; break; + case 1: f1 = value; break; + case 2: f2 = value; break; + case 3: f3 = value; break; + case 4: f4 = value; break; + default: data[index - FIELDS_STORE_SIZE] = value; + } + + } + + public int indexOf(Object obj) + { + int N = size; + for (int i = 0; i != N; ++i) { + Object current = getImpl(i); + if (current == obj || (current != null && current.equals(obj))) { + return i; + } + } + return -1; + } + + public int lastIndexOf(Object obj) + { + for (int i = size; i != 0;) { + --i; + Object current = getImpl(i); + if (current == obj || (current != null && current.equals(obj))) { + return i; + } + } + return -1; + } + + public final Object peek() + { + int N = size; + if (N == 0) throw onEmptyStackTopRead(); + return getImpl(N - 1); + } + + public final Object pop() + { + if (sealed) throw onSeledMutation(); + int N = size; + --N; + Object top; + switch (N) { + case -1: throw onEmptyStackTopRead(); + case 0: top = f0; f0 = null; break; + case 1: top = f1; f1 = null; break; + case 2: top = f2; f2 = null; break; + case 3: top = f3; f3 = null; break; + case 4: top = f4; f4 = null; break; + default: + top = data[N - FIELDS_STORE_SIZE]; + data[N - FIELDS_STORE_SIZE] = null; + } + size = N; + return top; + } + + public final void push(Object value) + { + add(value); + } + + public final void add(Object value) + { + if (sealed) throw onSeledMutation(); + int N = size; + if (N >= FIELDS_STORE_SIZE) { + ensureCapacity(N + 1); + } + size = N + 1; + setImpl(N, value); + } + + public final void add(int index, Object value) + { + int N = size; + if (!(0 <= index && index <= N)) throw onInvalidIndex(index, N + 1); + if (sealed) throw onSeledMutation(); + Object tmp; + switch (index) { + case 0: + if (N == 0) { f0 = value; break; } + tmp = f0; f0 = value; value = tmp; + case 1: + if (N == 1) { f1 = value; break; } + tmp = f1; f1 = value; value = tmp; + case 2: + if (N == 2) { f2 = value; break; } + tmp = f2; f2 = value; value = tmp; + case 3: + if (N == 3) { f3 = value; break; } + tmp = f3; f3 = value; value = tmp; + case 4: + if (N == 4) { f4 = value; break; } + tmp = f4; f4 = value; value = tmp; + + index = FIELDS_STORE_SIZE; + default: + ensureCapacity(N + 1); + if (index != N) { + System.arraycopy(data, index - FIELDS_STORE_SIZE, + data, index - FIELDS_STORE_SIZE + 1, + N - index); + } + data[index - FIELDS_STORE_SIZE] = value; + } + size = N + 1; + } + + public final void remove(int index) + { + int N = size; + if (!(0 <= index && index < N)) throw onInvalidIndex(index, N); + if (sealed) throw onSeledMutation(); + --N; + switch (index) { + case 0: + if (N == 0) { f0 = null; break; } + f0 = f1; + case 1: + if (N == 1) { f1 = null; break; } + f1 = f2; + case 2: + if (N == 2) { f2 = null; break; } + f2 = f3; + case 3: + if (N == 3) { f3 = null; break; } + f3 = f4; + case 4: + if (N == 4) { f4 = null; break; } + f4 = data[0]; + + index = FIELDS_STORE_SIZE; + default: + if (index != N) { + System.arraycopy(data, index - FIELDS_STORE_SIZE + 1, + data, index - FIELDS_STORE_SIZE, + N - index); + } + data[N - FIELDS_STORE_SIZE] = null; + } + size = N; + } + + public final void clear() + { + if (sealed) throw onSeledMutation(); + int N = size; + for (int i = 0; i != N; ++i) { + setImpl(i, null); + } + size = 0; + } + + public final Object[] toArray() + { + Object[] array = new Object[size]; + toArray(array, 0); + return array; + } + + public final void toArray(Object[] array) + { + toArray(array, 0); + } + + public final void toArray(Object[] array, int offset) + { + int N = size; + switch (N) { + default: + System.arraycopy(data, 0, array, offset + FIELDS_STORE_SIZE, + N - FIELDS_STORE_SIZE); + case 5: array[offset + 4] = f4; + case 4: array[offset + 3] = f3; + case 3: array[offset + 2] = f2; + case 2: array[offset + 1] = f1; + case 1: array[offset + 0] = f0; + case 0: break; + } + } + + private void ensureCapacity(int minimalCapacity) + { + int required = minimalCapacity - FIELDS_STORE_SIZE; + if (required <= 0) throw new IllegalArgumentException(); + if (data == null) { + int alloc = FIELDS_STORE_SIZE * 2; + if (alloc < required) { + alloc = required; + } + data = new Object[alloc]; + } else { + int alloc = data.length; + if (alloc < required) { + if (alloc <= FIELDS_STORE_SIZE) { + alloc = FIELDS_STORE_SIZE * 2; + } else { + alloc *= 2; + } + if (alloc < required) { + alloc = required; + } + Object[] tmp = new Object[alloc]; + if (size > FIELDS_STORE_SIZE) { + System.arraycopy(data, 0, tmp, 0, + size - FIELDS_STORE_SIZE); + } + data = tmp; + } + } + } + + private static RuntimeException onInvalidIndex(int index, int upperBound) + { + // \u2209 is "NOT ELEMENT OF" + String msg = index+" \u2209 [0, "+upperBound+')'; + throw new IndexOutOfBoundsException(msg); + } + + private static RuntimeException onEmptyStackTopRead() + { + throw new RuntimeException("Empty stack"); + } + + private static RuntimeException onSeledMutation() + { + throw new IllegalStateException("Attempt to modify sealed array"); + } + + private void writeObject(ObjectOutputStream os) throws IOException + { + os.defaultWriteObject(); + int N = size; + for (int i = 0; i != N; ++i) { + Object obj = getImpl(i); + os.writeObject(obj); + } + } + + private void readObject(ObjectInputStream is) + throws IOException, ClassNotFoundException + { + is.defaultReadObject(); // It reads size + int N = size; + if (N > FIELDS_STORE_SIZE) { + data = new Object[N - FIELDS_STORE_SIZE]; + } + for (int i = 0; i != N; ++i) { + Object obj = is.readObject(); + setImpl(i, obj); + } + } + +// Number of data elements + private int size; + + private boolean sealed; + + private static final int FIELDS_STORE_SIZE = 5; + private transient Object f0, f1, f2, f3, f4; + private transient Object[] data; +} |