[armedbear-cvs] r12192 - trunk/abcl/src/org/armedbear/lisp
Ville Voutilainen
vvoutilainen at common-lisp.net
Tue Oct 13 19:32:49 UTC 2009
Author: vvoutilainen
Date: Tue Oct 13 15:32:46 2009
New Revision: 12192
Log:
Patch by Douglas R. Miles to improve performance after CHAR_MAX
was increased from 255 to 64k.
Added:
trunk/abcl/src/org/armedbear/lisp/CharHashMap.java
Modified:
trunk/abcl/src/org/armedbear/lisp/FaslReadtable.java
trunk/abcl/src/org/armedbear/lisp/LispCharacter.java
trunk/abcl/src/org/armedbear/lisp/Readtable.java
Added: trunk/abcl/src/org/armedbear/lisp/CharHashMap.java
==============================================================================
--- (empty file)
+++ trunk/abcl/src/org/armedbear/lisp/CharHashMap.java Tue Oct 13 15:32:46 2009
@@ -0,0 +1,72 @@
+package org.armedbear.lisp;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class CharHashMap<T> {
+
+ final public T[] constants;
+ final public T NULL;
+ final static int CACHE_SIZE = 256;
+ final HashMap<Character, T> backing;
+ public CharHashMap(Class componentType, T def) {
+ NULL = def;
+ constants = (T[]) Array.newInstance(componentType, CACHE_SIZE);
+ Arrays.fill(constants, NULL);
+ backing = new HashMap<Character, T>();
+ }
+
+ @Override
+ public Object clone() {
+ CharHashMap<T> n = new CharHashMap<T>(constants.getClass().getComponentType(),NULL);
+ System.arraycopy(constants,0, n.constants,0,CACHE_SIZE);
+ n.backing.putAll(backing);
+ return n;
+ }
+
+ public T get(char key) {
+ if (key<CACHE_SIZE) return constants[key];
+ T value = backing.get(key);
+ return (value==null) ? NULL:value;
+ }
+
+ public void clear() {
+ Arrays.fill(constants,NULL);
+ backing.clear();
+ }
+
+ public T put(char key, T value) {
+ if (key<CACHE_SIZE) {
+ T old = constants[key];
+ constants[key] = value;
+ return old;
+ }
+ else return backing.put(key, value);
+ }
+
+ public Iterator<Character> getCharIterator() {
+ return new Iterator<Character>() {
+ final Iterator<Character> carIt = backing.keySet().iterator();
+ int charNum = -1;
+ public boolean hasNext() {
+ if ( charNum<CACHE_SIZE) return true;
+ return carIt.hasNext();
+ }
+ public Character next() {
+ if ( charNum<CACHE_SIZE) return (char)++charNum;
+ return carIt.next();
+ }
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+ }
+}
Modified: trunk/abcl/src/org/armedbear/lisp/FaslReadtable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/FaslReadtable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/FaslReadtable.java Tue Oct 13 15:32:46 2009
@@ -43,6 +43,7 @@
@Override
protected void initialize()
{
+ Byte[] syntax = this.syntax.constants;
syntax[9] = SYNTAX_TYPE_WHITESPACE; // tab
syntax[10] = SYNTAX_TYPE_WHITESPACE; // linefeed
syntax[12] = SYNTAX_TYPE_WHITESPACE; // form feed
@@ -62,6 +63,7 @@
syntax['\\'] = SYNTAX_TYPE_SINGLE_ESCAPE;
syntax['|'] = SYNTAX_TYPE_MULTIPLE_ESCAPE;
+ LispObject[] readerMacroFunctions = this.readerMacroFunctions.constants;
readerMacroFunctions[';'] = FaslReader.FASL_READ_COMMENT;
readerMacroFunctions['"'] = FaslReader.FASL_READ_STRING;
readerMacroFunctions['('] = FaslReader.FASL_READ_LIST;
@@ -74,30 +76,31 @@
readerMacroFunctions[','] = Symbol.COMMA_MACRO;
DispatchTable dt = new DispatchTable();
- dt.functions['('] = FaslReader.FASL_SHARP_LEFT_PAREN;
- dt.functions['*'] = FaslReader.FASL_SHARP_STAR;
- dt.functions['.'] = FaslReader.FASL_SHARP_DOT;
- dt.functions[':'] = FaslReader.FASL_SHARP_COLON;
- dt.functions['A'] = FaslReader.FASL_SHARP_A;
- dt.functions['B'] = FaslReader.FASL_SHARP_B;
- dt.functions['C'] = FaslReader.FASL_SHARP_C;
- dt.functions['O'] = FaslReader.FASL_SHARP_O;
- dt.functions['P'] = FaslReader.FASL_SHARP_P;
- dt.functions['R'] = FaslReader.FASL_SHARP_R;
- dt.functions['S'] = FaslReader.FASL_SHARP_S;
- dt.functions['X'] = FaslReader.FASL_SHARP_X;
- dt.functions['\''] = FaslReader.FASL_SHARP_QUOTE;
- dt.functions['\\'] = FaslReader.FASL_SHARP_BACKSLASH;
- dt.functions['|'] = FaslReader.FASL_SHARP_VERTICAL_BAR;
- dt.functions[')'] = FaslReader.FASL_SHARP_ILLEGAL;
- dt.functions['<'] = FaslReader.FASL_SHARP_ILLEGAL;
- dt.functions[' '] = FaslReader.FASL_SHARP_ILLEGAL;
- dt.functions[8] = FaslReader.FASL_SHARP_ILLEGAL; // backspace
- dt.functions[9] = FaslReader.FASL_SHARP_ILLEGAL; // tab
- dt.functions[10] = FaslReader.FASL_SHARP_ILLEGAL; // newline, linefeed
- dt.functions[12] = FaslReader.FASL_SHARP_ILLEGAL; // page
- dt.functions[13] = FaslReader.FASL_SHARP_ILLEGAL; // return
- dispatchTables['#'] = dt;
+ LispObject[] dtfunctions = dt.functions.constants;
+ dtfunctions['('] = FaslReader.FASL_SHARP_LEFT_PAREN;
+ dtfunctions['*'] = FaslReader.FASL_SHARP_STAR;
+ dtfunctions['.'] = FaslReader.FASL_SHARP_DOT;
+ dtfunctions[':'] = FaslReader.FASL_SHARP_COLON;
+ dtfunctions['A'] = FaslReader.FASL_SHARP_A;
+ dtfunctions['B'] = FaslReader.FASL_SHARP_B;
+ dtfunctions['C'] = FaslReader.FASL_SHARP_C;
+ dtfunctions['O'] = FaslReader.FASL_SHARP_O;
+ dtfunctions['P'] = FaslReader.FASL_SHARP_P;
+ dtfunctions['R'] = FaslReader.FASL_SHARP_R;
+ dtfunctions['S'] = FaslReader.FASL_SHARP_S;
+ dtfunctions['X'] = FaslReader.FASL_SHARP_X;
+ dtfunctions['\''] = FaslReader.FASL_SHARP_QUOTE;
+ dtfunctions['\\'] = FaslReader.FASL_SHARP_BACKSLASH;
+ dtfunctions['|'] = FaslReader.FASL_SHARP_VERTICAL_BAR;
+ dtfunctions[')'] = FaslReader.FASL_SHARP_ILLEGAL;
+ dtfunctions['<'] = FaslReader.FASL_SHARP_ILLEGAL;
+ dtfunctions[' '] = FaslReader.FASL_SHARP_ILLEGAL;
+ dtfunctions[8] = FaslReader.FASL_SHARP_ILLEGAL; // backspace
+ dtfunctions[9] = FaslReader.FASL_SHARP_ILLEGAL; // tab
+ dtfunctions[10] = FaslReader.FASL_SHARP_ILLEGAL; // newline, linefeed
+ dtfunctions[12] = FaslReader.FASL_SHARP_ILLEGAL; // page
+ dtfunctions[13] = FaslReader.FASL_SHARP_ILLEGAL; // return
+ dispatchTables.constants['#'] = dt;
readtableCase = Keyword.UPCASE;
}
Modified: trunk/abcl/src/org/armedbear/lisp/LispCharacter.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/LispCharacter.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/LispCharacter.java Tue Oct 13 15:32:46 2009
@@ -37,10 +37,22 @@
public final class LispCharacter extends LispObject
{
- public static final LispCharacter[] constants = new LispCharacter[CHAR_MAX];
+ public static final LispCharacter[] constants;
+ public static final CharHashMap<LispCharacter> lispChars;
static
{
+ lispChars = new CharHashMap<LispCharacter>(LispCharacter.class,null){
+ public LispCharacter get(char c) {
+ LispCharacter lc = super.get(c);
+ if (lc==null) {
+ lc = new LispCharacter(c);
+ put(c, lc);
+ }
+ return lc;
+ }
+ };
+ constants = lispChars.constants;
for (int i = constants.length; i-- > 0;)
constants[i] = new LispCharacter((char)i);
}
@@ -51,7 +63,7 @@
{
try
{
- return constants[c];
+ return lispChars.get(c);
}
catch (ArrayIndexOutOfBoundsException e)
{
@@ -341,7 +353,7 @@
{
int n = Fixnum.getValue(arg);
if (n < CHAR_MAX)
- return constants[n];
+ return lispChars.get((char)n);
else if (n <= Character.MAX_VALUE)
return new LispCharacter((char)n);
// SBCL signals a type-error here: "not of type (UNSIGNED-BYTE 8)"
@@ -613,7 +625,7 @@
return "Rubout";
}
if (c<0 || c>255) return null;
- return constants[c].name;
+ return lispChars.get(c).name;
}
// ### char-name
@@ -651,8 +663,7 @@
}
static void setCharName(int settingChar, String string) {
- if (settingChar>=CHAR_MAX) return;
- LispCharacter c = constants[settingChar];
+ LispCharacter c = lispChars.get((char)settingChar);
c.name = string;
namedToChar.put(string.toLowerCase(), c);
}
Modified: trunk/abcl/src/org/armedbear/lisp/Readtable.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/Readtable.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/Readtable.java Tue Oct 13 15:32:46 2009
@@ -32,6 +32,7 @@
*/
package org.armedbear.lisp;
+import java.util.Iterator;
public class Readtable extends LispObject
{
@@ -42,9 +43,9 @@
public static final byte SYNTAX_TYPE_SINGLE_ESCAPE = 4;
public static final byte SYNTAX_TYPE_MULTIPLE_ESCAPE = 5;
- protected final byte[] syntax = new byte[CHAR_MAX];
- protected final LispObject[] readerMacroFunctions = new LispObject[CHAR_MAX];
- protected final DispatchTable[] dispatchTables = new DispatchTable[CHAR_MAX];
+ protected final CharHashMap<Byte> syntax = new CharHashMap<Byte>(Byte.class,SYNTAX_TYPE_CONSTITUENT);
+ protected final CharHashMap<LispObject> readerMacroFunctions = new CharHashMap<LispObject>(LispObject.class,null);
+ protected final CharHashMap<DispatchTable> dispatchTables = new CharHashMap<DispatchTable>(DispatchTable.class,null);
protected LispObject readtableCase;
@@ -55,6 +56,7 @@
protected void initialize()
{
+ Byte[] syntax = this.syntax.constants;
syntax[9] = SYNTAX_TYPE_WHITESPACE; // tab
syntax[10] = SYNTAX_TYPE_WHITESPACE; // linefeed
syntax[12] = SYNTAX_TYPE_WHITESPACE; // form feed
@@ -74,6 +76,7 @@
syntax['\\'] = SYNTAX_TYPE_SINGLE_ESCAPE;
syntax['|'] = SYNTAX_TYPE_MULTIPLE_ESCAPE;
+ LispObject[] readerMacroFunctions = this.readerMacroFunctions.constants;
readerMacroFunctions[';'] = LispReader.READ_COMMENT;
readerMacroFunctions['"'] = LispReader.READ_STRING;
readerMacroFunctions['('] = LispReader.READ_LIST;
@@ -86,32 +89,32 @@
readerMacroFunctions[','] = Symbol.COMMA_MACRO;
DispatchTable dt = new DispatchTable();
+ LispObject[] dtfunctions = dt.functions.constants;
+ dtfunctions['('] = LispReader.SHARP_LEFT_PAREN;
+ dtfunctions['*'] = LispReader.SHARP_STAR;
+ dtfunctions['.'] = LispReader.SHARP_DOT;
+ dtfunctions[':'] = LispReader.SHARP_COLON;
+ dtfunctions['A'] = LispReader.SHARP_A;
+ dtfunctions['B'] = LispReader.SHARP_B;
+ dtfunctions['C'] = LispReader.SHARP_C;
+ dtfunctions['O'] = LispReader.SHARP_O;
+ dtfunctions['P'] = LispReader.SHARP_P;
+ dtfunctions['R'] = LispReader.SHARP_R;
+ dtfunctions['S'] = LispReader.SHARP_S;
+ dtfunctions['X'] = LispReader.SHARP_X;
+ dtfunctions['\''] = LispReader.SHARP_QUOTE;
+ dtfunctions['\\'] = LispReader.SHARP_BACKSLASH;
+ dtfunctions['|'] = LispReader.SHARP_VERTICAL_BAR;
+ dtfunctions[')'] = LispReader.SHARP_ILLEGAL;
+ dtfunctions['<'] = LispReader.SHARP_ILLEGAL;
+ dtfunctions[' '] = LispReader.SHARP_ILLEGAL;
+ dtfunctions[8] = LispReader.SHARP_ILLEGAL; // backspace
+ dtfunctions[9] = LispReader.SHARP_ILLEGAL; // tab
+ dtfunctions[10] = LispReader.SHARP_ILLEGAL; // newline, linefeed
+ dtfunctions[12] = LispReader.SHARP_ILLEGAL; // page
+ dtfunctions[13] = LispReader.SHARP_ILLEGAL; // return
- dt.functions['('] = LispReader.SHARP_LEFT_PAREN;
- dt.functions['*'] = LispReader.SHARP_STAR;
- dt.functions['.'] = LispReader.SHARP_DOT;
- dt.functions[':'] = LispReader.SHARP_COLON;
- dt.functions['A'] = LispReader.SHARP_A;
- dt.functions['B'] = LispReader.SHARP_B;
- dt.functions['C'] = LispReader.SHARP_C;
- dt.functions['O'] = LispReader.SHARP_O;
- dt.functions['P'] = LispReader.SHARP_P;
- dt.functions['R'] = LispReader.SHARP_R;
- dt.functions['S'] = LispReader.SHARP_S;
- dt.functions['X'] = LispReader.SHARP_X;
- dt.functions['\''] = LispReader.SHARP_QUOTE;
- dt.functions['\\'] = LispReader.SHARP_BACKSLASH;
- dt.functions['|'] = LispReader.SHARP_VERTICAL_BAR;
- dt.functions[')'] = LispReader.SHARP_ILLEGAL;
- dt.functions['<'] = LispReader.SHARP_ILLEGAL;
- dt.functions[' '] = LispReader.SHARP_ILLEGAL;
- dt.functions[8] = LispReader.SHARP_ILLEGAL; // backspace
- dt.functions[9] = LispReader.SHARP_ILLEGAL; // tab
- dt.functions[10] = LispReader.SHARP_ILLEGAL; // newline, linefeed
- dt.functions[12] = LispReader.SHARP_ILLEGAL; // page
- dt.functions[13] = LispReader.SHARP_ILLEGAL; // return
-
- dispatchTables['#'] = dt;
+ dispatchTables.constants['#'] = dt;
readtableCase = Keyword.UPCASE;
}
@@ -125,35 +128,44 @@
rt = checkReadtable(obj);
synchronized (rt)
{
- System.arraycopy(rt.syntax, 0, syntax, 0, CHAR_MAX);
- System.arraycopy(rt.readerMacroFunctions, 0, readerMacroFunctions, 0,
- CHAR_MAX);
- // Deep copy.
- for (int i = dispatchTables.length; i-- > 0;)
- {
- DispatchTable dt = rt.dispatchTables[i];
- if (dt != null)
- dispatchTables[i] = new DispatchTable(dt);
- }
- readtableCase = rt.readtableCase;
+ copyReadtable(rt, this);
}
}
// FIXME synchronization
private static void copyReadtable(Readtable from, Readtable to)
{
- System.arraycopy(from.syntax, 0, to.syntax, 0, CHAR_MAX);
- System.arraycopy(from.readerMacroFunctions, 0, to.readerMacroFunctions, 0,
- CHAR_MAX);
- for (int i = from.dispatchTables.length; i-- > 0;)
- {
- DispatchTable dt = from.dispatchTables[i];
- if (dt != null)
- to.dispatchTables[i] = new DispatchTable(dt);
- else
- to.dispatchTables[i] = null;
+ Iterator<Character> charIterator = from.syntax.getCharIterator();
+ while (charIterator.hasNext()) {
+ char c = charIterator.next();
+ Byte dt = from.syntax.get(c);
+ if (dt!=null) {
+ to.syntax.put(c, dt);
+ } else {
+ to.syntax.put(c, null);
+ }
+ }
+ charIterator = from.readerMacroFunctions.getCharIterator();
+ while (charIterator.hasNext()) {
+ char c = charIterator.next();
+ LispObject dt = from.readerMacroFunctions.get(c);
+ if (dt!=null) {
+ to.readerMacroFunctions.put(c, dt);
+ } else {
+ to.readerMacroFunctions.put(c, null);
+ }
+ }
+ charIterator = from.dispatchTables.getCharIterator();
+ while (charIterator.hasNext()) {
+ char c = charIterator.next();
+ DispatchTable dt = from.dispatchTables.get(c);
+ if (dt!=null) {
+ to.dispatchTables.put(c, new DispatchTable(dt));
+ } else {
+ to.dispatchTables.put(c, null);
+ }
}
- to.readtableCase = from.readtableCase;
+ to.readtableCase = from.readtableCase;
}
@Override
@@ -191,16 +203,12 @@
public boolean isWhitespace(char c)
{
- if (c < CHAR_MAX)
- return syntax[c] == SYNTAX_TYPE_WHITESPACE;
- return false;
+ return getSyntaxType(c) == SYNTAX_TYPE_WHITESPACE;
}
public byte getSyntaxType(char c)
{
- if (c < CHAR_MAX)
- return syntax[c];
- return SYNTAX_TYPE_CONSTITUENT;
+ return syntax.get(c);
}
public boolean isInvalid(char c)
@@ -239,10 +247,7 @@
public LispObject getReaderMacroFunction(char c)
{
- if (c < CHAR_MAX)
- return readerMacroFunctions[c];
- else
- return null;
+ return readerMacroFunctions.get(c);
}
private LispObject getMacroCharacter(char c) throws ConditionThrowable
@@ -251,7 +256,7 @@
LispObject non_terminating_p;
if (function != null)
{
- if (syntax[c] == SYNTAX_TYPE_NON_TERMINATING_MACRO)
+ if (syntax.get(c) == SYNTAX_TYPE_NON_TERMINATING_MACRO)
non_terminating_p = T;
else
non_terminating_p = NIL;
@@ -272,15 +277,15 @@
else
syntaxType = SYNTAX_TYPE_TERMINATING_MACRO;
// FIXME synchronization
- syntax[dispChar] = syntaxType;
- readerMacroFunctions[dispChar] = LispReader.READ_DISPATCH_CHAR;
- dispatchTables[dispChar] = new DispatchTable();
+ syntax.put(dispChar,syntaxType);
+ readerMacroFunctions.put(dispChar, LispReader.READ_DISPATCH_CHAR);
+ dispatchTables.put(dispChar, new DispatchTable());
}
public LispObject getDispatchMacroCharacter(char dispChar, char subChar)
throws ConditionThrowable
{
- DispatchTable dispatchTable = dispatchTables[dispChar];
+ DispatchTable dispatchTable = dispatchTables.get(dispChar);
if (dispatchTable == null)
{
LispCharacter c = LispCharacter.getInstance(dispChar);
@@ -288,7 +293,7 @@
" is not a dispatch character."));
}
LispObject function =
- dispatchTable.functions[LispCharacter.toUpperCase(subChar)];
+ dispatchTable.functions.get(LispCharacter.toUpperCase(subChar));
return (function != null) ? function : NIL;
}
@@ -296,28 +301,28 @@
LispObject function)
throws ConditionThrowable
{
- DispatchTable dispatchTable = dispatchTables[dispChar];
+ DispatchTable dispatchTable = dispatchTables.get(dispChar);
if (dispatchTable == null)
{
LispCharacter c = LispCharacter.getInstance(dispChar);
error(new LispError(c.writeToString() +
" is not a dispatch character."));
}
- dispatchTable.functions[LispCharacter.toUpperCase(subChar)] = function;
+ dispatchTable.functions.put(LispCharacter.toUpperCase(subChar), function);
}
protected static class DispatchTable
{
- public LispObject[] functions = new LispObject[CHAR_MAX];
+ protected final CharHashMap<LispObject> functions;
public DispatchTable()
{
+ functions = new CharHashMap<LispObject>(LispObject.class,null);
}
public DispatchTable(DispatchTable dt)
{
- for (int i = 0; i < functions.length; i++)
- functions[i] = dt.functions[i];
+ functions = (CharHashMap<LispObject>) dt.functions.clone();
}
}
@@ -427,8 +432,8 @@
syntaxType = SYNTAX_TYPE_TERMINATING_MACRO;
Readtable rt = designator_readtable(fourth);
// REVIEW synchronization
- rt.syntax[c] = syntaxType;
- rt.readerMacroFunctions[c] = designator;
+ rt.syntax.put(c, syntaxType);
+ rt.readerMacroFunctions.put(c, designator);
return T;
}
};
@@ -530,20 +535,18 @@
else
fromReadtable = checkReadtable(STANDARD_READTABLE.symbolValue());
// REVIEW synchronization
- toReadtable.syntax[toChar] = fromReadtable.syntax[fromChar];
- toReadtable.readerMacroFunctions[toChar] =
- fromReadtable.readerMacroFunctions[fromChar];
+ toReadtable.syntax.put(toChar, fromReadtable.syntax.get(fromChar));
+ toReadtable.readerMacroFunctions.put(toChar,
+ fromReadtable.readerMacroFunctions.get(fromChar));
// "If the character is a dispatching macro character, its entire
// dispatch table of reader macro functions is copied."
- if (fromReadtable.dispatchTables[fromChar] != null)
- {
- toReadtable.dispatchTables[toChar] =
- new DispatchTable(fromReadtable.dispatchTables[fromChar]);
- }
+ DispatchTable found = fromReadtable.dispatchTables.get(fromChar);
+ if (found!=null)
+ toReadtable.dispatchTables.put(toChar, new DispatchTable(found));
else
// Don't leave behind dispatch tables when fromChar
// doesn't have one
- toReadtable.dispatchTables[toChar] = null;
+ toReadtable.dispatchTables.put(toChar, null);
return T;
}
};
More information about the armedbear-cvs
mailing list