Changeset 12275


Ignore:
Timestamp:
11/10/09 19:45:37 (12 years ago)
Author:
ehuelsmann
Message:

Switch special bindings access schema to mirror that of SBCL/CCL/XCL:

use an array of current bindings with a linked list to store the
bindings to be restored upon unwinding.

Note: This change means a ~40% performance increase in Maxima;

given your application, YMMV, but since this schema trades
efficiency of establishing and unwinding over access, you
theoretically could see slow downs.

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/LispThread.java

    r12272 r12275  
    3636import java.util.Iterator;
    3737import java.util.concurrent.ConcurrentHashMap;
     38import java.util.concurrent.atomic.AtomicInteger;
    3839
    3940public final class LispThread extends LispObject
     
    6768    private boolean destroyed;
    6869    private final LispObject name;
    69     public SpecialBinding lastSpecialBinding;
    7070    public LispObject[] _values;
    7171    private boolean threadInterrupted;
     
    307307    }
    308308
     309
     310
     311    final static int UNASSIGNED_SPECIAL_INDEX = 0;
     312
     313    /** Indicates the last special slot which has been assigned.
     314     * Symbols which don't have a special slot assigned use a slot
     315     * index of 0 for efficiency reasons: it eliminates the need to
     316     * check for index validity before accessing the specials array.
     317     *
     318     */
     319    final static AtomicInteger lastSpecial
     320        = new AtomicInteger(UNASSIGNED_SPECIAL_INDEX);
     321
     322    /** This array stores the current special binding for every symbol
     323     * which has been globally or locally declared special.
     324     *
     325     * If the array element has a null value, this means there currently
     326     * is no active binding. If the array element contains a valid
     327     * SpecialBinding object, but the value field of it is null, that
     328     * indicates an "UNBOUND VARIABLE" situation.
     329     */
     330    final SpecialBinding[] specials = new SpecialBinding[4097];
     331
     332    /** This array stores the symbols associated with the special
     333     * bindings slots.
     334     */
     335    final static Symbol[] specialNames = new Symbol[4097];
     336
     337    /** This variable points to the head of a linked list of saved
     338     * special bindings. Its main purpose is to allow a mark/reset
     339     * interface to special binding and unbinding.
     340     */
     341    private SpecialBindingsMark savedSpecials = null;
     342
    309343    /** Marks the state of the special bindings,
    310344     * for later rewinding by resetSpecialBindings().
    311345     */
    312346    public final SpecialBindingsMark markSpecialBindings() {
    313         return new SpecialBindingsMark(lastSpecialBinding);
     347        return savedSpecials;
    314348    }
    315349
     
    318352     */
    319353    public final void resetSpecialBindings(SpecialBindingsMark mark) {
    320         lastSpecialBinding = mark.binding;
     354        SpecialBindingsMark c = savedSpecials;
     355        while (mark != c) {
     356            specials[c.idx] = c.binding;
     357            c = c.next;
     358        }
     359        savedSpecials = c;
    321360    }
    322361
     
    327366    // Package level access: only for Interpreter.run()
    328367    final void clearSpecialBindings() {
    329         lastSpecialBinding = null;
     368        resetSpecialBindings(null);
     369    }
     370
     371    /** Assigns a specials array index number to the symbol,
     372     * if it doesn't already have one.
     373     */
     374    private static final void assignSpecialIndex(Symbol sym)
     375    {
     376        if (sym.specialIndex != 0)
     377            return;
     378
     379        synchronized (sym) {
     380            // Don't use an atomic access: we'll be swapping values only once.
     381            if (sym.specialIndex == 0) {
     382                sym.specialIndex = lastSpecial.incrementAndGet();
     383                specialNames[sym.specialIndex] = sym;
     384            }
     385        }
    330386    }
    331387
    332388    public final SpecialBinding bindSpecial(Symbol name, LispObject value)
    333389    {
    334         return lastSpecialBinding
    335             = new SpecialBinding(name, value, lastSpecialBinding);
     390        int idx;
     391
     392        assignSpecialIndex(name);
     393        SpecialBinding binding = specials[idx = name.specialIndex];
     394        savedSpecials = new SpecialBindingsMark(idx, binding, savedSpecials);
     395        return specials[idx] = new SpecialBinding(idx, value);
    336396    }
    337397
    338398    public final SpecialBinding bindSpecialToCurrentValue(Symbol name)
    339399    {
    340         SpecialBinding binding = lastSpecialBinding;
    341         while (binding != null) {
    342             if (binding.name == name) {
    343                 return lastSpecialBinding =
    344                     new SpecialBinding(name, binding.value, lastSpecialBinding);
    345             }
    346             binding = binding.next;
    347         }
    348         // Not found.
    349         return lastSpecialBinding =
    350             new SpecialBinding(name, name.getSymbolValue(), lastSpecialBinding);
     400        int idx;
     401
     402        assignSpecialIndex(name);
     403        SpecialBinding binding = specials[idx = name.specialIndex];
     404        savedSpecials = new SpecialBindingsMark(idx, binding, savedSpecials);
     405        return specials[idx]
     406            = new SpecialBinding(idx,
     407                                 (binding == null) ? null : binding.value);
    351408    }
    352409
     
    362419     * @see Symbol#symbolValue
    363420     */
    364     public final LispObject lookupSpecial(LispObject name)
    365     {
    366         SpecialBinding binding = lastSpecialBinding;
    367         while (binding != null) {
    368             if (binding.name == name)
    369                 return binding.value;
    370             binding = binding.next;
    371         }
    372         return null;
    373     }
    374 
    375     public final SpecialBinding getSpecialBinding(LispObject name)
    376     {
    377         SpecialBinding binding = lastSpecialBinding;
    378         while (binding != null) {
    379             if (binding.name == name)
    380                 return binding;
    381             binding = binding.next;
    382         }
    383         return null;
     421    public final LispObject lookupSpecial(Symbol name)
     422    {
     423        SpecialBinding binding = specials[name.specialIndex];
     424        return (binding == null) ? null : binding.value;
     425    }
     426
     427    public final SpecialBinding getSpecialBinding(Symbol name)
     428    {
     429        return specials[name.specialIndex];
    384430    }
    385431
    386432    public final LispObject setSpecialVariable(Symbol name, LispObject value)
    387433    {
    388         SpecialBinding binding = lastSpecialBinding;
    389         while (binding != null) {
    390             if (binding.name == name) {
    391                 binding.value = value;
    392                 return value;
    393             }
    394             binding = binding.next;
    395         }
     434        SpecialBinding binding = specials[name.specialIndex];
     435        if (binding != null)
     436            return binding.value = value;
     437
    396438        name.setSymbolValue(value);
    397439        return value;
     
    401443
    402444    {
    403         SpecialBinding binding = lastSpecialBinding;
    404         while (binding != null) {
    405             if (binding.name == name) {
    406                 LispObject newValue = new Cons(thing, binding.value);
    407                 binding.value = newValue;
    408                 return newValue;
    409             }
    410             binding = binding.next;
    411         }
     445        SpecialBinding binding = specials[name.specialIndex];
     446        if (binding != null)
     447            return binding.value = new Cons(thing, binding.value);
     448
    412449        LispObject value = name.getSymbolValue();
    413450        if (value != null) {
     
    422459    public final LispObject safeSymbolValue(Symbol name)
    423460    {
    424         SpecialBinding binding = lastSpecialBinding;
    425         while (binding != null) {
    426             if (binding.name == name)
    427                 return binding.value;
    428             binding = binding.next;
    429         }
     461        SpecialBinding binding = specials[name.specialIndex];
     462        if (binding != null)
     463            return binding.value;
     464
    430465        LispObject value = name.getSymbolValue();
    431466        return value != null ? value : NIL;
     
    480515    }
    481516
    482     public final void pushStackFrame(StackFrame frame) 
     517    public final void pushStackFrame(StackFrame frame)
    483518    {
    484519  frame.setNext(stack);
  • trunk/abcl/src/org/armedbear/lisp/Load.java

    r12272 r12275  
    428428    // internal symbol
    429429    private static final Symbol _FASL_VERSION_ =
    430         exportConstant("*FASL-VERSION*", PACKAGE_SYS, Fixnum.getInstance(33));
     430        exportConstant("*FASL-VERSION*", PACKAGE_SYS, Fixnum.getInstance(34));
    431431
    432432    // ### *fasl-anonymous-package*
  • trunk/abcl/src/org/armedbear/lisp/SpecialBinding.java

    r12254 r12275  
    3434package org.armedbear.lisp;
    3535
    36 // Package accessibility.
    3736final public class SpecialBinding
    3837{
    39     final LispObject name;
     38    /** The index in the specials array of the symbol
     39     *  to which this value belongs.
     40     */
     41    final int idx;
     42
     43    /** The value bound */
    4044    public LispObject value;
    41     final SpecialBinding next;
    4245
    43     SpecialBinding(LispObject name, LispObject value, SpecialBinding next)
     46    SpecialBinding(int idx, LispObject value)
    4447    {
    45         this.name = name;
     48        this.idx = idx;
    4649        this.value = value;
    47         this.next = next;
    4850    }
    4951
     
    5759    {
    5860        if (value == null)
    59             return Lisp.error(new UnboundVariable(name));
     61            // return or not: error doesn't return anyway
     62            Lisp.error(new UnboundVariable(LispThread.specialNames[idx]));
    6063
    6164        return value;
    6265    }
     66
     67    /** Sets the value of the binding.
     68     *
     69     * Note: this method can only be called when the
     70     *    binding is the one which is currently visible.
     71     */
     72    final public void setValue(LispObject value)
     73    {
     74        this.value = value;
     75    }
    6376}
  • trunk/abcl/src/org/armedbear/lisp/SpecialBindingsMark.java

    r12273 r12275  
    4040final public class SpecialBindingsMark {
    4141
     42    /** The index in the specials array of the saved binding. */
     43    int idx;
     44
    4245    /** Special binding state to be restored */
    4346    // package level access
    4447    SpecialBinding binding;
     48    SpecialBindingsMark next;
    4549
    4650    /** Constructor to be called by LispThread.markSpecialBindings() only */
    4751    // package level access
    48     SpecialBindingsMark(SpecialBinding binding) {
     52    SpecialBindingsMark(int idx, SpecialBinding binding,
     53                        SpecialBindingsMark next) {
     54        this.idx = idx;
    4955        this.binding = binding;
     56        this.next = next;
    5057    }
    5158}
  • trunk/abcl/src/org/armedbear/lisp/Symbol.java

    r12272 r12275  
    5050  public final SimpleString name;
    5151  private int hash = -1;
     52
     53  /** To be accessed by LispThread only:
     54   * used to find the index in the LispThread.specials array
     55   */
     56  int specialIndex = LispThread.UNASSIGNED_SPECIAL_INDEX;
    5257  private LispObject pkg; // Either a package object or NIL.
    5358  private LispObject value;
Note: See TracChangeset for help on using the changeset viewer.