JS parser: removed unused classes and methods
This commit is contained in:
@@ -81,8 +81,6 @@ import java.util.MissingResourceException;
|
||||
*/
|
||||
|
||||
public class Context {
|
||||
public static final String languageVersionProperty = "language version";
|
||||
public static final String errorReporterProperty = "error reporter";
|
||||
|
||||
/**
|
||||
* Create a new Context.
|
||||
@@ -308,26 +306,6 @@ public class Context {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the implementation version.
|
||||
*
|
||||
* <p>
|
||||
* The implementation version is of the form
|
||||
* <pre>
|
||||
* "<i>name langVer</i> <code>release</code> <i>relNum date</i>"
|
||||
* </pre>
|
||||
* where <i>name</i> is the name of the product, <i>langVer</i> is
|
||||
* the language version, <i>relNum</i> is the release number, and
|
||||
* <i>date</i> is the release date for that specific
|
||||
* release in the form "yyyy mm dd".
|
||||
*
|
||||
* @return a string that encodes the product, language version, release
|
||||
* number, and date.
|
||||
*/
|
||||
public String getImplementationVersion() {
|
||||
return "Rhino 1.5 release 4.1 2003 04 21";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current error reporter.
|
||||
*
|
||||
@@ -361,49 +339,6 @@ public class Context {
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current locale.
|
||||
*
|
||||
* @see java.util.Locale
|
||||
*/
|
||||
public Locale setLocale(Locale loc) {
|
||||
Locale result = locale;
|
||||
locale = loc;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify any registered listeners that a bounded property has changed
|
||||
* @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
|
||||
* @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
|
||||
* @see java.beans.PropertyChangeListener
|
||||
* @see java.beans.PropertyChangeEvent
|
||||
* @param property the bound property
|
||||
* @param oldValue the old value
|
||||
* @param newVale the new value
|
||||
*/
|
||||
void firePropertyChange(String property, Object oldValue,
|
||||
Object newValue)
|
||||
{
|
||||
Object[] array = listeners;
|
||||
if (array != null) {
|
||||
firePropertyChangeImpl(array, property, oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void firePropertyChangeImpl(Object[] array, String property,
|
||||
Object oldValue, Object newValue)
|
||||
{
|
||||
for (int i = array.length; i-- != 0;) {
|
||||
Object obj = array[i];
|
||||
if (obj instanceof PropertyChangeListener) {
|
||||
PropertyChangeListener l = (PropertyChangeListener)obj;
|
||||
l.propertyChange(new PropertyChangeEvent(
|
||||
this, property, oldValue, newValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a warning using the error reporter for the current thread.
|
||||
*
|
||||
@@ -423,20 +358,6 @@ public class Context {
|
||||
lineSource, lineOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a warning using the error reporter for the current thread.
|
||||
*
|
||||
* @param message the warning message to report
|
||||
* @see org.mozilla.javascript.ErrorReporter
|
||||
*/
|
||||
/*
|
||||
public static void reportWarning(String message) {
|
||||
int[] linep = { 0 };
|
||||
String filename = getSourcePositionFromStack(linep);
|
||||
Context.reportWarning(message, filename, linep[0], null, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Report an error using the error reporter for the current thread.
|
||||
*
|
||||
@@ -461,155 +382,6 @@ public class Context {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an error using the error reporter for the current thread.
|
||||
*
|
||||
* @param message the error message to report
|
||||
* @see org.mozilla.javascript.ErrorReporter
|
||||
*/
|
||||
/*
|
||||
public static void reportError(String message) {
|
||||
int[] linep = { 0 };
|
||||
String filename = getSourcePositionFromStack(linep);
|
||||
Context.reportError(message, filename, linep[0], null, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Report a runtime error using the error reporter for the current thread.
|
||||
*
|
||||
* @param message the error message to report
|
||||
* @param sourceName a string describing the source, such as a filename
|
||||
* @param lineno the starting line number
|
||||
* @param lineSource the text of the line (may be null)
|
||||
* @param lineOffset the offset into lineSource where problem was detected
|
||||
* @return a runtime exception that will be thrown to terminate the
|
||||
* execution of the script
|
||||
* @see org.mozilla.javascript.ErrorReporter
|
||||
*/
|
||||
/*
|
||||
public static EvaluatorException reportRuntimeError(String message,
|
||||
String sourceName,
|
||||
int lineno,
|
||||
String lineSource,
|
||||
int lineOffset)
|
||||
{
|
||||
Context cx = getCurrentContext();
|
||||
if (cx != null) {
|
||||
cx.errorCount++;
|
||||
return cx.getErrorReporter().
|
||||
runtimeError(message, sourceName, lineno,
|
||||
lineSource, lineOffset);
|
||||
} else {
|
||||
throw new EvaluatorException(message);
|
||||
}
|
||||
}
|
||||
|
||||
static EvaluatorException reportRuntimeError0(String messageId) {
|
||||
return reportRuntimeError(getMessage0(messageId));
|
||||
}
|
||||
|
||||
static EvaluatorException reportRuntimeError1
|
||||
(String messageId, Object arg1)
|
||||
{
|
||||
return reportRuntimeError(getMessage1(messageId, arg1));
|
||||
}
|
||||
|
||||
static EvaluatorException reportRuntimeError2
|
||||
(String messageId, Object arg1, Object arg2)
|
||||
{
|
||||
return reportRuntimeError(getMessage2(messageId, arg1, arg2));
|
||||
}
|
||||
|
||||
static EvaluatorException reportRuntimeError3
|
||||
(String messageId, Object arg1, Object arg2, Object arg3)
|
||||
{
|
||||
return reportRuntimeError(getMessage3(messageId, arg1, arg2, arg3));
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Report a runtime error using the error reporter for the current thread.
|
||||
*
|
||||
* @param message the error message to report
|
||||
* @see org.mozilla.javascript.ErrorReporter
|
||||
*/
|
||||
/*
|
||||
public static EvaluatorException reportRuntimeError(String message) {
|
||||
int[] linep = { 0 };
|
||||
String filename = getSourcePositionFromStack(linep);
|
||||
return Context.reportRuntimeError(message, filename, linep[0], null, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get a value corresponding to a key.
|
||||
* <p>
|
||||
* Since the Context is associated with a thread it can be
|
||||
* used to maintain values that can be later retrieved using
|
||||
* the current thread.
|
||||
* <p>
|
||||
* Note that the values are maintained with the Context, so
|
||||
* if the Context is disassociated from the thread the values
|
||||
* cannot be retreived. Also, if private data is to be maintained
|
||||
* in this manner the key should be a java.lang.Object
|
||||
* whose reference is not divulged to untrusted code.
|
||||
* @param key the key used to lookup the value
|
||||
* @return a value previously stored using putThreadLocal.
|
||||
*/
|
||||
public final Object getThreadLocal(Object key) {
|
||||
if (hashtable == null)
|
||||
return null;
|
||||
return hashtable.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value that can later be retrieved using a given key.
|
||||
* <p>
|
||||
* @param key the key used to index the value
|
||||
* @param value the value to save
|
||||
*/
|
||||
public void putThreadLocal(Object key, Object value) {
|
||||
if (hashtable == null)
|
||||
hashtable = new Hashtable();
|
||||
hashtable.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove values from thread-local storage.
|
||||
* @param key the key for the entry to remove.
|
||||
* @since 1.5 release 2
|
||||
*/
|
||||
public void removeThreadLocal(Object key) {
|
||||
if (hashtable == null)
|
||||
return;
|
||||
hashtable.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether functions are compiled by this context using
|
||||
* dynamic scope.
|
||||
* <p>
|
||||
* If functions are compiled with dynamic scope, then they execute
|
||||
* in the scope of their caller, rather than in their parent scope.
|
||||
* This is useful for sharing functions across multiple scopes.
|
||||
* @since 1.5 Release 1
|
||||
*/
|
||||
public final boolean hasCompileFunctionsWithDynamicScope() {
|
||||
return compileFunctionsWithDynamicScopeFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether functions compiled by this context should use
|
||||
* dynamic scope.
|
||||
* <p>
|
||||
* @param flag if true, compile functions with dynamic scope
|
||||
* @since 1.5 Release 1
|
||||
*/
|
||||
public void setCompileFunctionsWithDynamicScope(boolean flag) {
|
||||
compileFunctionsWithDynamicScopeFlag = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* if hasFeature(FEATURE_NON_ECMA_GET_YEAR) returns true,
|
||||
* Date.prototype.getYear subtructs 1900 only if 1900 <= date < 2000
|
||||
@@ -690,21 +462,11 @@ public class Context {
|
||||
return getMessage(messageId, null);
|
||||
}
|
||||
|
||||
static String getMessage1(String messageId, Object arg1) {
|
||||
Object[] arguments = {arg1};
|
||||
return getMessage(messageId, arguments);
|
||||
}
|
||||
|
||||
static String getMessage2(String messageId, Object arg1, Object arg2) {
|
||||
Object[] arguments = {arg1, arg2};
|
||||
return getMessage(messageId, arguments);
|
||||
}
|
||||
|
||||
static String getMessage3
|
||||
(String messageId, Object arg1, Object arg2, Object arg3) {
|
||||
Object[] arguments = {arg1, arg2, arg3};
|
||||
return getMessage(messageId, arguments);
|
||||
}
|
||||
/**
|
||||
* Internal method that reports an error for missing calls to
|
||||
* enter().
|
||||
@@ -734,11 +496,6 @@ public class Context {
|
||||
static final boolean printTrees = true;
|
||||
static final boolean printICode = true;
|
||||
|
||||
final boolean isVersionECMA1() {
|
||||
return version == VERSION_DEFAULT || version >= VERSION_1_3;
|
||||
}
|
||||
|
||||
|
||||
// Rudimentary support for Design-by-Contract
|
||||
static void codeBug() {
|
||||
throw new RuntimeException("FAILED ASSERTION");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -404,37 +404,6 @@ public class IRFactory {
|
||||
return new Node(TokenStream.ASSIGN, left, right, nodeOp);
|
||||
}
|
||||
|
||||
private Node createConvert(Class toType, Node expr) {
|
||||
if (toType == null)
|
||||
return expr;
|
||||
Node result = new Node(TokenStream.CONVERT, expr);
|
||||
result.putProp(Node.TYPE_PROP, Number.class);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean hasSideEffects(Node exprTree) {
|
||||
switch (exprTree.getType()) {
|
||||
case TokenStream.INC:
|
||||
case TokenStream.DEC:
|
||||
case TokenStream.SETPROP:
|
||||
case TokenStream.SETELEM:
|
||||
case TokenStream.SETNAME:
|
||||
case TokenStream.CALL:
|
||||
case TokenStream.NEW:
|
||||
return true;
|
||||
default:
|
||||
Node child = exprTree.getFirstChild();
|
||||
while (child != null) {
|
||||
if (hasSideEffects(child))
|
||||
return true;
|
||||
else
|
||||
child = child.getNext();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void reportError(String msgResource) {
|
||||
|
||||
String message = Context.getMessage0(msgResource);
|
||||
|
||||
@@ -214,18 +214,10 @@ public class Node implements Cloneable {
|
||||
return this.intDatum;
|
||||
}
|
||||
|
||||
public boolean hasChildren() {
|
||||
return first != null;
|
||||
}
|
||||
|
||||
public Node getFirstChild() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public Node getLastChild() {
|
||||
return last;
|
||||
}
|
||||
|
||||
public Node getNext() {
|
||||
return next;
|
||||
}
|
||||
@@ -238,19 +230,6 @@ public class Node implements Cloneable {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
public Node getChildBefore(Node child) {
|
||||
if (child == first)
|
||||
return null;
|
||||
Node n = first;
|
||||
while (n.next != child) {
|
||||
n = n.next;
|
||||
if (n == null)
|
||||
throw new RuntimeException("node is not a child");
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public Node getLastSibling() {
|
||||
Node n = this;
|
||||
while (n.next != null) {
|
||||
@@ -259,14 +238,6 @@ public class Node implements Cloneable {
|
||||
return n;
|
||||
}
|
||||
|
||||
public void addChildToFront(Node child) {
|
||||
child.next = first;
|
||||
first = child;
|
||||
if (last == null) {
|
||||
last = child;
|
||||
}
|
||||
}
|
||||
|
||||
public void addChildToBack(Node child) {
|
||||
child.next = null;
|
||||
if (last == null) {
|
||||
@@ -277,15 +248,6 @@ public class Node implements Cloneable {
|
||||
last = child;
|
||||
}
|
||||
|
||||
public void addChildrenToFront(Node children) {
|
||||
Node lastSib = children.getLastSibling();
|
||||
lastSib.next = first;
|
||||
first = children;
|
||||
if (last == null) {
|
||||
last = lastSib;
|
||||
}
|
||||
}
|
||||
|
||||
public void addChildrenToBack(Node children) {
|
||||
if (last != null) {
|
||||
last.next = children;
|
||||
@@ -296,67 +258,6 @@ public class Node implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'child' before 'node'.
|
||||
*/
|
||||
public void addChildBefore(Node newChild, Node node) {
|
||||
if (newChild.next != null)
|
||||
throw new RuntimeException(
|
||||
"newChild had siblings in addChildBefore");
|
||||
if (first == node) {
|
||||
newChild.next = first;
|
||||
first = newChild;
|
||||
return;
|
||||
}
|
||||
Node prev = getChildBefore(node);
|
||||
addChildAfter(newChild, prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 'child' after 'node'.
|
||||
*/
|
||||
public void addChildAfter(Node newChild, Node node) {
|
||||
if (newChild.next != null)
|
||||
throw new RuntimeException(
|
||||
"newChild had siblings in addChildAfter");
|
||||
newChild.next = node.next;
|
||||
node.next = newChild;
|
||||
if (last == node)
|
||||
last = newChild;
|
||||
}
|
||||
|
||||
public void removeChild(Node child) {
|
||||
Node prev = getChildBefore(child);
|
||||
if (prev == null)
|
||||
first = first.next;
|
||||
else
|
||||
prev.next = child.next;
|
||||
if (child == last) last = prev;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public void replaceChild(Node child, Node newChild) {
|
||||
newChild.next = child.next;
|
||||
if (child == first) {
|
||||
first = newChild;
|
||||
} else {
|
||||
Node prev = getChildBefore(child);
|
||||
prev.next = newChild;
|
||||
}
|
||||
if (child == last)
|
||||
last = newChild;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public void replaceChildAfter(Node prevChild, Node newChild) {
|
||||
Node child = prevChild.next;
|
||||
newChild.next = child.next;
|
||||
prevChild.next = newChild;
|
||||
if (child == last)
|
||||
last = newChild;
|
||||
child.next = null;
|
||||
}
|
||||
|
||||
public static final int
|
||||
TARGET_PROP = 1,
|
||||
BREAK_PROP = 2,
|
||||
@@ -458,16 +359,6 @@ public class Node implements Cloneable {
|
||||
return props.getObject(propType);
|
||||
}
|
||||
|
||||
public int getIntProp(int propType, int defaultValue) {
|
||||
if (props == null)
|
||||
return defaultValue;
|
||||
return props.getInt(propType, defaultValue);
|
||||
}
|
||||
|
||||
public int getExistingIntProp(int propType) {
|
||||
return props.getExistingInt(propType);
|
||||
}
|
||||
|
||||
public void putProp(int propType, Object prop) {
|
||||
if (prop == null) {
|
||||
removeProp(propType);
|
||||
@@ -561,37 +452,6 @@ public class Node implements Cloneable {
|
||||
|| this.getIntDatum() == ((Node) o).getIntDatum();
|
||||
}
|
||||
|
||||
public Node cloneNode() {
|
||||
Node result;
|
||||
try {
|
||||
result = (Node) super.clone();
|
||||
result.next = null;
|
||||
result.first = null;
|
||||
result.last = null;
|
||||
}
|
||||
catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Node cloneTree() {
|
||||
Node result = cloneNode();
|
||||
for (Node n2 = getFirstChild(); n2 != null; n2 = n2.getNext()) {
|
||||
Node n2clone = n2.cloneTree();
|
||||
if (result.last != null) {
|
||||
result.last.next = n2clone;
|
||||
}
|
||||
if (result.first == null) {
|
||||
result.first = n2clone;
|
||||
}
|
||||
result.last = n2clone;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (Context.printTrees) {
|
||||
@@ -661,70 +521,10 @@ public class Node implements Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toStringTree() {
|
||||
return toStringTreeHelper(0);
|
||||
}
|
||||
|
||||
|
||||
private String toStringTreeHelper(int level) {
|
||||
if (Context.printTrees) {
|
||||
StringBuffer s = new StringBuffer();
|
||||
for (int i=0; i < level; i++) {
|
||||
s.append(" ");
|
||||
}
|
||||
s.append(toString());
|
||||
s.append('\n');
|
||||
for (Node cursor = getFirstChild(); cursor != null;
|
||||
cursor = cursor.getNext())
|
||||
{
|
||||
Node n = cursor;
|
||||
s.append(n.toStringTreeHelper(level+1));
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the subtree under this node is the same as another subtree.
|
||||
* Returns null if it's equal, or a message describing the differences.
|
||||
*/
|
||||
public String checkTreeEquals(Node node2) {
|
||||
boolean eq = false;
|
||||
|
||||
if (type == node2.getType() &&
|
||||
getChildCount() == node2.getChildCount() &&
|
||||
getClass() == node2.getClass()) {
|
||||
|
||||
eq = this.equals(node2);
|
||||
}
|
||||
|
||||
if (!eq) {
|
||||
return "Node tree inequality:\nTree1:\n" + toStringTreeHelper(1) +
|
||||
"\n\nTree2:\n" + node2.toStringTreeHelper(1);
|
||||
}
|
||||
|
||||
String res = null;
|
||||
Node n, n2;
|
||||
for (n = first, n2 = node2.first;
|
||||
res == null && n != null;
|
||||
n = n.next, n2 = n2.next) {
|
||||
res = n.checkTreeEquals(n2);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void setIsSyntheticBlock(boolean val) {
|
||||
isSyntheticBlock = val;
|
||||
}
|
||||
|
||||
public boolean isSyntheticBlock() {
|
||||
return isSyntheticBlock;
|
||||
}
|
||||
|
||||
int type; // type of the node; TokenStream.NAME for example
|
||||
Node next; // next sibling
|
||||
private Node first; // first element of a linked list of children
|
||||
|
||||
@@ -1,694 +0,0 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* 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 Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Igor Bukanov
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (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 NPL, indicate your decision by
|
||||
* deleting the provisions above and replace 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 NPL or the GPL.
|
||||
*/
|
||||
// Modified by Google
|
||||
|
||||
package com.google.gwt.dev.js.rhino;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Map to associate objects to integers.
|
||||
* The map does not synchronize any of its operation, so either use
|
||||
* it from a single thread or do own synchronization or perform all mutation
|
||||
* operations on one thread before passing the map to others
|
||||
*/
|
||||
|
||||
public class ObjToIntMap implements Serializable {
|
||||
|
||||
public static final Object NULL_VALUE = new String("");
|
||||
|
||||
// Map implementation via hashtable,
|
||||
// follows "The Art of Computer Programming" by Donald E. Knuth
|
||||
|
||||
// ObjToIntMap is a copy cat of ObjToIntMap with API adjusted to object keys
|
||||
|
||||
public static class Iterator {
|
||||
|
||||
Iterator(ObjToIntMap master) {
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
final void init(Object[] keys, int[] values, int keyCount) {
|
||||
this.keys = keys;
|
||||
this.values = values;
|
||||
this.cursor = -1;
|
||||
this.remaining = keyCount;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
master.initIterator(this);
|
||||
next();
|
||||
}
|
||||
|
||||
public boolean done() {
|
||||
return remaining < 0;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
if (remaining == -1) Context.codeBug();
|
||||
if (remaining == 0) {
|
||||
remaining = -1;
|
||||
cursor = -1;
|
||||
}else {
|
||||
for (++cursor; ; ++cursor) {
|
||||
Object key = keys[cursor];
|
||||
if (key != null && key != DELETED) {
|
||||
--remaining;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
Object key = keys[cursor];
|
||||
if (key == NULL_VALUE) { key = null; }
|
||||
return key;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return values[cursor];
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
values[cursor] = value;
|
||||
}
|
||||
|
||||
ObjToIntMap master;
|
||||
private int cursor;
|
||||
private int remaining;
|
||||
private Object[] keys;
|
||||
private int[] values;
|
||||
}
|
||||
|
||||
public ObjToIntMap() {
|
||||
this(4);
|
||||
}
|
||||
|
||||
public ObjToIntMap(int keyCountHint) {
|
||||
if (keyCountHint < 0) Context.codeBug();
|
||||
// Table grow when number of stored keys >= 3/4 of max capacity
|
||||
int minimalCapacity = keyCountHint * 4 / 3;
|
||||
int i;
|
||||
for (i = 2; (1 << i) < minimalCapacity; ++i) { }
|
||||
power = i;
|
||||
if (check && power < 2) Context.codeBug();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return keyCount == 0;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return keyCount;
|
||||
}
|
||||
|
||||
public boolean has(Object key) {
|
||||
if (key == null) { key = NULL_VALUE; }
|
||||
return 0 <= findIndex(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get integer value assigned with key.
|
||||
* @return key integer value or defaultValue if key is absent
|
||||
*/
|
||||
public int get(Object key, int defaultValue) {
|
||||
if (key == null) { key = NULL_VALUE; }
|
||||
int index = findIndex(key);
|
||||
if (0 <= index) {
|
||||
return values[index];
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get integer value assigned with key.
|
||||
* @return key integer value
|
||||
* @throws RuntimeException if key does not exist
|
||||
*/
|
||||
public int getExisting(Object key) {
|
||||
if (key == null) { key = NULL_VALUE; }
|
||||
int index = findIndex(key);
|
||||
if (0 <= index) {
|
||||
return values[index];
|
||||
}
|
||||
// Key must exist
|
||||
Context.codeBug();
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void put(Object key, int value) {
|
||||
if (key == null) { key = NULL_VALUE; }
|
||||
int index = ensureIndex(key);
|
||||
values[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If table already contains a key that equals to keyArg, return that key
|
||||
* while setting its value to zero, otherwise add keyArg with 0 value to
|
||||
* the table and return it.
|
||||
*/
|
||||
public Object intern(Object keyArg) {
|
||||
boolean nullKey = false;
|
||||
if (keyArg == null) {
|
||||
nullKey = true;
|
||||
keyArg = NULL_VALUE;
|
||||
}
|
||||
int index = ensureIndex(keyArg);
|
||||
values[index] = 0;
|
||||
return (nullKey) ? null : keys[index];
|
||||
}
|
||||
|
||||
public void remove(Object key) {
|
||||
if (key == null) { key = NULL_VALUE; }
|
||||
int index = findIndex(key);
|
||||
if (0 <= index) {
|
||||
keys[index] = DELETED;
|
||||
--keyCount;
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
int i = keys.length;
|
||||
while (i != 0) {
|
||||
keys[--i] = null;
|
||||
}
|
||||
keyCount = 0;
|
||||
occupiedCount = 0;
|
||||
}
|
||||
|
||||
public Iterator newIterator() {
|
||||
return new Iterator(this);
|
||||
}
|
||||
|
||||
// The sole purpose of the method is to avoid accessing private fields
|
||||
// from the Iterator inner class to workaround JDK 1.1 compiler bug which
|
||||
// generates code triggering VerifierError on recent JVMs
|
||||
final void initIterator(Iterator i) {
|
||||
i.init(keys, values, keyCount);
|
||||
}
|
||||
|
||||
/** Return array of present keys */
|
||||
public Object[] getKeys() {
|
||||
Object[] array = new Object[keyCount];
|
||||
getKeys(array, 0);
|
||||
return array;
|
||||
}
|
||||
|
||||
public void getKeys(Object[] array, int offset) {
|
||||
int count = keyCount;
|
||||
for (int i = 0; count != 0; ++i) {
|
||||
Object key = keys[i];
|
||||
if (key != null && key != DELETED) {
|
||||
if (key == NULL_VALUE) { key = null; }
|
||||
array[offset] = key;
|
||||
++offset;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int tableLookupStep(int fraction, int mask, int power) {
|
||||
int shift = 32 - 2 * power;
|
||||
if (shift >= 0) {
|
||||
return ((fraction >>> shift) & mask) | 1;
|
||||
}
|
||||
else {
|
||||
return (fraction & (mask >>> -shift)) | 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int findIndex(Object key) {
|
||||
if (keys != null) {
|
||||
int hash = key.hashCode();
|
||||
int fraction = hash * A;
|
||||
int index = fraction >>> (32 - power);
|
||||
Object test = keys[index];
|
||||
if (test != null) {
|
||||
int N = 1 << power;
|
||||
if (test == key
|
||||
|| (values[N + index] == hash && test.equals(key)))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
// Search in table after first failed attempt
|
||||
int mask = N - 1;
|
||||
int step = tableLookupStep(fraction, mask, power);
|
||||
int n = 0;
|
||||
for (;;) {
|
||||
if (check) {
|
||||
if (n >= occupiedCount) Context.codeBug();
|
||||
++n;
|
||||
}
|
||||
index = (index + step) & mask;
|
||||
test = keys[index];
|
||||
if (test == null) {
|
||||
break;
|
||||
}
|
||||
if (test == key
|
||||
|| (values[N + index] == hash && test.equals(key)))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Insert key that is not present to table without deleted entries
|
||||
// and enough free space
|
||||
private int insertNewKey(Object key, int hash) {
|
||||
if (check && occupiedCount != keyCount) Context.codeBug();
|
||||
if (check && keyCount == 1 << power) Context.codeBug();
|
||||
int fraction = hash * A;
|
||||
int index = fraction >>> (32 - power);
|
||||
int N = 1 << power;
|
||||
if (keys[index] != null) {
|
||||
int mask = N - 1;
|
||||
int step = tableLookupStep(fraction, mask, power);
|
||||
int firstIndex = index;
|
||||
do {
|
||||
if (check && keys[index] == DELETED) Context.codeBug();
|
||||
index = (index + step) & mask;
|
||||
if (check && firstIndex == index) Context.codeBug();
|
||||
} while (keys[index] != null);
|
||||
}
|
||||
keys[index] = key;
|
||||
values[N + index] = hash;
|
||||
++occupiedCount;
|
||||
++keyCount;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private void rehashTable() {
|
||||
if (keys == null) {
|
||||
if (check && keyCount != 0) Context.codeBug();
|
||||
if (check && occupiedCount != 0) Context.codeBug();
|
||||
int N = 1 << power;
|
||||
keys = new Object[N];
|
||||
values = new int[2 * N];
|
||||
}
|
||||
else {
|
||||
// Check if removing deleted entries would free enough space
|
||||
if (keyCount * 2 >= occupiedCount) {
|
||||
// Need to grow: less then half of deleted entries
|
||||
++power;
|
||||
}
|
||||
int N = 1 << power;
|
||||
Object[] oldKeys = keys;
|
||||
int[] oldValues = values;
|
||||
int oldN = oldKeys.length;
|
||||
keys = new Object[N];
|
||||
values = new int[2 * N];
|
||||
|
||||
int remaining = keyCount;
|
||||
occupiedCount = keyCount = 0;
|
||||
for (int i = 0; remaining != 0; ++i) {
|
||||
Object key = oldKeys[i];
|
||||
if (key != null && key != DELETED) {
|
||||
int keyHash = oldValues[oldN + i];
|
||||
int index = insertNewKey(key, keyHash);
|
||||
values[index] = oldValues[i];
|
||||
--remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure key index creating one if necessary
|
||||
private int ensureIndex(Object key) {
|
||||
int hash = key.hashCode();
|
||||
int index = -1;
|
||||
int firstDeleted = -1;
|
||||
if (keys != null) {
|
||||
int fraction = hash * A;
|
||||
index = fraction >>> (32 - power);
|
||||
Object test = keys[index];
|
||||
if (test != null) {
|
||||
int N = 1 << power;
|
||||
if (test == key
|
||||
|| (values[N + index] == hash && test.equals(key)))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
if (test == DELETED) {
|
||||
firstDeleted = index;
|
||||
}
|
||||
|
||||
// Search in table after first failed attempt
|
||||
int mask = N - 1;
|
||||
int step = tableLookupStep(fraction, mask, power);
|
||||
int n = 0;
|
||||
for (;;) {
|
||||
if (check) {
|
||||
if (n >= occupiedCount) Context.codeBug();
|
||||
++n;
|
||||
}
|
||||
index = (index + step) & mask;
|
||||
test = keys[index];
|
||||
if (test == null) {
|
||||
break;
|
||||
}
|
||||
if (test == key
|
||||
|| (values[N + index] == hash && test.equals(key)))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
if (test == DELETED && firstDeleted < 0) {
|
||||
firstDeleted = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Inserting of new key
|
||||
if (check && keys != null && keys[index] != null)
|
||||
Context.codeBug();
|
||||
if (firstDeleted >= 0) {
|
||||
index = firstDeleted;
|
||||
}
|
||||
else {
|
||||
// Need to consume empty entry: check occupation level
|
||||
if (keys == null || occupiedCount * 4 >= (1 << power) * 3) {
|
||||
// Too litle unused entries: rehash
|
||||
rehashTable();
|
||||
return insertNewKey(key, hash);
|
||||
}
|
||||
++occupiedCount;
|
||||
}
|
||||
keys[index] = key;
|
||||
values[(1 << power) + index] = hash;
|
||||
++keyCount;
|
||||
return index;
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.defaultWriteObject();
|
||||
|
||||
int count = keyCount;
|
||||
for (int i = 0; count != 0; ++i) {
|
||||
Object key = keys[i];
|
||||
if (key != null && key != DELETED) {
|
||||
--count;
|
||||
out.writeObject(key);
|
||||
out.writeInt(values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
|
||||
int writtenKeyCount = keyCount;
|
||||
if (writtenKeyCount != 0) {
|
||||
keyCount = 0;
|
||||
int N = 1 << power;
|
||||
keys = new Object[N];
|
||||
values = new int[2 * N];
|
||||
for (int i = 0; i != writtenKeyCount; ++i) {
|
||||
Object key = in.readObject();
|
||||
int hash = key.hashCode();
|
||||
int index = insertNewKey(key, hash);
|
||||
values[index] = in.readInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final long serialVersionUID = 3396438333234169727L;
|
||||
|
||||
// A == golden_ratio * (1 << 32) = ((sqrt(5) - 1) / 2) * (1 << 32)
|
||||
// See Knuth etc.
|
||||
private static final int A = 0x9e3779b9;
|
||||
|
||||
private static final Object DELETED = new Object();
|
||||
|
||||
// Structure of kyes and values arrays (N == 1 << power):
|
||||
// keys[0 <= i < N]: key value or null or DELETED mark
|
||||
// values[0 <= i < N]: value of key at keys[i]
|
||||
// values[N <= i < 2*N]: hash code of key at keys[i-N]
|
||||
|
||||
private transient Object[] keys;
|
||||
private transient int[] values;
|
||||
|
||||
private int power;
|
||||
private int keyCount;
|
||||
private transient int occupiedCount; // == keyCount + deleted_count
|
||||
|
||||
// If true, enables consitency checks
|
||||
private static final boolean check = false;
|
||||
|
||||
/* TEST START
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (!check) {
|
||||
System.err.println("Set check to true and re-run");
|
||||
throw new RuntimeException("Set check to true and re-run");
|
||||
}
|
||||
|
||||
ObjToIntMap map;
|
||||
map = new ObjToIntMap(0);
|
||||
testHash(map, 3);
|
||||
map = new ObjToIntMap(0);
|
||||
testHash(map, 10 * 1000);
|
||||
map = new ObjToIntMap();
|
||||
testHash(map, 10 * 1000);
|
||||
map = new ObjToIntMap(30 * 1000);
|
||||
testHash(map, 10 * 100);
|
||||
map.clear();
|
||||
testHash(map, 4);
|
||||
map = new ObjToIntMap(0);
|
||||
testHash(map, 10 * 100);
|
||||
}
|
||||
|
||||
private static void testHash(ObjToIntMap map, int N) {
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
check(-1 == map.get(key, -1));
|
||||
map.put(key, i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
map.put(key, i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
check(map.size() == N);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
Object[] keys = map.getKeys();
|
||||
check(keys.length == N);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = keys[i];
|
||||
check(map.has(key));
|
||||
}
|
||||
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
int Nsqrt = -1;
|
||||
for (int i = 0; ; ++i) {
|
||||
if (i * i >= N) {
|
||||
Nsqrt = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i * i);
|
||||
map.put(key, i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
check(map.size() == 2 * N - Nsqrt);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i * i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(-1 - i * i);
|
||||
map.put(key, i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
check(map.size() == 3 * N - Nsqrt);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(-1 - i * i);
|
||||
map.remove(key);
|
||||
check(!map.has(key));
|
||||
}
|
||||
|
||||
check(map.size() == 2 * N - Nsqrt);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i * i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
int j = intSqrt(i);
|
||||
if (j * j == i) {
|
||||
check(j == map.get(key, -1));
|
||||
}else {
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i * i);
|
||||
map.remove(key);
|
||||
check(-2 == map.get(key, -2));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
map.put(key, i);
|
||||
check(i == map.get(key, -2));
|
||||
}
|
||||
|
||||
check(map.size() == N);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
check(i == map.get(key, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
ObjToIntMap copy = (ObjToIntMap)writeAndRead(map);
|
||||
check(copy.size() == N);
|
||||
|
||||
for (int i = 0; i != N; ++i) {
|
||||
Object key = testKey(i);
|
||||
check(i == copy.get(key, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
checkSameMaps(copy, map);
|
||||
|
||||
System.out.println(); System.out.flush();
|
||||
}
|
||||
|
||||
private static void checkSameMaps(ObjToIntMap map1, ObjToIntMap map2) {
|
||||
check(map1.size() == map2.size());
|
||||
Object[] keys = map1.getKeys();
|
||||
check(keys.length == map1.size());
|
||||
for (int i = 0; i != keys.length; ++i) {
|
||||
check(map1.get(keys[i], -1) == map2.get(keys[i], -1));
|
||||
}
|
||||
}
|
||||
|
||||
private static void check(boolean condition) {
|
||||
if (!condition) Context.codeBug();
|
||||
}
|
||||
|
||||
private static Object[] testPool;
|
||||
|
||||
private static Object testKey(int i) {
|
||||
int MAX_POOL = 100;
|
||||
if (0 <= i && i < MAX_POOL) {
|
||||
if (testPool != null && testPool[i] != null) {
|
||||
return testPool[i];
|
||||
}
|
||||
}
|
||||
Object x = new Double(i + 0.5);
|
||||
if (0 <= i && i < MAX_POOL) {
|
||||
if (testPool == null) {
|
||||
testPool = new Object[MAX_POOL];
|
||||
}
|
||||
testPool[i] = x;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
private static int intSqrt(int i) {
|
||||
int approx = (int)Math.sqrt(i) + 1;
|
||||
while (approx * approx > i) {
|
||||
--approx;
|
||||
}
|
||||
return approx;
|
||||
}
|
||||
|
||||
private static Object writeAndRead(Object obj) {
|
||||
try {
|
||||
java.io.ByteArrayOutputStream
|
||||
bos = new java.io.ByteArrayOutputStream();
|
||||
java.io.ObjectOutputStream
|
||||
out = new java.io.ObjectOutputStream(bos);
|
||||
out.writeObject(obj);
|
||||
out.close();
|
||||
byte[] data = bos.toByteArray();
|
||||
java.io.ByteArrayInputStream
|
||||
bis = new java.io.ByteArrayInputStream(data);
|
||||
java.io.ObjectInputStream
|
||||
in = new java.io.ObjectInputStream(bis);
|
||||
Object result = in.readObject();
|
||||
in.close();
|
||||
return result;
|
||||
}catch (Exception ex) {
|
||||
throw new RuntimeException("Unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
// TEST END */
|
||||
|
||||
}
|
||||
@@ -49,31 +49,6 @@ public class ScriptRuntime {
|
||||
|
||||
public static double NaN = 0.0d / 0.0;
|
||||
|
||||
public static String numberToString(double d, int base) {
|
||||
if (Double.isNaN(d))
|
||||
return "NaN";
|
||||
if (d == Double.POSITIVE_INFINITY)
|
||||
return "Infinity";
|
||||
if (d == Double.NEGATIVE_INFINITY)
|
||||
return "-Infinity";
|
||||
if (d == 0.0)
|
||||
return "0";
|
||||
|
||||
if ((base < 2) || (base > 36)) {
|
||||
throw new Error(Context.getMessage1("msg.bad.radix",
|
||||
Integer.toString(base)));
|
||||
}
|
||||
|
||||
if (base != 10) {
|
||||
return DToA.JS_dtobasestr(base, d);
|
||||
} else {
|
||||
StringBuffer result = new StringBuffer();
|
||||
DToA.JS_dtostr(result, DToA.DTOSTR_STANDARD, 0, d);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for toNumber, parseInt, and TokenStream.getToken.
|
||||
*/
|
||||
@@ -171,68 +146,4 @@ public class ScriptRuntime {
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* For escaping strings printed by object and array literals; not quite
|
||||
* the same as 'escape.'
|
||||
*/
|
||||
public static String escapeString(String s) {
|
||||
|
||||
StringBuffer sb = null;
|
||||
|
||||
for(int i = 0, L = s.length(); i != L; ++i) {
|
||||
int c = s.charAt(i);
|
||||
|
||||
if (' ' <= c && c <= '~' && c != '"' && c != '\\') {
|
||||
// an ordinary print character (like C isprint()) and not "
|
||||
// or \ . Note single quote ' is not escaped
|
||||
if (sb != null) {
|
||||
sb.append((char)c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (sb == null) {
|
||||
sb = new StringBuffer(L + 3);
|
||||
sb.append(s);
|
||||
sb.setLength(i);
|
||||
}
|
||||
|
||||
int escape = -1;
|
||||
switch (c) {
|
||||
case '\b': escape = 'b'; break;
|
||||
case '\f': escape = 'f'; break;
|
||||
case '\n': escape = 'n'; break;
|
||||
case '\r': escape = 'r'; break;
|
||||
case '\t': escape = 't'; break;
|
||||
case 0xb: escape = 'v'; break; // Java lacks \v.
|
||||
case '"': escape = '"'; break;
|
||||
case ' ': escape = ' '; break;
|
||||
case '\\': escape = '\\'; break;
|
||||
}
|
||||
if (escape >= 0) {
|
||||
// an \escaped sort of character
|
||||
sb.append('\\');
|
||||
sb.append((char)escape);
|
||||
} else {
|
||||
int hexSize;
|
||||
if (c < 256) {
|
||||
// 2-digit hex
|
||||
sb.append("\\x");
|
||||
hexSize = 2;
|
||||
} else {
|
||||
// Unicode.
|
||||
sb.append("\\u");
|
||||
hexSize = 4;
|
||||
}
|
||||
// append hexadecimal form of c left-padded with 0
|
||||
for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
|
||||
int digit = 0xf & (c >> shift);
|
||||
int hc = (digit < 10) ? '0' + digit : 'a' - 10 + digit;
|
||||
sb.append((char)hc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (sb == null) ? s : sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -655,10 +655,6 @@ public class TokenStream {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clearPushback() {
|
||||
this.pushbackToken = EOF;
|
||||
}
|
||||
|
||||
public void ungetToken(int tt) {
|
||||
if (this.pushbackToken != EOF && tt != ERROR) {
|
||||
String message = Context.getMessage2("msg.token.replaces.pushback",
|
||||
@@ -688,37 +684,6 @@ public class TokenStream {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isJSKeyword(String s) {
|
||||
return getKeywordId(s) != 0;
|
||||
}
|
||||
|
||||
public static boolean isJSIdentifier(String s) {
|
||||
int length = s.length();
|
||||
|
||||
if (length == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))
|
||||
return false;
|
||||
|
||||
for (int i=1; i<length; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (!Character.isJavaIdentifierPart(c)) {
|
||||
if (c == '\\') {
|
||||
if (! ((i + 5) < length)
|
||||
&& (s.charAt(i + 1) == 'u')
|
||||
&& 0 <= xDigitToInt(s.charAt(i + 2))
|
||||
&& 0 <= xDigitToInt(s.charAt(i + 3))
|
||||
&& 0 <= xDigitToInt(s.charAt(i + 4))
|
||||
&& 0 <= xDigitToInt(s.charAt(i + 5))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isAlpha(int c) {
|
||||
return ((c >= 'a' && c <= 'z')
|
||||
|| (c >= 'A' && c <= 'Z'));
|
||||
@@ -746,11 +711,6 @@ public class TokenStream {
|
||||
|| Character.getType((char)c) == Character.SPACE_SEPARATOR);
|
||||
}
|
||||
|
||||
public static boolean isJSLineTerminator(int c) {
|
||||
return (c == '\n' || c == '\r'
|
||||
|| c == 0x2028 || c == 0x2029);
|
||||
}
|
||||
|
||||
private void skipLine() throws IOException {
|
||||
// skip to end of line
|
||||
int c;
|
||||
|
||||
@@ -454,201 +454,4 @@ class UintMap implements Serializable {
|
||||
|
||||
// If true, enables consitency checks
|
||||
private static final boolean check = false;
|
||||
|
||||
/* TEST START
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (!check) {
|
||||
System.err.println("Set check to true and re-run");
|
||||
throw new RuntimeException("Set check to true and re-run");
|
||||
}
|
||||
|
||||
UintMap map;
|
||||
map = new UintMap();
|
||||
testHash(map, 2);
|
||||
map = new UintMap();
|
||||
testHash(map, 10 * 1000);
|
||||
map = new UintMap(30 * 1000);
|
||||
testHash(map, 10 * 100);
|
||||
map.clear();
|
||||
testHash(map, 4);
|
||||
map = new UintMap(0);
|
||||
testHash(map, 10 * 100);
|
||||
}
|
||||
|
||||
private static void testHash(UintMap map, int N) {
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i, i);
|
||||
check(i == map.getInt(i, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i, i);
|
||||
check(i == map.getInt(i, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i, new Integer(i));
|
||||
check(-1 == map.getInt(i, -1));
|
||||
Integer obj = (Integer)map.getObject(i);
|
||||
check(obj != null && i == obj.intValue());
|
||||
}
|
||||
|
||||
check(map.size() == N);
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
int[] keys = map.getKeys();
|
||||
check(keys.length == N);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
int key = keys[i];
|
||||
check(map.has(key));
|
||||
check(!map.isIntType(key));
|
||||
check(map.isObjectType(key));
|
||||
Integer obj = (Integer) map.getObject(key);
|
||||
check(obj != null && key == obj.intValue());
|
||||
}
|
||||
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
check(-1 == map.getInt(i, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i * i, i);
|
||||
check(i == map.getInt(i * i, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
check(i == map.getInt(i * i, -1));
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i * i, new Integer(i));
|
||||
check(-1 == map.getInt(i * i, -1));
|
||||
map.remove(i * i);
|
||||
check(!map.has(i * i));
|
||||
map.put(i * i, i);
|
||||
check(map.isIntType(i * i));
|
||||
check(null == map.getObject(i * i));
|
||||
map.remove(i * i);
|
||||
check(!map.isObjectType(i * i));
|
||||
check(!map.isIntType(i * i));
|
||||
}
|
||||
|
||||
int old_size = map.size();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.remove(i * i);
|
||||
check(map.size() == old_size);
|
||||
}
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
map.clear();
|
||||
check(map.size() == 0);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(i * i, i);
|
||||
map.put(i * i + 1, new Double(i+0.5));
|
||||
}
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
map = new UintMap(0);
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
map = new UintMap(1);
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
map = new UintMap(1000);
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
map = new UintMap(N / 10);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(2*i+1, i);
|
||||
}
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
map = new UintMap(N / 10);
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(2*i+1, i);
|
||||
}
|
||||
for (int i = 0; i != N / 2; ++i) {
|
||||
map.remove(2*i+1);
|
||||
}
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
|
||||
System.out.print("."); System.out.flush();
|
||||
map = new UintMap();
|
||||
for (int i = 0; i != N; ++i) {
|
||||
map.put(2*i+1, new Double(i + 10));
|
||||
}
|
||||
for (int i = 0; i != N / 2; ++i) {
|
||||
map.remove(2*i+1);
|
||||
}
|
||||
checkSameMaps(map, (UintMap)writeAndRead(map));
|
||||
|
||||
System.out.println(); System.out.flush();
|
||||
|
||||
}
|
||||
|
||||
private static void checkSameMaps(UintMap map1, UintMap map2) {
|
||||
check(map1.size() == map2.size());
|
||||
int[] keys = map1.getKeys();
|
||||
check(keys.length == map1.size());
|
||||
for (int i = 0; i != keys.length; ++i) {
|
||||
int key = keys[i];
|
||||
check(map2.has(key));
|
||||
check(map1.isObjectType(key) == map2.isObjectType(key));
|
||||
check(map1.isIntType(key) == map2.isIntType(key));
|
||||
Object o1 = map1.getObject(key);
|
||||
Object o2 = map2.getObject(key);
|
||||
if (map1.isObjectType(key)) {
|
||||
check(o1.equals(o2));
|
||||
}else {
|
||||
check(map1.getObject(key) == null);
|
||||
check(map2.getObject(key) == null);
|
||||
}
|
||||
if (map1.isIntType(key)) {
|
||||
check(map1.getExistingInt(key) == map2.getExistingInt(key));
|
||||
}else {
|
||||
check(map1.getInt(key, -10) == -10);
|
||||
check(map1.getInt(key, -11) == -11);
|
||||
check(map2.getInt(key, -10) == -10);
|
||||
check(map2.getInt(key, -11) == -11);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void check(boolean condition) {
|
||||
if (!condition) Context.codeBug();
|
||||
}
|
||||
|
||||
private static Object writeAndRead(Object obj) {
|
||||
try {
|
||||
java.io.ByteArrayOutputStream
|
||||
bos = new java.io.ByteArrayOutputStream();
|
||||
java.io.ObjectOutputStream
|
||||
out = new java.io.ObjectOutputStream(bos);
|
||||
out.writeObject(obj);
|
||||
out.close();
|
||||
byte[] data = bos.toByteArray();
|
||||
java.io.ByteArrayInputStream
|
||||
bis = new java.io.ByteArrayInputStream(data);
|
||||
java.io.ObjectInputStream
|
||||
in = new java.io.ObjectInputStream(bis);
|
||||
Object result = in.readObject();
|
||||
in.close();
|
||||
return result;
|
||||
}catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException("Unexpected");
|
||||
}
|
||||
}
|
||||
|
||||
// TEST END */
|
||||
}
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape 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/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
|
||||
* 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 Netscape are
|
||||
* Copyright (C) 1997-2000 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Igor Bukanov
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (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 NPL, indicate your decision by
|
||||
* deleting the provisions above and replace 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 NPL or the GPL.
|
||||
*/
|
||||
// Modified by Google
|
||||
|
||||
package com.google.gwt.dev.js.rhino;
|
||||
|
||||
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 {
|
||||
|
||||
public ObjArray() { }
|
||||
|
||||
public ObjArray(int capacityHint) {
|
||||
if (capacityHint < 0) throw new IllegalArgumentException();
|
||||
if (capacityHint > FIELDS_STORE_SIZE) {
|
||||
data = new Object[capacityHint - FIELDS_STORE_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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 invalidIndex(index, size);
|
||||
return getImpl(index);
|
||||
}
|
||||
|
||||
public final void set(int index, Object value) {
|
||||
if (!(0 <= index && index < size)) throw invalidIndex(index, size);
|
||||
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;
|
||||
case 5: return f5;
|
||||
}
|
||||
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;
|
||||
case 5: f5 = 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 invalidEmptyStackAccess();
|
||||
return getImpl(N - 1);
|
||||
}
|
||||
|
||||
public final Object pop() {
|
||||
int N = size;
|
||||
--N;
|
||||
Object top;
|
||||
switch (N) {
|
||||
case -1: throw invalidEmptyStackAccess();
|
||||
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;
|
||||
case 5: top = f5; f5 = 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) {
|
||||
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) {
|
||||
Object tmp;
|
||||
int N = size;
|
||||
if (!(0 <= index && index <= N)) throw invalidIndex(index, N + 1);
|
||||
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;
|
||||
case 5:
|
||||
if (N == 5) { f5 = value; break; }
|
||||
tmp = f5; f5 = 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 invalidIndex(index, N);
|
||||
--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 = f5;
|
||||
case 5:
|
||||
if (N == 5) { f5 = null; break; }
|
||||
f5 = 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() {
|
||||
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 6: array[offset + 5] = f5;
|
||||
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 invalidIndex(int index, int upperBound) {
|
||||
// \u2209 is "NOT ELEMENT OF"
|
||||
String msg = index+" \u2209 [0, "+upperBound+')';
|
||||
return new IndexOutOfBoundsException(msg);
|
||||
}
|
||||
|
||||
private static RuntimeException invalidEmptyStackAccess() {
|
||||
throw new RuntimeException("Empty stack");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static final long serialVersionUID = 7448768847663119705L;
|
||||
|
||||
// Number of data elements
|
||||
private int size;
|
||||
|
||||
private static final int FIELDS_STORE_SIZE = 6;
|
||||
private transient Object f0, f1, f2, f3, f4, f5;
|
||||
private transient Object[] data;
|
||||
}
|
||||
Reference in New Issue
Block a user