All Manuals > Delivery User Guide > 10 Delivery and Internal Systems

10.1 Delivery and CLOS

Most applications using CLOS can be delivered without difficulty. However, there are a few potential exceptions to this rule. Code dynamically redefining classes and methods, and with certain method combinations, needs some extra work.

However, at delivery level 0 it is unlikely that you will need to do anything.

10.1.1 Applications defining classes or methods dynamically

Set the deliver keyword :keep-clos to t or :full-dynamic-definition to keep the code needed for dynamic definition in the image.

At delivery level 0 the default value of :keep-clos is :full-dynamic-definition, so you will not need to do anything special.

10.1.2 Special dispatch functions and templates for them

The LispWorks CLOS implementation achieves fast method dispatch by producing special functions to perform discrimination and method dispatch. Since the required operation can often only be determined by seeing what arguments a generic function is called with, these functions can often end up being generated and compiled at run time.

If the compiler has been removed in a delivered application, then these special run time-generated functions cannot be compiled on the fly.

There are two ways in which the delivery system deals with this problem.

The first is to have a set of pre-compiled "template" constructors which can construct an appropriate function. LispWorks comes with extensive set of such constructors, which should cover most of cases. The programmer can add her own, as explained below.

The other mechanism is to construct generic closures to do the work. The code that generates the closures can cope with:

  1. A simple method combination, with the operator naming a function (or generic function) -- not a macro or special form.
  2. A more complicated method combination, constructing a form which should effectively be a tree of progn , multiple-value-prog1 and call-method forms.

In most cases the effect on method dispatch time of using the generic technique is negligible. Pathological cases might, however, cause a slowdown of 10-20% over compiled special functions. In this case, as well as for cases of user-defined complex method combinations which the generic mechanism cannot cope with, the delivered image must have precompiled "template" constructors, and if they are not already there the user needs to add them, as described next.

10.1.2.1 Finding the necessary templates

Even though it cannot compile the functions at run time, delivery can generate the forms for them. The necessary method combination templates can be found by using the keyword :warn-on-missing-templates. This defaults to nil. If this keyword is non-nil, a warning is issued whenever a missing template is detected. The value of this keyword can be either a string or a pathname, in which case it is a file to put the warning in, or t, in which case the warning goes to *terminal-io*. The warning takes this form:

;*****
 
;>>> Add this combination to the template file <<<
 
(CLOS::PRE-COMPILE-COMBINED-METHODS
 
  ((1 COMMON-LISP:NIL) COMMON-LISP:NIL (CLOS::_CALL-METHOD_)))
 
; *****

You can take this template, place it in an ordinary lisp file, return to LispWorks, and compile it. This compiled file should be loaded into the image before delivery. See 10.1.2.2 Incorporating the templates into the application.

Most missing templates can be found statically, and if :warn-on-missing-templates has been set, they are output at the time of saving the delivery image. An attempt is made to find all missing templates. However, because method combinations are dependent on the actual arguments to generic functions, it is not always possible to find every missing template. The application must be run to be sure of finding all the missing templates.

Note: Valid combinations may be generated or seen in warnings even if they are never used. Delivery can only tell you what combinations the application could potentially use.

10.1.2.2 Incorporating the templates into the application

A typical measure is to put all the templates generated into a file. You can add new ones to it as you work through the delivery process. The templates must be compiled and loaded into the application before delivery. To do this:

  1. Collect into one template file all the method combination template forms that have been output, so that it looks something like this:
    (CLOS::PRE-COMPILE-COMBINED-METHODS ((1 COMMON-LISP:NIL) COMMON-LISP:NIL
     
        (COMMON-LISP:MULTIPLE-VALUE-PROG1 (CLOS::_CALL-METHOD_)
     
                              (CLOS::_CALL-METHOD_)
     
                              (CLOS::_CALL-METHOD_))))
     
    (CLOS::DEFINE-PRE-TEMPLATES
     
      CLOS::DEMAND-CACHING-DCODE-MISS-FUNCTION (5 COMMON-LISP:NIL (4)))
     
    (CLOS::DEFINE-PRE-TEMPLATES
     
      CLOS::DEMAND-CACHING-DCODE-MISS-FUNCTION (6 COMMON-LISP:NIL (4)))
    ...
    

    No matter how many times the template form is printed, it only needs to be included in the template file once.

  2. In the LispWorks image, compile the template file.
  3. Load the compiled template file into the image (along with the application and library files) before delivery.

10.1.3 Delivery and the MOP

MOP programmers should note that, by default, the direct slots and direct methods of all classes are emptied at delivery level 1 and above. To prevent this, set the deliver keyword :keep-clos to t, :full-dynamic-definition or :meta-object-slots as required.

10.1.4 Compression of CLOS metaobjects

To reduce the size of the delivered image, the delivery process compresses the representation of CLOS metaobjects (classes, generic functions and methods). This includes:

  1. nullifying the class direct slots of the class.
  2. Changing the effective slots to a function that is used in the initialization of the instance. This is controlled by :metaclasses-to-keep-effective-slots and :classes-to-keep-effective-slots.
  3. Compressing the representation of method objects. This is controlled by :keep-clos. If :keep-clos is t, the representation of method objects is not compressed. There is also no compression if you add a method to method-qualifiers, method-specializers or method-function.
  4. Compressing the representation of generic functions. This is not done if :keep-clos is t, or if you add methods to any of the accessors of generic functions.

10.1.5 Classes, methods, and delivery

See 4.6.2 Shaking the image for a discussion of how unused class definitions and methods are treated by delivery process.

10.1.6 Delivery and make-instance initarg checking

By default make-instance checks for valid initargs in LispWorks, signalling an error on an invalid call. However, in a delivered application this behavior may not be useful.

Initarg checking in the delivered application is controlled by the deliver keyword :make-instance-keyword-check.

For more information about make-instance initarg checking, see the LispWorks® User Guide and Reference Manual.


Delivery User Guide - 01 Dec 2021 19:35:04