aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java')
-rw-r--r--trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java388
1 files changed, 388 insertions, 0 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java b/trunk/infrastructure/rhino1_7R1/src/org/mozilla/javascript/ObjArray.java
new file mode 100644
index 0000000..a9636a3
--- /dev/null
+++ b/trunk/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;
+}