home *** CD-ROM | disk | FTP | other *** search
- @device[Postscript]
- @make[Article]
- @style[FontFamily "TimesRoman"]
- @pageheading[]
- @pagefooting[center "@value<page>"]
- @newpage(1)
- @begin[Center]
- @heading[CMU Common Lisp Memory Layout under New Type Scheme]
- @b[David B. McDonald]
- @value[Date]
- @end[Center]
-
- @section[Introduction]
-
- This document describes some ideas on how to layout memory under
- the new type scheme for CMU Common Lisp. There are many issues that are
- involved in this design. Each of the important issues that I have been
- able to identify is examined in a separate section. In each section two
- possible alternatives are proposed: one that assumes the default Unix
- 4.3BSD environment and one that assumes the significantly more advanced
- Mach environment. Throughout this document, I will use Unix to mean a
- non-Mach version of Unix, such as Berkeley 4.3BSD.
-
- Section @ref[differences] describes the features of current Unix and Mach
- systems that affect the design. Section @ref[layout] describes a possible
- memory layout scheme under both Unix and Mach. Section @ref[Stacks]
- describes how the stacks should be layed out. Section @ref[management]
- describes how memory could be allocated and managed with the new type
- scheme. Section @ref[garbage] describes how garbage collection could work
- under the new type scheme assuming a simple stop and copy garbage
- collector. Section @ref[genesis] describes how an initial kernel Lisp core
- file is generated. Section @ref[ccode] describes how C code should be
- loaded into a running Lisp. Section @ref[Purification] describes some idea
- on what the purification process should do to reduce the amount of work for
- the garbage collector. Section @ref[saving] describes how Lisp core files
- can be created so that the Lisp environment of a running process can be
- restored and run at a later time. Finally, section @ref[Summary]
- summarizes what I believe is a reasonable approach to memory layout with
- the new type scheme.
-
- @section[Mach vs. Unix]
- @label[Differences]
-
- Mach is a superset of Unix, so a design that relied on Mach without paying
- any attention to Unix would be more flexible and easier to implement.
- However, if CMU Common Lisp is going to run on non-Mach Unix systems, it is
- important to understand some of the short comings of these systems. In the
- following discussion, I am assuming a standard Unix 4.3BSD environment.
- Some vendor Unix systems, such as Dec's Ultrix or Sun's SunOs, may provide
- some or all of the features that make Mach a better operating to which to
- port Lisp. I don't have documentation on these, so don't know what if any
- features these systems support.
-
- The following features are important to the design:
- @begin[Description]
- text segment@\The text segment contains the code for a process. This
- segment normally starts at address #x0. This is true for Mach. The
- important aspect about the text segment is that it is shared amongst all
- the process running the same program. For Lisp, in a Unix environment,
- this means it is important to have as much of the Lisp code and read-only
- data in this segment as possible to allow sharing. This segment is
- protected read-only by the operating system -- writing to it is not allowed
- and will cause a segment violation. There is a separate part of an a.out
- file that contains the text segment.
-
- data segment@\The data segment contains the data for a process. This
- segment normally starts at the beginning of the page after the end of the
- text segment. On the IBM RT PC it starts at #x10000000 instead. An a.out
- file contains two pieces of information for the data segment. The first is
- the size of the initialized data which is contained in the a.out file so
- that the data segment is initialized properly. The second piece of
- information is the size of the uninitialized data which when a program is
- loaded immediately follows the initialized data and is initialized to zero.
-
- stack segment@\The stack segment contains the Unix user stack. This stack
- is normally near the high end of the address space and grows downwards
- toward the end of the data segment. An a.out files contains no
- information about the stack segment. Unix normally sets up the stack so
- that if it overflows, more memory is allocated automatically without the
- running process ever detecting anything. On the IBM RT PC, the stack
- segment starts at #xDFFFFFFC and grows downward.
-
- memory allocation@\Memory allocation is where Unix and Mach diverge. On a
- Unix system, it is only possible to allocate memory at the end of the data
- segment by using the brk system call. There are subroutine libraries built
- on top of this that provide more flexible allocation. The memory allocated
- is always writable and there is no provision made to set the protection of
- this memory to no access (useful for guard pages of stacks and generational
- garbage collection) or read-only (useful for generation garbage
- collection). Note that any call out to C code could cause memory to be
- allocated by the brk system call either directly or through the subroutine
- libraries (e.g., malloc and free).
-
- file mapping@\Unix does not currently provide any facility for mapping
- files into the address space of a process. A similar effect can be
- achieved by reading a file into memory. However, no sharing is possible as
- there is in Mach with its read-only or copy-on-write file mapping.
- @end[Description]
-
- A convenient memory layout for the new CMU Common Lisp implementation would
- use the standard a.out executable file format and the brk memory allocation
- calls. This would allow CMU Common Lisp to run on less advanced versions
- of Unix than Mach. However, the Mach memory allocation and file mapping
- calls provide a degree of flexibility that make using the standard Unix
- calls, as they currently exist, difficult at best. Some of the current
- Unix BSD documentation contains definitions of unimplemented system calls
- that provide appropriate memory primitives such as allocation, protection,
- and file mapping that would allow Lisp to run on non-Mach machines without
- as much trouble.
-
- @section[Basic Memory Layout]
- @label[layout]
-
- The basic memory layout, assuming an a.out file format for Lisp save files
- follows (a similar layout could be used for Mach, although this is not
- necessary):
- @begin[Verbatim]
- +-------------------------------------------------------+
- | C start up code |
- +-------------------------------------------------------+
- | Lisp Miscops (Lisp assembler) |
- +-------------------------------------------------------+
- | Lisp read only data |
- +-------------------------------------------------------+
- | Gap 1 |
- +-------------------------------------------------------+
- | C data |
- +-------------------------------------------------------+
- | Miscop data |
- +-------------------------------------------------------+
- | Lisp static data |
- +-------------------------------------------------------+
- | Gap 2 |
- +-------------------------------------------------------+
- | Lisp dynamic 0 data |
- +-------------------------------------------------------+
- | Lisp dynamic 1 data |
- +-------------------------------------------------------+
- | Gap 3 |
- +-------------------------------------------------------+
- | C stack |
- +-------------------------------------------------------+
- @end[Verbatim]
-
- The meaning of the above areas and what they contain is as follows:
- @begin[Description]
- C Start Up Code@\This area would correspond to the current lisp start up
- code. It would gain control from the operating system when lisp is run,
- pass in the environment and command line switches to Lisp, pick up
- the Lisp starting point from a known location and jump into Lisp code.
- This code would include the socket.o file that is necessary to open a
- connection to the X11 server.
-
- Lisp Miscops@\This area would contain all the Lisp miscops including
- assembler routines and compiled miscops (e.g., bignum code).
-
- Lisp Read Only Data@\This area would contain all the data in the default
- Lisp process that is read-only. This would include the combined
- function/code objects, documentation strings, symbol names, etc. that
- should never be modified.
-
- Gap 1@\There may be a region of memory between the end of the Lisp read
- only data and the beginning of C data. On the IBM RT PC, there
- is a gap since C code would start at #x0 and C data would start
- at #x10000000. On the Sun there isn't this separation between C code
- and data, so there may be no gap at all. The advantage of having a gap is
- that during the purification/save process for non system cores, read-only
- data could be moved into the Lisp read only area.
-
- C Data@\This area contains the C data from the Lisp start up code.
-
- Miscop Data@\This area contains any data areas the Lisp miscops need. For
- example, allocation information should be accessible from miscops.
- Allowing for miscop data requires enhancing the assembler to allow for
- resolving these addresses at miscop load time. The current miscops use a
- fixed location in memory to hold any data they need. This scheme is
- inappropriate on non Mach operating systems.
-
- Lisp Static Data@\This area contains all the Lisp data from the default
- Lisp process that must be writable. This would include symbols, strings
- that are used as buffers, arrays, vectors, etc. In user saved Lisp
- files, this area should also include any C or foreign code loaded into Lisp.
-
- Gap 2@\A relatively small gap should exist, so that it is possible to
- allocate more data to static space without having to move dynamic space
- around.
-
- Lisp Dynamic 0 Data@\This area is where Lisp starts allocating new dynamic
- objects when it first starts. A saved Lisp file may contain some initial
- data in this area.
-
- Lisp Dynamic 1 Data@\The first GC will copy objects from the Lisp dynamic 0
- data area to here and then flip back and forth between these two areas.
-
- Gap 3@\For both Mach and Unix, there will be a gap between the end of
- dynamic space and the C stack.
-
- C Stack@\The C stack contains control information for the C start up code,
- including environment information and command line switches.
- @end[Description]
-
- The important thing to notice about the above layout is that it is possible
- to use the Unix a.out file format to represent a Lisp save file. This is
- not important under Mach since file mapping is available and the various
- areas could lie anywhere in memory. However, on non-Mach systems there is
- far less flexibility on where these areas can be located.
-
- The addresses, at which each of the areas described above start, depend on the
- particular machine and operating system. For example, on the IBM RT PC the
- C Start Up code starts at #x0, the Lisp Miscops would immediately follow,
- and then the Lisp Read Only Data. In Unix terminology these three areas
- would correspond to the text segment of an a.out file. This means they
- would be shared among all the processes running Lisp even on non Mach
- machines. The C Data starts at #x10000000, miscop data and the Lisp static
- data would immediately follow. In Unix terminology, this would correspond
- to the initialized data segment. The Lisp Dynamic 0 and 1 data areas
- should be allocated after this area. Note that if there is any dynamic
- data in the Lisp save file, it would follow the Lisp static area and be
- part of the initialized data segment. A gap of several pages should be
- left free between static and dynamic 0 data to allow static data to grow
- without causing a major garbage collection.
-
- Note that nothing has been said about the location of the Lisp stacks. The
- following section describes stacks in more detail. The location of these
- stacks depend on whether Mach or Unix semantics are used.
-
- @section[Stacks]
- @label[Stacks]
-
- The new implementation of CMU Common Lisp appears to require the use of
- three stacks:
- @begin[description]
- control stack@\The control stack contains information about the flow
- of control of a Lisp computation. This would include information about
- catch points for non-local exits, save areas for registers that must be
- preserved across function boundaries (including return points), and local
- variables that do not fit into registers. The control stack must contain
- only Lisp objects since it must be scanned by the garbage collector.
-
- binding stack@\The binding stack contains binding information for special
- variables. As a computation progresses, special symbols and their old
- values are stored on this stack as these variables are bound. As a
- computation unwinds, this information is used to restore the old value to
- the symbol. The binding stack must contain only lisp objects since it must
- be scanned by the garbage collector.
-
- non-lisp (or number) stack@\The non-lisp stack contains thirty-two bit
- objects that must never be processed by the garbage collector. This stack
- is necessary to allow writing portable number code in Lisp. I strongly
- recommend that the standard Unix stack be used for this purpose. This has
- no disadvantages that I can think of other than reserving the standard C
- register for this stack which on machines with thirty-two registers is not
- a problem. It has the advantage that system calls, calling out to C
- routines, and interrupt processing will be easier and more efficient.
- Also, in some Unix versions, the register containing the stack is treated
- specially and Lisp using it for something else may be dangerous.
- @end[Description]
-
- There is one important consideration in the design of where these various
- stacks are located in memory. Pointers into any of the above three stacks
- will look like fixnums to the system, so it will be difficult to move the
- stacks around once they have been allocated. I believe there are two main
- avenues to follow here depending on whether Mach features are used or only
- those available in standard Unix.
-
- Using Mach features, I believe the following stack scheme is the correct
- way to go. I am going to use stack locations that make sense for the IBM
- RT PC version of Mach. Other versions of Mach may use slightly different
- locations.
- @begin[Description]
- control stack@\The control stack should start at location #xBFFFFFFC and
- grow downward.
-
- binding stack@\The binding stack should start at location #xCFFFFFFC and
- grow downward.
-
- non-lisp stack@\The non-lisp or number stack should be the Unix stack and
- starts at #XDFFFFFFC and grows downward.
- @end[Description]
- The advantage of this scheme is the stacks are separate so the GC needs no
- knowledge about the structure of the stacks. Also, they are at fixed
- locations and it is easy to restore a saved Lisp using the Mach map_fd call.
- Each stack can be up to 256 megabytes before overflow occurs. This should
- be large enough for some time to come. The control stack could actually
- grow bigger since it has only have dynamic memory below it and they will be
- separated by a large amount of space. Interrupt handling should be fairly
- straight forward since the initial interrupt information could automatically be
- stored on the Unix stack. An interrupt stack frame will be created on the
- Lisp control stack and any information that is necessary for Lisp can be
- copied from the Unix stack to the Lisp control stack.
-
- For Unix, there are a couple of possible solutions to the stack problem. One
- solution is to put the control and binding stacks before or after static
- space. These stacks would be of fixed size and could not grow since it
- would be hard to move them because stack pointers would be difficult to
- find. To increase the size of the stacks, it would be necessary to rebuild
- the system. Also, the entirety of both stacks would have to be saved in a
- Lisp save file no matter if only one page was in use.
-
- Another solution is to combine all of the stacks. This is probably the
- correct solution for Unix, but introduces significant complexities. Each
- Lisp stack frame would have to have enough information so that the Garbage
- collector could parse the frame. In particular, each frame would need to
- be divided into non-Lisp space and Lisp only space. Also, it would have to
- have a pointer to the previous active frame on the stack. Any stack
- information outside of a stack frame would be ignored by the garbage
- collector. A stack frame needs to specify which locations contain non-Lisp
- data and which contain Lisp data. The active frame pointer can be used to
- chase down the stack frames and GC the objects in the Lisp parts of each
- frame. This means the active frame pointer must always be valid when a GC
- occurs. Open but not active frames would be part of the frame for the
- function building the open frame. One problem is dealing with an arbitrary
- number of multiple values coming back from a function. If these come back
- on the stack, the Lisp/non-lisp information may need to be updated by the
- multiple-value return mechanism to make sure everything is in a legal
- state. The binding stack would use a mechanism similar to unwind-protect
- to restore old symbol values. Call out to C should be handled by using a
- frame on the stack that is outside the caller's stack frame and thus not
- part of the frame -- GC will ignore it. Interrupts can be handled in one
- of two ways:
- @begin[Itemize]
- An interrupt frame will be created on the stack and an interrupt handler
- called. While interrupts are disabled, the interrupt handler would be
- responsible for cleaning up the stack to make sure that it is consistent.
- It should copy the interrupt information that the Lisp interrupt processor
- needs and return from the interrupt causing control to pass to the real
- interrupt handler that can set up a legal Lisp frame (interrupts must still
- be disabled at this point).
-
- Have a separate interrupt stack as is done in the current system. A fixed
- location before or after the static region would be a likely candidate for
- this.
- @end[Itemize]
- Saving the stack could be done by copying the contents into the a.out file
- just after the static space area. On restoring the file, it would be
- necessary to copy this information into the Unix stack (normally this will
- be a couple of pages).
-
- @section[Memory Management]
- @label[management]
-
- Under Mach, using vm_allocate and vm_deallocate to allocate and free memory
- used for dynamic space is a big advantage. Lisp doesn't have to
- worry about where this memory is and new dynamic space will be zero-fill
- pages. This is much more efficient than under Unix where the new dynamic
- space (after the first GC) will contain old garbage and has to be paged in
- from disk. Under Mach, even if brk memory allocation is used, it will be
- wise to vm_deallocate and vm_allocate old space so that they are zero fill
- pages.
-
- Under Unix, when Lisp starts up it must use the brk system call to allocate
- a chunk of memory, half of which will be used for dynamic 0; the other half
- for dynamic 1. The amount of space actually allocated should be specified
- by a command line switch. If dynamic memory usage grows sufficiently to
- require more memory to allocate, it will be necessary to allocate more
- memory to both dynamic spaces. However, it is not possible to guarantee
- that the new memory allocated will be contiguous with the top of dynamic 1
- because C routines that have been called may have called the brk system
- call or more likely used a library call to allocate more memory.
-
- It is convenient for the two dynamic memory areas to be the same size and
- each one to be contiguous. However, since under Unix there is no way to
- guarantee that the memory allocated with brk will be contiguous, a scheme
- that allows Lisp and non-Lisp memory to be intermingled may be necessary. A
- possible scheme is to have chunks of memory of some fixed size (e.g., 64K
- or 128K bytes) and do allocation in terms of these. This means the garbage
- collector and variable length allocation routines become more complicated.
- When one region of memory is exhausted there may be another that should be
- used.
-
- Another possibility is to allow memory to expand only once effectively
- doubling the size of each dynamic space. This could be done by combining
- the original dynamic 0 and dynamic 1 space into dynamic 0 space and
- allocating a chunk of memory of the same size. Note a check could be made
- to see if the new memory will be contiguous and then Lisp could grow more
- slowly with doubling used as a last resort. It is also possible for Lisp
- to provide its own version of the C allocation calls. The only problem
- with this is that a C or assembler program could invoke the brk system call
- directly without going through the normal library routines.
-
-
- @section[Garbage Collection]
- @label[garbage]
-
- Garbage collecting should be fairly straight forward. With two dynamic
- spaces, it is necessary only to copy the accessible objects from old
- dynamic space to new dynamic space.
-
- Under Mach, when a GC is triggered, the following should be done:
- @begin[Enumerate]
- Use vm_allocate to allocate at least as much space as is currently being
- used by the old dynamic space. The amount allocated could be increased
- some if a lot of data was kept the last time a GC was performed.
-
- Scan the roots of Lisp moving any Lisp objects from old dynamic space to
- new dynamic space leaving GC forward pointers behind.. The roots of Lisp
- would include the Lisp registers, control and binding stack, and static
- space.
-
- Scavenge new dynamic space. That is, all the objects in new dynamic space
- that contain Lisp object must be scanned for pointers into old space. All
- accessible objects in old space must be transported to new space.
-
- Use vm_deallocate to deallocate the old dynamic space, since it is no
- longer in use.
- @end[Enumerate]
- The above GC algorithm should work well under Mach. There only needs to be
- a free pointer (the first free location in new dynamic space) and an end
- pointer (the first location that is unusable). On a machine with 32
- registers, these might as well be in registers. On other machines, leaving
- these in memory is probably best.
-
- Under Unix, a similar algorithm could be used, but if new dynamic space is
- not contiguous because of C allocation problems, GC will have to be more
- complicated. It may have to allocate large objects in a different area
- than the current allocation area.
-
- @section[Genesis]
- @label[genesis]
-
- There are two options with genesis. If the a.out file format is used for
- Lisp save files as it should if only Unix features are used, then Genesis
- will have to be modified heavily. If Mach memory allocation and file
- mapping features are used, the the current Genesis can be used without too
- much modification. Although, it would make sense to have a way for data
- areas used by the miscops to be allocated at miscop load time and any
- references to these areas be resolved by genesis rather than using fixed
- memory location as is currently done.
-
- If the Unix a.out format is used, Genesis must be modified to generate an
- a.out executable file rather than the current Lisp core file format. I do
- not believe that this is difficult. To use the a.out format, the following
- sequence of operations need to be performed:
- @begin[Enumerate]
- Read the C start up file object code and allocate space for it at the front
- of what will become the text segment. Allocate space for the C data at the
- start of what will be come the data segment. Note: On the IBM RT PC this
- is straight forward and can be done easily from the executable file created
- by ld, since text starts at #x0 and data starts at #x10000000. On other
- machines it will be necessary to make sure that the data segment starts at
- a location high enough to allow space for all the Lisp read-only data.
- This may be done using ld switches or by having a small assembler language
- routine that allocates a few megabytes of space in the text segment.
-
- Read the Lisp miscop files and place them in the text segment after the C
- code. Note that some of the current miscops need to access fixed memory
- locations. A more ambitious scheme would allow the assembler to define
- data areas for the miscops that need data. The allocation tables needed by
- Lisp are an example where this is would be useful. If this scheme is
- adopted, these data structures would be allocated after the C data.
-
- The Lisp files needed to run a kernel core should now be loaded. All
- code/function objects should be allocated in the text segment. All other
- objects should be loaded in the data segment. This is not an optimal
- arrangement. Certain strings (e.g., documentation strings and symbol
- names) and other constants should also be put in the text segment. This
- requires the compiler to generate information so that the cold loader knows
- what objects are read-only.
-
- Write out an a.out file with the new text and data segments created by the
- above process. Also the symbol table information contained in the original
- C start up code for Lisp should be copied to this file so that loading of
- foreign functions can use this symbol table information.
- @end[Enumerate]
-
- @section[Loading C code]
- @label[ccode]
-
- Loading C code should be relatively simple. As is currently done, it will
- be necessary to run ld with the appropriate switches to generate an
- incremental load file using the lisp executable file as the base (or the
- most recent intermediate file created by a previous load of foreign code in
- the currently running Lisp). This incremental load file should be linked
- so that it will be placed at the end of the current lisp static area.
-
- A problem that may occur here is that the space between the end of the
- current static area and the beginning of dynamic 0 space is too small for
- the resulting object file. In this case, it is necessary to perform a
- garbage collection so that more space can be allocated to static space from
- dynamic 0 space.
-
- @section[Purification]
- @label[purification]
-
- Purification should not be as necessary in the new system as it was in the
- old. With all the functions in a file contained in one combined
- function/code object, the function object and code vector will always be
- near one another. The important thing to do with purification is to make
- sure that all the constants pointed at by a function/code object be near
- it. The only things that may cause problems are symbols, because other
- constants should be near the function/code object since they are
- loaded at the same time. Also, some function/code objects should be near
- one another if they share a large number of constants. Initially,
- I don't think it is necessary to implement purification. At some time in
- the future purification should be combined with the save Lisp process so
- that the Lisp save file has somewhat better locality than it would
- otherwise.
-
- In the future the purification process should be done while a Lisp core
- file is being saved. This will allow the system to write out either an
- a.out file format or the current Lisp core file format file in which
- everything may have been relocated to reduce the amount of paging.
- Purification should effectively do a complete GC of read-only, static, and
- dynamic space relocating everything into read-only and static space with
- all objects relocated so that function/code objects that call one another
- or share many constants are near one another. The information necessary to
- do this can be retrieved from the function/code objects. The number of
- references to an object from a function/code object could be obtained, but
- it probably isn't worth the effort. Using the reference information, a
- better ordering of all Lisp objects could be made.
-
- @section[Saving Lisp Cores]
- @label[saving]
-
- There are two options for saving a Lisp core file. One is to use the a.out
- format which would be the preferred method if Unix is to be supported.
- Under Mach, retaining the current (or similar) format has some advantages.
- In particular, all the memory allocation and stack problems are no longer
- something to worry about. The current save miscop should be rewritten in
- Lisp for portability reasons.
-
- The save process under Unix should use the a.out file format and
- effectively do purification while creating the file. The Unix manuals
- contain a description of a.out file format. In the following, I am
- assuming that all three stacks have been combined into one and the standard
- Unix stack is being used for this combined stack. To create a Lisp a.out file,
- the following steps are necessary:
- @begin[Enumerate]
- If Lisp is currently allocating space in the dynamic 0 area, a normal GC
- should be performed to move all the data into dynamic 1 space.
-
- If there is a gap between the text and data segments as on the IBM RT PC,
- allocate space to hold the new read-only data area in the text area. On
- machines without this gap, read-only data must be placed in the static
- area. All references to read-only below assume this.
-
- Do a purifying GC in which objects are moved into the new read-only area
- and to the end of the current static area. The static area will grow and
- either more memory must be allocated to dynamic space or the size of the
- dynamic areas must be adjusted appropriately after this purifying GC has
- finished.
-
- The Lisp is now ready to be saved. First the header page must be written
- out. This header page includes a magic number that says this is an a.out
- file. It also includes the size of the text segment (read-only data), the
- size of the initialized data segment (static data plus amount of stack that
- must be saved), the size of the symbol table, and the size of the string
- table must be written. The size of the uninitialized data segment should
- be 0.
-
- The text (read-only data) segment must be written. It must be rounded
- off to a page boundary.
-
- The initialized data (static data) segment must be written. The part of
- the stack that Lisp needs to run must also be written to the file now.
- This segment also must be rounded off to a page boundary.
-
- The symbol table and string table information from the original Lisp a.out
- file or the last intermediate a.out file created by loading C code must be
- copied to the file.
- @end[Enumerate]
- At this point, a new a.out file should have been created. This file should
- be made executable and it should be possible to run and have Lisp restart.
-
- One important thing to notice is that when the saved Lisp file starts
- executing, it must copy the stack information out of the initialized data
- segment into the proper place on the Unix stack. This should not be
- difficult, but may require someone to write some assembly code to do this.
- Note that the restarted Lisp should make sure the stack is in the location
- it expects -- otherwise the OS has changed out form underneath it and it
- will be necessary to recreate the saved file on the new version of the
- operating system.
-
- @section[Summary]
- @label[Summary]
-
- I have tried to give a brief summary of how memory should be layed out under
- two assumptions: one using Mach virtual memory features and the other using
- standard Unix memory allocation. My belief at this point is that it would
- be nice to run in a standard Unix environment, but that it will complicate
- everything to such a degree that I don't think it is worth doing.
- When the system is running stably on a couple of machines, it might be
- worth spending the large amount of time necessary to come up with a good
- scheme for dealing with standard Unix (if you wait long enough maybe it
- will improve to the point that some of the serious problems are corrected).
-
- My recommendation would be to use Mach features and do the following:
- @begin[Itemize]
- Use the current core file format and the current Lisp start up code and map
- the various regions of memory Lisp uses into the process. Using the a.out
- file format would be convenient, but makes it difficult to have stacks out
- of the way.
-
- Use the Unix stack provided by Mach as the non-lisp or number stack. This
- means the compiler should specify that whatever register is used for this
- stack be used as the number stack register. This stack always grows
- downward.
-
- Keep the binding and control stacks separate and place them just below the
- Unix stack. On the IBM RT PC the Unix stack is in segment 13, the binding
- should be in segment 12, and the control stack in segment 11. These latter
- tow stacks should also grow downward.
-
- Vm_allocate the rest of whatever segment the C data is in. Load C code and
- user defined miscops into this area and move Lisp objects here during
- purification. If, as on the IBM RT PC, there are separate text and data
- segments, then read-only data could be moved into the text segment. This
- probably isn't worth worrying about.
-
- Dynamic space should be allocated using vm_allocate. When a GC occurs, new
- dynamic space should be vm_allocated at that time based on the size of the
- current dynamic space and how much space was retained during the previous
- GC. The initial amount of space allocated to dynamic space should be
- specified by a command line switch with a reasonable default value (such as
- 2 megabytes). Vm_deallocate the old dynamic space when the GC is finished.
- @end[Itemize]
-