Ideas on how to improve function call. It would be nice to have function call be just a jal to the correct address. But for this to work, two additional things have to happen: - GC needs to know about and be able to find these instructions so it can fix them up just like any other pointer. - When a function name is redefined (i.e. the fdefn-function is changed), all refereces to the old definition have to be fixed to point to the new definition. Note: nothing special needs to happen with respect to the return address. The JAL will put it in LIP which {xep-,}allocate-frame can convert into the tagged object. The JAL instruction should be aligned such that the LRA header is a constant offset from the resultant LIP so the LRA pointer can be computed with one instruction. Fixing GC is easy: just include with each code component the offset of each call site and the offset in the constants pool for the fdefn object refered to by that call site. When scavenging a code component, use this information to fix each call site. Actually, it's easier then that. Use a Large-Object-Space to hold all code objects. Then they don't move. So you don't need to find any of the references. Also, you don't have to fix up any return pcs. The redefinition issue is much harder. Basically, there are three different ways to approach it: - When you redefine a name, put some trampoline code in the old definition that jumps to the new definition. The next time the garbage collector runs, it will remove the indirection. - When you redefine a name, search through the heap for code objects that refer to that fdefn object in their constants pool. - For each fdefn object, record a chain of all code components that use it. You have to include some kind of weak pointer technology to keep this from keeping dead code objects alive. First, lets consider the trampoline option. Unfortunately, this option has one very serious drawback. Specifically, you have to destroy the old definition. If someone has previously called FDEFINITION and plans on funcalling it later, then you loose big. If you try to do something like have ``named'' and ``unnamed'' entry points, and only trash the named entry, then you loose if someone uses (SETF FDEFINITION) to establish some other name for this function. Again, you can throw additional hacks at the issue, and do something like only use the ``named'' entry for the ``primary'' name for a function. But why? Something this compilicated is just asking for problems. A slight variant of the trampoline option would be to continue to indirect through the fdefn object every invocation. Part of the fdefn object could be code to jump to the actual function. Call-sites would just be a direct jump to the fdefn object. So instead of indirecting twice and then jumping, you would indirect onces via a jump and then jump again. Better than what we currently have, reasonably easy to impliment, but not really all that much of an improvement. The search-the-heap option has definate promise in conjunction with a generational garbage collector. This domain of the search can be narrowed by noting that no code objects can refer to ``younger'' fdefn objects, and hence you only need to search the generation of the fdefn object and younger ones. By caching the results of the search on a per-generation basis, you can easily cut down the amount of searching you have to do for the normal case. The most common case of redefinition is probably going to be Joe Random User trying to debug their piece of code. By noting that the fdefn object being changed is rather young, the system could tell that it doesn't have to search though all the pre-loaded portions of the core because they will have been purified into older generations. But it will still work if someone redefines an internal routine, it will just be rather slow. Each time a generation is flipped, the information for that generation is flushed. This way, references to call sites in garbage code objects are not kept around, so nothing special needs to happen to finalise them. With an explicit where-called database, it's trivial to fix the references to a name when it is redefined. The hassel comes with maintaining the database. Whenever a code component is created, entries for all of it's call sites have to be made even if this component is just going to be executed once and then then thrown away (e.g. a top level form). Another possibility is to maintain a complete where-called database for all real generations, and just search the ephemeral regions. If it turns out that searching the heap is taking too much time, this might turn out to be a reasonable compromise.