[squeak-dev] ClassBuilder update:to: broken with Spur (Eliot ?)

Stéphane Rollandin lecteur at zogotounga.net
Mon Feb 2 13:45:06 UTC 2015


Hello,

In order to load muO in the latest Spur image, I had to reintroduce the 
garbageCollect that has been deleted from method #update:to: in 
ClassBuilder.

There is a verbose discussion in both the previous and current 
implementations of this methods.

 From nice 3/10/2013, we read (talking about the Smalltalk 
garbageCollect bit):

	"Warning: Read this before you even think about removing the GC. Yes, 
it slows us down. Quite heavily if you have a large image. However, 
there's no good and simple alternative here, since unfortunately, 
#become: does change class pointers. What happens is that after the 
above become all of the instances of the old class will have a class 
pointer identifying them as instances of newClass. If we get our hands 
on any of these instances we will break immediately since their expected 
instance layout (that of its class, e.g., newClass) will not match their 
actual instance layout (that of oldClass). And getting your hands on any 
of those instances is really simple - just reshaping one class two times 
in rapid succession will do it. Reflection techniques, interrupts, etc. 
will only add to this problem. In the case of Metaclass things get even 
worse since when we recompile the entire class hierarchy we will 
recompile both, Metaclass and its instances (and some of its instances 
will have the old and some the new layout).

		The only easy solution to this problem would be to 'fix up' the class 
pointers of the old instances to point to the old class (using 
primitiveChangeClassTo:). But this won't work either - as we do a 
one-way become we would have to search the entire object memory for the 
oldClass and couldn't even clearly identify it unless we give it some 
'special token' which sounds quite error-prone. If you really need to 
get rid of the GC here are some alternatives:

		On the image level, one could create a copy of the oldClass before 
becoming it into the new class and, after becoming it, 'fix up' the old 
instances. That would certainly work but it sounds quite complex, as we 
need to make sure we're not breaking any of the superclass/subclass 
meta/non-meta class variants.

		Alternatively, fix up #becomeForward on the VM-level to 'dump the 
source objects' of #become. This would be quite doable (just 'convert' 
them into a well known special class such as bitmap) yet it has problems 
if (accidentally or not) one of the objects in #become: appears on 'both 
sides of the fence' (right now, this will work ... in a way ... even 
though the consequences are unclear).

		Another alternative is to provide a dedicated primitive for this 
(instead of using it implicitly in become) which would allow us to dump 
all the existing instances right here. This is equivalent to a more 
general primitiveChangeClassTo: and might be worthwhile but it would 
likely have to keep in mind the differences between bits and pointer 
thingies etc.

		Since all of the alternatives seem rather complex and magical compared 
to a straight-forward GC it seems best to stick with the GC solution for 
now. If someone has a real need to fix this problem, that person will 
likely be motivated enough to check out the alternatives. Personally I'd 
probably go for #1 (copy the old class and remap the instances to it) 
since it's a solution that could be easily reverted from within the 
image if there's any problem with it."


In the current version we read:

	"eem 5/31/2014 07:22 At this point there used to be a garbage collect 
whose purpose was to ensure no old instances existed after the 
becomeForward:.  Without the GC it was possible to resurrect old 
instances using e.g. allInstancesDo:.  This was because the 
becomeForward: updated references from the old objects to new objects 
but didn't destroy the old objects. But as of late 2013/early 2014 
becomeForward: has been modified to free all the old objects."


This latest statement may not hold true, since I could not load muO due 
to "Metaclasses can only have one instance" errors (originating in 
ClassDescription>>#updateInstances:from:isMeta:.


Stef



More information about the Squeak-dev mailing list