source: branches/0.16.x/abcl/src/org/armedbear/lisp/StandardGenericFunction.java

Last change on this file was 12079, checked in by ehuelsmann, 16 years ago

Add API to execute()-able classes for hot spot profiling
next to normal stack profiling.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.7 KB
Line 
1/*
2 * StandardGenericFunction.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: StandardGenericFunction.java 12079 2009-07-31 19:45:54Z ehuelsmann $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import java.util.HashMap;
37
38public final class StandardGenericFunction extends StandardObject
39{
40  private LispObject function;
41
42  private int numberOfRequiredArgs;
43
44  private HashMap<CacheEntry,LispObject> cache;
45  private HashMap<LispObject,LispObject> slotCache;
46
47  public StandardGenericFunction()
48  {
49    super(StandardClass.STANDARD_GENERIC_FUNCTION,
50          StandardClass.STANDARD_GENERIC_FUNCTION.getClassLayout().getLength());
51  }
52
53  public StandardGenericFunction(String name, Package pkg, boolean exported,
54                                 Function function, LispObject lambdaList,
55                                 LispObject specializers)
56  {
57    this();
58    try
59      {
60        Symbol symbol;
61        if (exported)
62          symbol = pkg.internAndExport(name.toUpperCase());
63        else
64          symbol = pkg.intern(name.toUpperCase());
65        symbol.setSymbolFunction(this);
66        this.function = function;
67        slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = symbol;
68        slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST] =
69          lambdaList;
70        slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS] =
71          lambdaList;
72        numberOfRequiredArgs = lambdaList.length();
73        slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS] =
74          NIL;
75        StandardMethod method =
76          new StandardMethod(this, function, lambdaList, specializers);
77        slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS] =
78          list(method);
79        slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS] =
80          StandardClass.STANDARD_METHOD;
81        slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION] =
82          Symbol.STANDARD;
83        slots[StandardGenericFunctionClass.SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER] =
84          NIL;
85        slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE] =
86          NIL;
87        slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION] = NIL;
88      }
89    catch (ConditionThrowable t)
90      {
91        Debug.assertTrue(false);
92      }
93  }
94
95  private void finalizeInternal()
96  {
97    cache = null;
98  }
99
100  @Override
101  public LispObject typep(LispObject type) throws ConditionThrowable
102  {
103    if (type == Symbol.COMPILED_FUNCTION)
104      {
105        if (function != null)
106          return function.typep(type);
107        else
108          return NIL;
109      }
110    if (type == Symbol.STANDARD_GENERIC_FUNCTION)
111      return T;
112    if (type == StandardClass.STANDARD_GENERIC_FUNCTION)
113      return T;
114    return super.typep(type);
115  }
116
117  public LispObject getGenericFunctionName()
118  {
119    return slots[StandardGenericFunctionClass.SLOT_INDEX_NAME];
120  }
121
122  public void setGenericFunctionName(LispObject name)
123  {
124    slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = name;
125  }
126
127  @Override
128  public LispObject execute() throws ConditionThrowable
129  {
130    return function.execute();
131  }
132
133  @Override
134  public LispObject execute(LispObject arg) throws ConditionThrowable
135  {
136    return function.execute(arg);
137  }
138
139  @Override
140  public LispObject execute(LispObject first, LispObject second)
141    throws ConditionThrowable
142  {
143    return function.execute(first, second);
144  }
145
146  @Override
147  public LispObject execute(LispObject first, LispObject second,
148                            LispObject third)
149    throws ConditionThrowable
150  {
151    return function.execute(first, second, third);
152  }
153
154  @Override
155  public LispObject execute(LispObject first, LispObject second,
156                            LispObject third, LispObject fourth)
157    throws ConditionThrowable
158  {
159    return function.execute(first, second, third, fourth);
160  }
161
162  @Override
163  public LispObject execute(LispObject first, LispObject second,
164                            LispObject third, LispObject fourth,
165                            LispObject fifth)
166    throws ConditionThrowable
167  {
168    return function.execute(first, second, third, fourth,
169                            fifth);
170  }
171
172  @Override
173  public LispObject execute(LispObject first, LispObject second,
174                            LispObject third, LispObject fourth,
175                            LispObject fifth, LispObject sixth)
176    throws ConditionThrowable
177  {
178    return function.execute(first, second, third, fourth,
179                            fifth, sixth);
180  }
181
182  @Override
183  public LispObject execute(LispObject first, LispObject second,
184                            LispObject third, LispObject fourth,
185                            LispObject fifth, LispObject sixth,
186                            LispObject seventh)
187    throws ConditionThrowable
188  {
189    return function.execute(first, second, third, fourth,
190                            fifth, sixth, seventh);
191  }
192
193  @Override
194  public LispObject execute(LispObject first, LispObject second,
195                            LispObject third, LispObject fourth,
196                            LispObject fifth, LispObject sixth,
197                            LispObject seventh, LispObject eighth)
198    throws ConditionThrowable
199  {
200    return function.execute(first, second, third, fourth,
201                            fifth, sixth, seventh, eighth);
202  }
203
204  @Override
205  public LispObject execute(LispObject[] args) throws ConditionThrowable
206  {
207    return function.execute(args);
208  }
209
210  @Override
211  public String writeToString() throws ConditionThrowable
212  {
213    LispObject name = getGenericFunctionName();
214    if (name != null)
215      {
216        FastStringBuffer sb = new FastStringBuffer();
217        sb.append(getLispClass().getSymbol().writeToString());
218        sb.append(' ');
219        sb.append(name.writeToString());
220        return unreadableString(sb.toString());
221      }
222    return super.writeToString();
223  }
224
225  // Profiling.
226  private int callCount;
227  private int hotCount;
228
229  @Override
230  public final int getCallCount()
231  {
232    return callCount;
233  }
234
235  @Override
236  public void setCallCount(int n)
237  {
238    callCount = n;
239  }
240
241  @Override
242  public final void incrementCallCount()
243  {
244    ++callCount;
245  }
246
247    @Override
248    public final int getHotCount()
249    {
250        return hotCount;
251    }
252
253    @Override
254    public void setHotCount(int n)
255    {
256        hotCount = n;
257    }
258
259    @Override
260    public final void incrementHotCount()
261    {
262        ++hotCount;
263    }
264
265    // AMOP (p. 216) specifies the following readers as generic functions:
266  //   generic-function-argument-precedence-order
267  //   generic-function-declarations
268  //   generic-function-lambda-list
269  //   generic-function-method-class
270  //   generic-function-method-combination
271  //   generic-function-methods
272  //   generic-function-name
273
274  // ### %generic-function-name
275  private static final Primitive _GENERIC_FUNCTION_NAME =
276    new Primitive("%generic-function-name", PACKAGE_SYS, true)
277    {
278      @Override
279      public LispObject execute(LispObject arg) throws ConditionThrowable
280      {
281          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME];
282      }
283    };
284
285  // ### %set-generic-function-name
286  private static final Primitive _SET_GENERIC_FUNCTION_NAME =
287    new Primitive("%set-generic-function-name", PACKAGE_SYS, true)
288    {
289      @Override
290      public LispObject execute(LispObject first, LispObject second)
291        throws ConditionThrowable
292      {
293          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_NAME] = second;
294          return second;
295      }
296    };
297
298  // ### %generic-function-lambda-list
299  private static final Primitive _GENERIC_FUNCTION_LAMBDA_LIST =
300    new Primitive("%generic-function-lambda-list", PACKAGE_SYS, true)
301    {
302      @Override
303      public LispObject execute(LispObject arg) throws ConditionThrowable
304      {
305          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST];
306      }
307    };
308
309  // ### %set-generic-function-lambdaList
310  private static final Primitive _SET_GENERIC_FUNCTION_LAMBDA_LIST =
311    new Primitive("%set-generic-function-lambda-list", PACKAGE_SYS, true)
312    {
313      @Override
314      public LispObject execute(LispObject first, LispObject second)
315        throws ConditionThrowable
316      {
317          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_LAMBDA_LIST] = second;
318          return second;
319      }
320    };
321
322  // ### funcallable-instance-function funcallable-instance => function
323  private static final Primitive FUNCALLABLE_INSTANCE_FUNCTION =
324    new Primitive("funcallable-instance-function", PACKAGE_MOP, false,
325                  "funcallable-instance")
326    {
327      @Override
328      public LispObject execute(LispObject arg)
329        throws ConditionThrowable
330      {
331          return checkStandardGenericFunction(arg).function;
332      }
333    };
334
335  // ### set-funcallable-instance-function funcallable-instance function => unspecified
336  // AMOP p. 230
337  private static final Primitive SET_FUNCALLABLE_INSTANCE_FUNCTION =
338    new Primitive("set-funcallable-instance-function", PACKAGE_MOP, true,
339                  "funcallable-instance function")
340    {
341      @Override
342      public LispObject execute(LispObject first, LispObject second)
343        throws ConditionThrowable
344      {
345          checkStandardGenericFunction(first).function = second;
346          return second;
347      }
348    };
349
350  // ### gf-required-args
351  private static final Primitive GF_REQUIRED_ARGS =
352    new Primitive("gf-required-args", PACKAGE_SYS, true)
353    {
354      @Override
355      public LispObject execute(LispObject arg) throws ConditionThrowable
356      {
357          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS];
358      }
359    };
360
361  // ### %set-gf-required-args
362  private static final Primitive _SET_GF_REQUIRED_ARGS =
363    new Primitive("%set-gf-required-args", PACKAGE_SYS, true)
364    {
365      @Override
366      public LispObject execute(LispObject first, LispObject second)
367        throws ConditionThrowable
368      {
369        final StandardGenericFunction gf = checkStandardGenericFunction(first);
370        gf.slots[StandardGenericFunctionClass.SLOT_INDEX_REQUIRED_ARGS] = second;
371        gf.numberOfRequiredArgs = second.length();
372        return second;
373      }
374    };
375
376  // ### generic-function-initial-methods
377  private static final Primitive GENERIC_FUNCTION_INITIAL_METHODS =
378    new Primitive("generic-function-initial-methods", PACKAGE_SYS, true)
379    {
380      @Override
381      public LispObject execute(LispObject arg) throws ConditionThrowable
382      {
383          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS];
384      }
385    };
386
387  // ### set-generic-function-initial-methods
388  private static final Primitive SET_GENERIC_FUNCTION_INITIAL_METHODS =
389    new Primitive("set-generic-function-initial-methods", PACKAGE_SYS, true)
390    {
391      @Override
392      public LispObject execute(LispObject first, LispObject second)
393        throws ConditionThrowable
394      {
395          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_INITIAL_METHODS] = second;
396          return second;
397      }
398    };
399
400  // ### generic-function-methods
401  private static final Primitive GENERIC_FUNCTION_METHODS =
402    new Primitive("generic-function-methods", PACKAGE_SYS, true)
403    {
404      @Override
405      public LispObject execute(LispObject arg) throws ConditionThrowable
406      {
407          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS];
408      }
409    };
410
411  // ### set-generic-function-methods
412  private static final Primitive SET_GENERIC_FUNCTION_METHODS =
413    new Primitive("set-generic-function-methods", PACKAGE_SYS, true)
414    {
415      @Override
416      public LispObject execute(LispObject first, LispObject second)
417        throws ConditionThrowable
418      {
419          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHODS] = second;
420          return second;
421      }
422    };
423
424  // ### generic-function-method-class
425  private static final Primitive GENERIC_FUNCTION_METHOD_CLASS =
426    new Primitive("generic-function-method-class", PACKAGE_SYS, true)
427    {
428      @Override
429      public LispObject execute(LispObject arg) throws ConditionThrowable
430      {
431          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS];
432      }
433    };
434
435  // ### set-generic-function-method-class
436  private static final Primitive SET_GENERIC_FUNCTION_METHOD_CLASS =
437    new Primitive("set-generic-function-method-class", PACKAGE_SYS, true)
438    {
439      @Override
440      public LispObject execute(LispObject first, LispObject second)
441        throws ConditionThrowable
442      {
443          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_CLASS] = second;
444          return second;
445      }
446    };
447
448  // ### generic-function-method-combination
449  private static final Primitive GENERIC_FUNCTION_METHOD_COMBINATION =
450    new Primitive("generic-function-method-combination", PACKAGE_SYS, true)
451    {
452      @Override
453      public LispObject execute(LispObject arg) throws ConditionThrowable
454      {
455          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION];
456      }
457    };
458
459  // ### set-generic-function-method-combination
460  private static final Primitive SET_GENERIC_FUNCTION_METHOD_COMBINATION =
461    new Primitive("set-generic-function-method-combination", PACKAGE_SYS, true)
462    {
463      @Override
464      public LispObject execute(LispObject first, LispObject second)
465        throws ConditionThrowable
466      {
467          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_METHOD_COMBINATION] 
468      = second;
469          return second;
470      }
471    };
472
473  // ### generic-function-argument-precedence-order
474  private static final Primitive GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER =
475    new Primitive("generic-function-argument-precedence-order", PACKAGE_SYS, true)
476    {
477      @Override
478      public LispObject execute(LispObject arg) throws ConditionThrowable
479      {
480          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass
481               .SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER];
482      }
483    };
484
485  // ### set-generic-function-argument-precedence-order
486  private static final Primitive SET_GENERIC_FUNCTION_ARGUMENT_PRECEDENCE_ORDER =
487    new Primitive("set-generic-function-argument-precedence-order", PACKAGE_SYS, true)
488    {
489      @Override
490      public LispObject execute(LispObject first, LispObject second)
491        throws ConditionThrowable
492      {
493          checkStandardGenericFunction(first)
494      .slots[StandardGenericFunctionClass.SLOT_INDEX_ARGUMENT_PRECEDENCE_ORDER] = second;
495          return second;
496      }
497    };
498
499  // ### generic-function-classes-to-emf-table
500  private static final Primitive GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE =
501    new Primitive("generic-function-classes-to-emf-table", PACKAGE_SYS, true)
502    {
503      @Override
504      public LispObject execute(LispObject arg) throws ConditionThrowable
505      {
506          return checkStandardGenericFunction(arg)
507      .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE];
508      }
509    };
510
511  // ### set-generic-function-classes-to-emf-table
512  private static final Primitive SET_GENERIC_FUNCTION_CLASSES_TO_EMF_TABLE =
513    new Primitive("set-generic-function-classes-to-emf-table", PACKAGE_SYS, true)
514    {
515      @Override
516      public LispObject execute(LispObject first, LispObject second)
517        throws ConditionThrowable
518      {
519          checkStandardGenericFunction(first)
520      .slots[StandardGenericFunctionClass.SLOT_INDEX_CLASSES_TO_EMF_TABLE] = second;
521          return second;
522      }
523    };
524
525  // ### generic-function-documentation
526  private static final Primitive GENERIC_FUNCTION_DOCUMENTATION =
527    new Primitive("generic-function-documentation", PACKAGE_SYS, true)
528    {
529      @Override
530      public LispObject execute(LispObject arg) throws ConditionThrowable
531      {
532          return checkStandardGenericFunction(arg).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION];
533      }
534    };
535
536  // ### set-generic-function-documentation
537  private static final Primitive SET_GENERIC_FUNCTION_DOCUMENTATION =
538    new Primitive("set-generic-function-documentation", PACKAGE_SYS, true)
539    {
540      @Override
541      public LispObject execute(LispObject first, LispObject second)
542        throws ConditionThrowable
543      {
544          checkStandardGenericFunction(first).slots[StandardGenericFunctionClass.SLOT_INDEX_DOCUMENTATION] 
545      = second;
546          return second;
547      }
548    };
549
550  // ### %finalize-generic-function
551  private static final Primitive _FINALIZE_GENERIC_FUNCTION =
552    new Primitive("%finalize-generic-function", PACKAGE_SYS, true,
553                  "generic-function")
554    {
555      @Override
556      public LispObject execute(LispObject arg) throws ConditionThrowable
557      {
558          final StandardGenericFunction gf = checkStandardGenericFunction(arg);
559          gf.finalizeInternal();       
560          return T;
561      }
562    };
563
564  // ### cache-emf
565  private static final Primitive CACHE_EMF =
566    new Primitive("cache-emf", PACKAGE_SYS, true, "generic-function args emf")
567    {
568      @Override
569      public LispObject execute(LispObject first, LispObject second,
570                                LispObject third)
571        throws ConditionThrowable
572      {
573        final StandardGenericFunction gf = checkStandardGenericFunction(first);
574        LispObject args = second;
575        LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
576        for (int i = gf.numberOfRequiredArgs; i-- > 0;)
577          {
578            array[i] = gf.getArgSpecialization(args.car());
579            args = args.cdr();
580          }
581        CacheEntry specializations = new CacheEntry(array);
582        HashMap<CacheEntry,LispObject> ht = gf.cache;
583        if (ht == null)
584            ht = gf.cache = new HashMap<CacheEntry,LispObject>();
585        ht.put(specializations, third);
586        return third;
587      }
588    };
589
590  // ### get-cached-emf
591  private static final Primitive GET_CACHED_EMF =
592    new Primitive("get-cached-emf", PACKAGE_SYS, true, "generic-function args")
593    {
594      @Override
595      public LispObject execute(LispObject first, LispObject second)
596        throws ConditionThrowable
597      {
598        final StandardGenericFunction gf = checkStandardGenericFunction(first);
599        LispObject args = second;
600        LispObject[] array = new LispObject[gf.numberOfRequiredArgs];
601        for (int i = gf.numberOfRequiredArgs; i-- > 0;)
602          {
603            array[i] = gf.getArgSpecialization(args.car());
604            args = args.cdr();
605          }
606        CacheEntry specializations = new CacheEntry(array);
607        HashMap<CacheEntry,LispObject> ht = gf.cache;
608        if (ht == null)
609          return NIL;
610        LispObject emf = (LispObject) ht.get(specializations);
611        return emf != null ? emf : NIL;
612      }
613    };
614
615  /**
616   * Returns an object representing generic function
617   * argument <tt>arg</tt> in a <tt>CacheEntry</tt>
618   *
619   * <p>In the simplest case, when this generic function
620   * does not have EQL specialized methos, and therefore
621   * only argument types are relevant for choosing
622   * applicable methods, the value returned is the
623   * class of <tt>arg</tt>
624   *
625   * <p>If the function has EQL specialized methods:
626   *   - if <tt>arg</tt> is EQL to some of the EQL-specializers,
627   *     a special object representing equality to that specializer
628   *     is returned.
629   *   - otherwise class of the <tt>arg</tt> is returned.
630   *
631   * <p>Note that we do not consider argument position, when
632   * calculating arg specialization. In rare cases (when
633   * one argument is eql-specialized to a symbol specifying
634   * class of another argument) this may result in redundant cache
635   * entries caching the same method. But the method cached is anyway
636   * correct for the arguments (because in case of cache miss, correct method
637   * is calculated by other code, which does not rely on getArgSpecialization;
638   * and because EQL is true only for objects of the same type, which guaranties
639   * that if a type-specialized methods was chached by eql-specialization,
640   * all the cache hits into this records will be from args of the conforming
641   * type).
642   *
643   * <p>Consider:
644   * <pre><tt>
645   * (defgeneric f (a b))
646   *
647   * (defmethod f (a (b (eql 'symbol)))
648   *   "T (EQL 'SYMBOL)")
649   *
650   * (defmethod f ((a symbol) (b (eql 'symbol)))
651   *   "SYMBOL (EQL 'SYMBOL)")
652   *
653   * (f 12 'symbol)
654   * => "T (EQL 'SYMBOL)"
655   *
656   * (f 'twelve 'symbol)
657   * => "SYMBOL (EQL 'SYMBOL)"
658   *
659   * (f 'symbol 'symbol)
660   * => "SYMBOL (EQL 'SYMBOL)"
661   *
662   * </tt></pre>
663   *
664   * After the two above calls <tt>cache</tt> will contain tree keys:
665   * <pre>
666   * { class FIXNUM, EqlSpecialization('SYMBOL) }
667   * { class SYMBOL, EqlSpecialization('SYMBOL) }
668   * { EqlSpecialization('SYMBOL), EqlSpecialization('SYMBOL) }.
669   * </pre>
670   */     
671  private LispObject getArgSpecialization(LispObject arg)
672  {
673    for (EqlSpecialization eqlSpecialization : eqlSpecializations)
674      {
675        if (eqlSpecialization.eqlTo.eql(arg))
676          return eqlSpecialization;
677      }
678    return arg.classOf();
679  }
680
681  // ### %get-arg-specialization
682  private static final Primitive _GET_ARG_SPECIALIZATION =
683    new Primitive("%get-arg-specialization", PACKAGE_SYS, true, "generic-function arg")
684    {
685      @Override
686      public LispObject execute(LispObject first, LispObject second)
687        throws ConditionThrowable
688      {
689        final StandardGenericFunction gf = checkStandardGenericFunction(first);
690        return gf.getArgSpecialization(second);
691      }
692    };
693
694  // ### cache-slot-location
695  private static final Primitive CACHE_SLOT_LOCATION =
696    new Primitive("cache-slot-location", PACKAGE_SYS, true, "generic-function layout location")
697    {
698      @Override
699      public LispObject execute(LispObject first, LispObject second,
700                                LispObject third)
701        throws ConditionThrowable
702      {
703        final StandardGenericFunction gf = checkStandardGenericFunction(first);
704        LispObject layout = second;
705        LispObject location = third;
706        HashMap<LispObject,LispObject> ht = gf.slotCache;
707        if (ht == null)
708          ht = gf.slotCache = new HashMap<LispObject,LispObject>();
709        ht.put(layout, location);
710        return third;
711      }
712    };
713
714  // ### get-cached-slot-location
715  private static final Primitive GET_CACHED_SLOT_LOCATION =
716    new Primitive("get-cached-slot-location", PACKAGE_SYS, true, "generic-function layout")
717    {
718      @Override
719      public LispObject execute(LispObject first, LispObject second)
720        throws ConditionThrowable
721      {
722        final StandardGenericFunction gf = checkStandardGenericFunction(first);
723        LispObject layout = second;
724        HashMap<LispObject,LispObject> ht = gf.slotCache;
725        if (ht == null)
726          return NIL;
727        LispObject location = (LispObject) ht.get(layout);
728        return location != null ? location : NIL;
729      }
730    };
731
732  private static final StandardGenericFunction GENERIC_FUNCTION_NAME =
733    new StandardGenericFunction("generic-function-name",
734                                PACKAGE_MOP,
735                                true,
736                                _GENERIC_FUNCTION_NAME,
737                                list(Symbol.GENERIC_FUNCTION),
738                                list(StandardClass.STANDARD_GENERIC_FUNCTION));
739
740  private static class CacheEntry
741  {
742    final LispObject[] array;
743
744    CacheEntry(LispObject[] array)
745    {
746      this.array = array;
747    }
748
749    @Override
750    public int hashCode()
751    {
752      int result = 0;
753      for (int i = array.length; i-- > 0;)
754        result ^= array[i].hashCode();
755      return result;
756    }
757
758    @Override
759    public boolean equals(Object object)
760    {
761      if (!(object instanceof CacheEntry))
762        return false;
763      final CacheEntry otherEntry = (CacheEntry) object;
764      if (otherEntry.array.length != array.length)
765        return false;
766      final LispObject[] otherArray = otherEntry.array;
767      for (int i = array.length; i-- > 0;)
768        if (array[i] != otherArray[i])
769          return false;
770      return true;
771    }
772  }
773
774  private EqlSpecialization eqlSpecializations[] = new EqlSpecialization[0];
775
776    // ### %init-eql-specializations
777    private static final Primitive _INIT_EQL_SPECIALIZATIONS
778      = new Primitive("%init-eql-specializations", PACKAGE_SYS, true, 
779        "generic-function eql-specilizer-objects-list")
780      {
781        @Override
782        public LispObject execute(LispObject first, LispObject second)
783          throws ConditionThrowable
784        {
785          final StandardGenericFunction gf = checkStandardGenericFunction(first);
786          LispObject eqlSpecializerObjects = second;
787          gf.eqlSpecializations = new EqlSpecialization[eqlSpecializerObjects.length()];
788          for (int i = 0; i < gf.eqlSpecializations.length; i++) {
789      gf.eqlSpecializations[i] = new EqlSpecialization(eqlSpecializerObjects.car());
790      eqlSpecializerObjects = eqlSpecializerObjects.cdr();
791          }
792          return NIL;
793        }
794      };
795
796  private static class EqlSpecialization extends LispObject
797  {
798    public LispObject eqlTo;
799
800    public EqlSpecialization(LispObject eqlTo)
801    {
802        this.eqlTo = eqlTo;
803    }
804  }
805 
806  public static final StandardGenericFunction checkStandardGenericFunction(LispObject obj)
807  throws ConditionThrowable
808  {
809    if (obj instanceof StandardGenericFunction)
810      return (StandardGenericFunction) obj;
811    return (StandardGenericFunction) // Not reached.
812      type_error(obj, Symbol.STANDARD_GENERIC_FUNCTION);
813  }
814}
Note: See TracBrowser for help on using the repository browser.