Comment 5 for bug 1903413

I think that at this point, this issue kinda looks like a request for a MOP extension.

I am currently thinking of establishing and documenting some sort of protocol for classes that want to exhibit the behavior that is wanted in this case: to be creatable en masse and fully garbage-collectable, at the cost of not being listed in the direct subclass list of its superclass and not being able to participate in e.g. MOP:MAP-DEPENDENTS. (Let's name these transient classes for the time being.)

Such a protocol would indirectly require specifying all places that are allowed to hold a strong reference to the class metaobject. Classes that want to be transient can follow this protocol, e.g. by specializing on ADD-DIRECT-SUBCLASS and declining to CALL-NEXT-METHOD, therefore not creating a strong reference from its superclass to itself.

The implementation of this protocol would need to follow into the implementation internals, so e.g. classoids are collectable when the class that they point at becomes unreachable.

Short writeup from my point of view follows. (I'm not a SBCL wizard, so this is going to be painfully incomplete.

* Transient classes don't pollute the image upon being created and collected; therefore, the memory leak is plugged.

* All related storages of metametaobjects (e.g. classoids/wrappers case of SBCL) would need to become weak, so they don't get in the way when the strong references to class objects are freed.
* New unit/regression tests.


> 2. it is virtually impossible to guarantee that something in the MOP has not put your object into a cache of some kind, especially as it is a metaobject. If make-instance on all metaobjects were forced to completely flush all caches in the system, maybe there would be a chance of "fixing" this issue.

I wonder if it should be MAKE-INSTANCE in this case; this seems expensive to flush the caches every time an instance is created.

Maybe there should be a separate function for flushing these caches, e.g. SB-PCL:FLUSH-MOP-CACHES, optionally invokable via the SB-EXT:GC interface by another keyword argument. Applications that would create tons of transient classes are also likely to call GC frequently; at this point, they would be able to also request the MOP caches to be flushed.

This seems feasible because it seems that class creation is usually tied to compilation and/or recompilation in the two concrete use cases I've seen (mfiano's game engine with live code reloading and pve's Smalltalk implementation in Common Lisp). This means that the warm-up costs of regenerating these caches will only need to be paid once after the flushing, and not during runtime of the game engine or generated Smalltalk programs.