Loading

The index for the Allegro CL Documentation is in index.htm. The documentation is described in introduction.htm.

This document contains the following sections:

1.0 Using the load function
   1.1 EOF encountered error during a load
   1.2 Special utilities for loading applications
2.0 Search lists
   2.1 Search List Structure
   2.2 Search lists variables
   2.3 Search list example
3.0 The Allegro Presto algorithm
   3.1 Comparison to autoloading
   3.2 Improved locality of reference
   3.3 Allegro Presto: basic usage
   3.4 Allegro Presto: advanced usage
   3.5 Libfasl loading
   3.6 What does the libfasl feature apply to?
   3.7 What does the libfasl feature do?
   3.8 When is a stub function fully loaded?
   3.9 When is libfasl loading invoked?
   3.10 What are the costs and advantages of using the libfasl feature?
   3.11 The in-package restriction
   3.12 Affect on users 1: keeping track of files
   3.13 What happens if Lisp cannot find a necessary fasl file?
   3.14 What happens if the file has changed?
   3.15 Affect on users 2: eq-ness of function objects
   3.16 Libfasl and excl:dumplisp
4.0 Loading and case modes

1.0 Using the load function

In Allegro CL, load has additional keyword arguments, libfasl, searchlist, and system-library, described in the next three bullets.

Note that certain global variables are bound when load is loading a file. Therefore, setting those variables in an initialization file (such as .clinit.cl) will not have the desired effect. (See also the next section which discusses setting global values in an initialization file). The following table shows what variables are bound by load:

Variable

Bound to

*package**package*
*readtable**readtable*
excl:*source-pathname*name of file being loaded
*redefinition-warnings**redefinition-warnings*
*libfasl*value of :libfasl keyword argument to load, if specified, or *libfasl*

Table 1 Variables bound by load

The top-level command :ld calls the load function. :ld will accept multiple filenames but it does not accept keyword arguments. :ld reads its arguments as strings and does not accept pathnames or streams as filename arguments. Therefore, to load the file test.cl, the following :ld command will work:

:ld test.cl

The file is found via the load search list, described below. With the default value of the load search-list (it is the value of the variable *load-search-list*), the path provided is merged with *default-pathname-defaults*.

There are other keyword arguments for load in Allegro CL other than those specified by the ANSI standard, such as unreferenced-lib-names, used when load loads foreign (C or Fortran) object files. See foreign-functions.htm for details of these additional keyword arguments.

1.1 EOF encountered error during a load

If you try to load a file that contains an incomplete form (because of, e.g., a missing closing parenthesis), load signals an error with condition end-of-file. Consider the following file missing-paren.cl:

(defun foo nil nil)
(defun bar (a b) (+ a b)

The closing parenthesis is missing from the definition of bar. When Lisp tries to load this file, it signals an error:

USER(1): :ld missing-paren.cl
; Loading /net/rubix/usr/tech/dm/missing-paren.cl.
Error: eof encountered on stream #<EXCL::CHARACTER-INPUT-FILE-STREAM
#p"/net/rubix/usr/tech/dm/missing-paren.cl" pos 45 @ #xa91f02>
starting at position 20.
 [condition type: END-OF-FILE]

Restart actions (select using :continue):
 0: retry the load of missing-paren.cl
[1] USER(2):

Note the line:

starting at position 20.

That indicates that the incomplete form starts at position 20 in the file. Opening the file in Emacs and entering the command C-u 20 C-f (assuming standard keybindings) should bring you to the beginning of the incomplete form.

1.2 Special utilities for loading applications

Allegro CL does provide certain utilities for loading collections of files, in particular collections of files which comprise an application. The primary utility for this purpose is the defsystem utility, described in defsystem.htm. A couple of simpler utilities are also available: the macros load-application and tenuring.

tenuring allows evaluation of forms with all live objects tenured at the end of the evaluation. You might want to call load within that macro. See the discussion in gc.htm for more information.

load-application allows you to specify the environment in which the loading takes place.

2.0 Search lists

Now that logical pathnames are available in Lisp, search lists may be obsolete. However, they are preserved for backward compatibility.

This section describes how load and require find the files they are called upon to load. Novice users, who keep the files to load in the same directory as they run Lisp need not concern themselves with the subtleties of this section. However, the facilities defined in this section are very powerful, allowing complicated mechanisms to be defined for finding files specified without directory paths or with only relative directory paths. If such capability will be useful to you, you should read on.

The functions require and load (and the top-level command :ld) read files. The Common Lisp standard specifies how the filename argument to these functions is processed to yield the true name of the file to be read: the argument is merged (using the Common Lisp function merge-pathnames) with the value of *default-pathname-defaults*. This file-finding mechanism is inadequate for all but the simplest of applications although logical pathnames may be adequate. Note that using the initial value of the load search-list, pathnames are merged with *default-pathname-defaults*. Note further that the directory specified by *default-pathname-defaults* may be different from the directory returned by current-directory (see the description of chdir).

Addressing the need for a more flexible file-finding mechanism, Allegro CL incorporates searchlists, data structures embodying information about how the functions load and require will find a file to load into Lisp. Both functions have their own search list.

Autoloading (where an action like calling a function triggers the loading of the module containing the associated functionality) also uses a search list. We do not discuss it much in this document since autoloading is usually invisible to the user.

Search lists permit the user to specify a sequence of pathnames to be merged with the filename argument to load or require. We henceforth refer to this filename argument as the suppliedname. From among those pathnames resulting from the sequence of merging operations, the first pathname that satisfies the given criteria will be loaded. Further, it is possible to specify side effects, e.g. to compile a file if the source file has been modified more recently than the corresponding compiled (fasl) file. This very general mechanism provides considerable control over file-loading operations.

The libfasl utility allows functionality to be kept on disk until actually needed. It permits users to run smaller images at the cost of slightly increased time to call functionality stored on disk but that cost is paid during the first call only; section 3.5 Libfasl loading describes the libfasl utility.

You can build a standard image. Which is controlled by the presto argument to build-lisp-image (see building-images.htm). Or you can load individual files in libfasl mode by specifying the libfasl argument to load true.

A libfasl image has most of the default Lisp functionality stored in a file called the bundle file, whose name is files and whose extension is bu or ebu. When you load a module (for example, inspect, foreign-functions, trace, etc.) the system must know to look in the bundle file instead of looking for the fasl file in the Lisp library. The :lib-bundle search list keyword argument provides this functionality.

2.1 Search List Structure

A search list is a recursive data structure. It may be a symbol, string, pathname, or a list of search lists. (The car of a list is interpreted specially.) The elements of a search list are processed sequentially. If the search list is recursive, it is processed in depth-first fashion. The goal of processing a search list is to locate a file to be loaded -- in effect a search list returns the pathname of a file. It is often convenient to refer to search lists as returning a pathname, especially when discussing recursive search lists. It is an error if a file cannot be located within the given constraints. The different kinds of search lists are handled as follows:

(merge-pathnames supplied-name search-element) 

We now define the effect of the keywords that can be the car of a list search list. In the definitions below, we borrow the Common Lisp notation &rest search-list to represent the rest of the list.

KeywordArgumentsDescription
:first&rest search-listsearch-list may be one or more symbols, strings, pathnames or lists of search lists. When this search list keyword is processed, each element of search-list is merged with the supplied name and the first existing file is returned. Once an existing file is found, any remaining elements in search-list are not processed. search-list is processed sequentially from head to tail. The search list returns nil if, after processing all elements of search-list, no such file exists. Note that if no search list keyword is specified, then the search list is treated as if it began with :first.
:newest&rest search-listsearch-list may be one or more symbols, strings, pathnames or lists of search-lists. When this search list keyword is processed, all of the elements in search-list are merged with the supplied name and the newest file is returned. If no files exist then nil is returned.
:newest-ask-compilefasl-name &rest search-listfasl-name must be a string or pathname. search-list may be one or more symbols, strings, pathnames or lists of search-lists. fasl-name is merged with the supplied name and the resulting pathname must name a fasl (compiled Lisp) file. Each element of search-list is then merged with the supplied name and the first existing file denoted among them, which should be a source file, is selected. If the fasl file exists, and if it is newer than the first source file, the pathname of the fasl file will be returned. If no source file exists, the fasl file is returned. If no fasl file exists, or if the fasl file is older than the first source file, the user is asked whether the source file should be compiled to yield a new fasl file. If the response is affirmative, the file is compiled and the pathname of the fasl file is returned. Otherwise, the pathname of the newest source file is returned. If neither fasl file nor source file exists, nil is returned.
:newest-do-compilefasl-name &rest search-listfasl-name must be a string or pathname. search-list may be one or more symbols, strings, pathnames or lists of search-lists. A list containing this keyword is processed identically to a list containing the :newest-ask-compile keyword, except that the user is not asked whether a file should be compiled. The compilation is always performed if required and the pathname of the resulting fasl file is returned. Note that if two source files mutually require each other, then this option can result in an infinite loop (where neither can be compiled until the other is). To resolve this conflict, one of the files must be loaded interpreted. Therefore, the :newest-do-compile option is not recommended for *require-search-list*.
:callfunction &rest search-listfunction must be funcallable. search-list may be one or more symbols, strings, pathnames or lists of search-lists. This search list keyword argument can be used by the user to add a new feature to search list processing. Note that misuse of this search list keyword argument can make it difficult to use Lisp. Most users will never have a use for this search list keyword argument. This function is applied, once, to four arguments: the supplied name, search-list, order and check-bundle. The argument order defaults to :first, but may be set to other values while processing an earlier search list (see the example below). check-bundle is non-nil if the bundle is to be checked. The function must return a pathname or a string or nil, and this value is returned by the search list. See the example just below this table.
:lib-bundlesub-pathname &optional default-pathnamesub-pathname and default-pathname can each be either pathnames or symbols whose symbol-value is a pathname. sub-pathname may be a list of pathnames that are merged together when the search list is processed.

This search list keyword argument first merges the supplied name and sub-pathname. Then the enough-namestring function is used to find the shortest string to identify uniquely the pathname relative to default-pathname. In other words, the pathname to be processed is determined by the form below:

(enough-namestring (merge-pathname supplied-name sub-path) default-pathname)

If the pathname produced by the form above is in the bundle, then three values are returned: the pathname, the ACL compiler time stamp and t. If the pathname is not in the bundle, then nil is returned.

For an example using :call, a user supplied function could look like:

(defun my-call 
 (target search-list order check-bundle)
 ;; User supplied code, eventually returning a pathname,
 ;; a string or nil.
 )
;; A sample searchlist that uses :call.
(:newest
 (:call my-call . . .)
 (:call my-call . . .))
;; The order argument to my-call will be :newest instead
;; of :first. 

2.2 Search lists variables

The search list for the load function is bound to the symbol *load-search-list*. The default value on many platforms for this symbol is

(#p"" #p(:type "fasl") #p(:type
      "cl") #p(:type "lisp"))

Thus load function looks for its file first by its supplied name in the directory which is the value of *default-pathname-defaults*. If it cannot find the file there, it looks in the same place for a file with a "fasl" file type, then with a "cl" file type, and then with a "lisp" file type. If no file is found, then the search list returns nil indicating no satisfactory file corresponding to the supplied name was found.

The search list for the require function is bound to the symbol *require-search-list*. The initial value for this symbol changed in release 6.0 compared to earlier releases. Its value is now:

((:first #p"sys:;code;.fasl"
	 #p"sys:;private;.fasl"
	 #p"sys:;clos;.fasl"
	 #p"sys:;sys;.fasl"
         (:lib-bundle #p"sys:;code;.fasl")
         (:lib-bundle #p"sys:;private;.fasl")
         (:lib-bundle #p"sys:;clos;.fasl")
         (:lib-bundle #p"sys:;sys;.fasl"))
 #p"src:;code;.cl"
 #p"src:;private;.cl"
 #p"src:;clos;.cl"
 #p"src:;sys;.cl")

require now only looks for fasl files in subdirectories of sys: and for source files in subdirectories of src:. In sys: it also looks in the bundle file. A problem with require is earlier releases, where it looked in the current directory as well as library directories, was that files with names the same as module name ("build" for example) were loaded in preference to the library file, with undesired results.

Note that looking in the bundle file is preceded by looking in code/. If a file exists in both the bundle and in the code/ subdirectory, then the first file encountered will be in code/ and will be used. (This ensures that a fixed fasl file which was originally part of the bundle, supplied as a patch and placed in code/, will be used instead of the version in the bundle file.)

There is also an autoload search list, the value of *autoload-search-list*, which is used by the system when an autoload is triggered. Autoloads are triggered by actions such as calling a function whose functionality is not presently in the system. (Not all such functions trigger autoloads. Typically only the important functions of a facility.) Autoloading is usually nearly invisible to users. Most modules are autoloaded from the bundle. The structure of the search list, however, ensures that updated fasl files which replace fasl files in the bundle are found and used correctly.

2.3 Search list example

Suppose that you maintain a personal Lisp library in a subdirectory of your home-directory, and that you wish to have the load function look for files in this subdirectory. Let us assume this subdirectory is named lisplib. It would be reasonable to search your library directory after searching the directory which is the value of *default-pathname-defaults*. (Note that the directory specified by *default-pathname-defaults* may be different from the directory returned by current-directory. See the description of chdir.)

Further, say you would like to compile automatically all files that are in your working or library directories. The following definition of system:*load-search-list* in an initialization file (such as .clinit.cl) will accomplish this. Your home directory pathname is denoted with a tilde (`~').

(setq system:*load-search-list*
  '(:first
    (:newest-do-compile 
      #.(make-pathname :type "fasl")
      #.(make-pathname :type "cl"))
     (:newest-do-compile
     #.(make-pathname :directory "~/lisplib"
:type "fasl")
      #.(make-pathname :directory "~/lisplib"
:type "cl"))
 ))

If you start up Lisp in the directory ~/work, the expression

(load "foo") 

will result in the following pathnames being generated.

>~/work/foo.fasl ;; these two point to
~/work/foo.cl ;; the current directory
~/lisplib/foo.fasl ;; these two point to the 
~/lisplib/foo.cl ;; lisplib directory

If ~/work/foo.cl exists, it will be compiled, if necessary, and ~/work/foo.fasl will be loaded. If ~/work/foo.fasl exists but ~/work/foo.cl does not, ~/work/foo.fasl will be loaded. If neither of these files exists, the next two files are examined. If ~/lisplib/foo.cl exists, it will be compiled, if necessary, and ~/lisplib/foo.fasl will be loaded. If ~/lisplib/foo.fasl exists but ~/lisplib/foo.cl does not, ~/lisplib/foo.fasl will be loaded. If neither of these files exist, an error is signaled.

Note: if you change the value of *require-search-list*, you must include

(:newest (:lib-bundle #p"sys:;code;.fasl") 
         #p"sys:;code;.fasl"
         #p"sys:;code;.cl"

so that Lisp will be able to find library files such as foreign.fasl.

3.0 The Allegro Presto algorithm

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

Under Allegro Presto, when a fasl file (a compiled Lisp file) is loaded into Lisp, only part of the information about a compiled function is loaded. The rest is kept in the fasl file and is loaded only when it is needed (typically, when the function is actually called). The partially-loaded function is called a stub function. The act of partially loading function definitions is called libfasl loading (distinguished from ordinary loading).

When the stub function is called, the system notices that only the stub definition is resident in the image so it automatically (and transparently to the user) retrieves the call-time function info from the disk file and, conceptually, replaces the stub definition with the complete definition. (We say conceptually because the exact mechanics and timing of the replacement are more complicated.)

The headings for the remainder of this section are:

3.1 Comparison to autoloading
3.2 Improved locality of reference
3.3 Allegro Presto: basic usage
3.4 Allegro Presto: advanced usage
3.5 Libfasl loading
3.6 What does the libfasl feature apply to?
3.7 What does the libfasl feature do?
3.8 When is a stub function fully loaded?
3.9 When is libfasl loading invoked?
3.10 What are the costs and advantages of using the libfasl feature?
3.11 The in-package restriction
3.12 Affect on users 1: keeping track of files
3.13 What happens if Lisp cannot find a necessary fasl file?
3.14 What happens if the file has changed?
3.15 Affect on users 2: eq-ness of function objects
3.16 Libfasl and excl:dumplisp

3.1 Comparison to autoloading

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

Autoloading is an image-size-reducing mechanism available in Allegro CL. Certain fasl files are not loaded into the standard image but are instead loaded only when certain functions associated with the fasl file are called. When a function that triggers autoloading is called (e.g. trace, which autoloads trace.fasl), the entire fasl file is fully loaded with the complete definitions of all defined functions. Thus a call to a single function can cause many functions to be loaded. With libfasl loading, some portion of the fasl file is brought into Lisp, including stub definitions for all defined functions, but full definitions are only loaded for those functions when they are actually called, saving the space required for the call time info of functions not called.

This benefit over autoloading is particularly important when Allegro CL is run with the Emacs-Lisp interface and/or Allegro Common Windows and Allegro Composer. Those utilities use much Lisp functionality and so cause many of the library files (including, e.g., foreign.fasl, process.fasl, and mdproc.fasl) to be loaded. Without Allegro Presto, these files are fully loaded and most of the benefits of autoloading disappear.

3.2 Improved locality of reference

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

The space-saving benefit of libfasl loading has just been described. A second benefit is also provided: improved locality of reference. Locality of reference refers to the likelihood that related things are placed together (the better the locality of reference, the higher the likelihood). Improved locality of reference arises because code vectors of stub functions called in conjunction with one another are loaded in close proximity. A feature of loading call-time function info is that it is immediately stored in oldspace rather than starting in newspace and being tenured to oldspace after a period of time. Therefore, the code vectors for functions called in close proximity will (in general) be stored in close proximity. This is a benefit because if they are on the same page in memory, they will always be paged in and out together. Optimal locality of reference will occur when the code vectors are on the same page in memory. That cannot, of course, be guaranteed but is evidently much more likely to occur with Allegro Presto and libfasl loading.

3.3 Allegro Presto: basic usage

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

The simplest way to use Allegro Presto, and the way recommended for most beginning users, is simply to specify :presto t to excl:build-lisp-image when building a Lisp image. If you do that, the system will libfasl load whatever is required during the building of the image. Further, the value of *libfasl* is set to t so all subsequent loads will also be libfasl loads (unless you override the value of *libfasl* in some fashion).

If you specify :presto nil, Allegro Presto will be disabled in the resulting image.

If you specify :presto :enable, Allegro Presto will be enabled but *libfasl* will initially be nil.

The function prestop, which takes no arguments, returns t or nil as Allegro Presto is or is not disabled in an image.

All of this is virtually transparent to the user, who will see no reduction in functionality.

3.4 Allegro Presto: advanced usage

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

We have provided the information and facilities for using Allegro Presto with the standard Allegro CL features (such as Allegro Composer and the foreign function interface). But we also provide tools for improving the performance of your application by gathering information about usage and providing that information to Lisp.

Suppose you are running a Lisp application and you are aware of the Allegro Presto utility: conceptually, what would you like to have happen? We would suggest that you will want the following:

  1. Have functionality that is less likely to be used stored on disk until needed.
  2. Have functionality that will certainly be used included in the image (to avoid paying the cost of fully loading functions you know will be called).

The simple use of Allegro Presto described above provides # 1: the fasl files that make up your application will be loaded in libfasl mode, which means that all functions (frequently or rarely used) will start as stubs and be fully loaded only when necessary. The time of loading will usually improve locality of reference.

So, how to get #2? What is necessary is to tell Lisp what functions will certainly be called and so should start fully loaded (thus saving the overhead required to resolve stub functions).

For example, consider Allegro Composer as an application. It is certain that anyone who uses Allegro Composer will call start-composer (since that function actually starts the utility). Therefore, there is no point in partially loading that function since it will quickly be fully loaded anyway.

3.5 Libfasl loading

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

We have already defined libfasl loading above, but here again is a brief definition: when a compiled file is loaded in libfasl mode, only part of the definition of each function is loaded. The partially loaded function is called a stub function and it contains a pointer to the file where the remainder of the definition resides. When the function is actually called, the remainder of the function definition is loaded (automatically and transparently to the user). Thus, libfasl loading allows a user to keep some part of Lisp functionality on disk until it is actually needed.

In this and the following sections, we discuss details and consequences of libfasl loading, covering a number of topics identified in large headings in bold type.

3.6 What does the libfasl feature apply to?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

The libfasl feature provides an alternate way of loading fasl (compiled Lisp) files. Therefore, it only applies to compiled functions defined in a fasl file (this includes library files). Functions defined and compiled within Lisp are not affected by the libfasl feature (since they are not loaded) and functions defined in Lisp source files which are loaded into Lisp are not affected by the libfasl feature (since they are not compiled). In order to avoid introducing package errors, only functions defined after an in-package form within a fasl file are libfasled.

3.7 What does the libfasl feature do?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

When a function in a compiled file is loaded in libfasl mode, only part of the compiled function is loaded. A compiled function is composed of various parts, including, for example, the code vector, where the code executed when the function is called is stored. In libfasl mode, the smallest amount of information possible is loaded. Included in that information is the name of the file which contains the remainder of the complete function. The documentation string (if there is one) is also always available without accessing the file containing the rest of the function.

A partially loaded function is also called a stub function. When a partially loaded function is actually called, all remaining parts are loaded. A function that has all its parts loaded is said to be fully loaded. The process of loading the remainder of a stub function is called resolving the call-time information or fully loading.

3.8 When is a stub function fully loaded?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

The following actions will cause the system to fully load a function definition:

  1. Calling the function.
  2. Calling resident-function with the function object as the argument.
  3. Getting the argument list of the function with arglist. (Note that arglist is called by other functions, e.g. describe, and by various Emacs commands.)
  4. Compiling a call to the function. (This occurs because the argument list is needed by the compiler.)
  5. Disassembling the function.
  6. Writing the function as a constant out to a fasl file.

Applications (including CLIM and Allegro Composer) can fully load stub functions at any time of course.

3.9 When is libfasl loading invoked?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

When the value of the :libfasl argument to load is true and load is loading a compiled file, functions will be loaded in libfasl mode (except see the paragraph headed 3.11 The in-package restriction below). If no value is specified for the :libfasl argument, it defaults to the value of *libfasl*. If :presto is specified true to build-lisp-image, the initial value of that variable is t.

Several other functions cause load to be called including require, load-system, and the top-level commands :ld and :cload. None of these functions or commands have the mechanism to specify whether loading should be in libfasl or normal mode, so the mode is determined by the value of *libfasl*.

3.10 What are the costs and advantages of using the libfasl feature?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

The costs are (1) a slightly increased time to execute functions the first time (but only the first time) they are called and (2) the necessity to ensure that the files where the unloaded functionality is stored are available to Lisp (and any descendent images made with dumplisp).

The advantage of libfasl loading is that information which may not be necessary will not be loaded until needed. This allows for a smaller image size than otherwise without reducing functionality (reductions in image size of between 25% and 40% are normal, 50% has been seen).

This feature is particularly useful when loading a large file since in fact only some of the functions defined in the file may ever be called and space is saved by not loading parts of the functions which are never called. A further advantage is an improvement in locality of reference since code vectors used near one another will be loaded closely together and are thus likely to be located close to one another.

3.11 The in-package restriction

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

In a given source file, only functions defined after an in-package form will be loaded in libfasl mode. Functions whose definitions are located in the source file before an in-package form will always be fully loaded. (Therefore, all functions in files that do not contain an in-package form will be fully loaded.) This restriction guards against package errors and confusion.

3.12 Affect on users 1: keeping track of files

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

In general, operation of libfasl loading should be transparent to the user. The additional time required to fully load a function the first time it is called is not significant and may not even be noticeable. However, there are two issues that should concern users: location of fasl files (discussed here) and eq-ness of function objects (discussed below).

The location of the file containing the call-time function information for a function is stored in the loaded portion of the function definition. When the function is called, the system looks for that file to load the remainder of the function. At that time, the file must be exactly where the system expects it (the location of the fasl file which was loaded in libfasl mode), or an error will be signaled. See also the information under the heading 3.14 What happens if the file has changed?.

Note that the file location is stored as an absolute pathname (regardless of how the file was specified to Lisp). Therefore, the current directory can be changed (with chdir) without affecting the ability to find the files needed to resolve stub functions. However, this fact also affects dumplisp. See dumplisp.htm for a discussion of that point. See presto-build-lib which bundles all information in one file. That may be useful when dumping an image intended for a different machine.

3.13 What happens if Lisp cannot find a necessary fasl file?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

If Lisp cannot find the file pointed to by a stub function, it clearly cannot continue computation since it has no code vector to execute. Therefore, Lisp signals an error. The error is similar to the following:

Error: Lisp is unable to resolve call-time information for stub
function <function name>, which was defined in file
<filename> and loaded in libfasl mode, because that file
is missing or has been changed or corrupted.

Note that if the file which cannot be found is the bundle file, files.bu or files.ebu, (which holds the code vectors of the base Lisp system), the failure may be fatal since Lisp may not be able to find the call-time function info necessary to process the error, resulting in a recursive error. However, we believe that the bundle file (and other Lisp library files) will be available while a Lisp image is running except under extraordinary circumstances. It is definitely a fatal error to remove such files while Lisp is running.

3.14 What happens if the file has changed?

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

If you change a compiled file which has already been libfasl loaded, (by, e.g., changing and compiling the source file) you must reload the changed compiled file in order to update the pointers within Lisp to the function definitions. The top-level command :cload, which does both a compile and a load, is very useful for ensuring that you have always loaded the most recently compiled file.

When a file is libfasl loaded, a pointer stored in the stub function points to the location in the file where a special code identifies the location as an appropriate location to begin loading the remainder of the function. If the pointer is found to point to a location that does not contain that special code, an error is signaled. The error is the same as shown above.

If the file exists, it is most likely to have been changed (corruption is possible but, presumably, rare). If the function is still defined in the file, it is most likely that the file was not reloaded and reloading will allow the function call to succeed. If the function is no longer defined in the file, reloading will (of course) make no difference and in that case, either calling the function in the first place was an error or the file where the function is now defined should be loaded.

Note that it is possible that after a file has been changed but not reloaded, the pointer in the stub function points to a location with the special code even though it no longer points to the correct definition (that is, it points to the definition of another function). We believe that this will be rare. When it occurs, however, Lisp will try to execute the wrong function code, likely leading to other errors (e.g. the wrong number of arguments passed) or strange results. This may lead to confusion and users should be aware of the possibility. This is an unavoidable problem. Providing sufficient checks to avoid this unlikely situation would so increase the cost of the libfasl feature that the benefits would be lost.

3.15 Affect on users 2: eq-ness of function objects

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

A stub function is not the same object as a fully loaded function. Suppose that a function foo is only partially loaded and another function, bar, calls foo. The function bar will contain a pointer to the stub definition of foo. Now suppose that foo is called independently of bar. foo will be fully loaded (probably into a different location) and the stub definition will be destructively modified to point to the full definition. However, bar will still point to the stub definition. Only at the next garbage collection will all pointers be updated and the stub function definition disposed of.

This means that things you might expect to be eq will not be eq, at least for a while. Thus, if the function is fully loaded and there has subsequently been a gc when you call resident-function, the returned value will be eq to the argument. If the function is not fully loaded or there has not been a gc, the returned value will not be eq to the argument and other references to the function object may not be eq to the returned value until after a garbage collection.

3.16 Libfasl and excl:dumplisp

Use of Allegro Presto is deprecated. The Allegro Presto facility may be removed from future releases.

Because much of the size saving obtained by Allegro Presto can be achieved with pll files and other techniques, and because Allegro Presto adds significant compexity to code and images, it is intended to remove the Allegro Presto facility in a future release.

Because the files needed to resolve stub functions must be available when the stub function is called, there are a number of ways in which libfasl loading affects the dumplisp utility. These are discussed in 15.0 Dumping a prestoized image in dumplisp.htm. Please look at that document before dumping an image containing stub functions.

4.0 Loading and case modes

Allegro CL supports both modes regarding case of letters in symbols naming Common Lisp objects: a case-insensitive mode where foo, FOO, foO, Foo, etc. all name the same symbol; and a case-sensitive mode where they all name different symbols. See case.htm for information on deciding upon, setting, and changing the case mode in Allegro CL. (Besides case-sensitivity, the mode also controls case preference, specifying the case of standard Common Lisp symbols, among other things, as described in case.htm.)

A problem with allowing different case modes is that a fasl file compiled in a an image using one mode will not behave as expected when loaded into an image. Consider for example the file containing two function definitions:

(in-package :cl-user)

(defun FOO (x) (+ 1 x))

(defun foo (y) (* 2 y))

In an ANSI-mode (case-insensitive) image, loading this file (as a source file) would result in one function definition, on the symbol FOO, which multiplied the argument by 2 and returned the result. In a modern-mode (case-sensitive) image, loading this file would result in two function definitions, one on FOO, and one on foo.

That problem (different behavior when the same source file is loaded into images using different modes) is, however, not surprising given the nature of case-sensitivity. Users working in different modes must manage the issue of symbols differing only in the case of the alphabetic letters in the name of the symbol.

A more serious problem occurs when dealing with compiled (fasl) files. If the file above is compiled in an ANSI-mode image, it will contain two (compiled) definitions of the function named by the symbol FOO. If the file is compiled in a modern-mode image, it will contain, again, two definitions: one on FOO, and one on foo. Now consider what happens when these fasl files are loaded. Let us consider all the cases (we are assuming the setting of convert-mixed-case-symbols is its initial value t, see below in this section for the behavior when the value is nil) :

Note the fourth case: when the file is compiled in ANSI-mode and loaded into modern-mode, the behavior is different from the source file being loaded into a modern-mode image. In all other cases, loading the source file and loading the compiled file produces the same behavior. Therefore, Allegro CL signals a continuable error with condition type excl:fasl-casemode-mismatch when an attempt is made to load a fasl file compiled in an ANSI-mode image into a modern-mode image:

; Fast loading x.fasl
Error: #p"x.fasl" was compiled in case-insensitive-upper mode.  
      Continuing to load this file may result in symbol-name mismatches.
 [condition type: fasl-casemode-mismatch]

Restart actions (select using :continue):
0: Continue loading x.fasl
1: retry the load of x.fasl
2: skip loading x.fasl
3: Return to Top Level (an "abort" restart)
4: Abort #<process Initial Lisp Listener>
[1] cl-user(2): 

The correct thing to do at this point is to recompile the source file in the modern-mode image (assuming that is possible). The results of choosing to continue (by, e.g. calling :continue) are undefined (but will not be untoward if in fact there are no name conflicts).

Note that the setting of convert-mixed-case-symbols does not affect compilation: all (unescaped) symbol names are converted to uppercase in ANSI-mode images during compilation. The setting does affect loading of fasl files, however. If the setting is nil (the initial setting is t), then the second case listed above:

produces the results: two definitions, one on FOO and one on |foo| (we are using escapes to indicate that the print name of the symbol is all lower case).

Copyright (c) 1998-2000, Franz Inc. Berkeley, CA., USA. All rights reserved. Created 2000.10.5.