Ok, I'm confused about the comments in initialCleanup, since in testing with a Pharo image from feb it DOES call the flushExternalPrimitives, but the comments imply a 3.8 or later image shouldn't have the root bit set.
Also then the flushExternalPrimitiveOf: seems to be invoked by the snapshotCleanUp.
So is the comment in initialCleanup wrong?
Could in the Closure VM could we skip flushExternalPrimitives for the new image type, since we *know* any closure image would have been processed by snapshotCleanUp, versus being a 3.2 image?
initialCleanup "Images written by VMs earlier than 3.6/3.7 will wrongly have the root bit set on the active context. Besides clearing the root bit, we treat this as a marker that these images also lack a cleanup of external primitives (which has been introduced at the same time when the root bit problem was fixed). In this case, we merely flush them from here."
((self longAt: activeContext) bitAnd: RootBit) = 0 ifTrue:[^nil]. "root bit is clean" "Clean root bit of activeContext" self longAt: activeContext put: ((self longAt: activeContext) bitAnd: AllButRootBit). "Clean external primitives" self flushExternalPrimitives.
then
flushExternalPrimitives "Flush the references to external functions from plugin primitives. This will force a reload of those primitives when accessed next. Note: We must flush the method cache here so that any failed primitives are looked up again." | oop primIdx | oop := self firstObject. [self oop: oop isLessThan: endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [(self isCompiledMethod: oop) ifTrue: ["This is a compiled method" primIdx := self primitiveIndexOf: oop. primIdx = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oop]]]. oop := self objectAfter: oop]. self flushMethodCache. self flushObsoleteIndexedPrimitives. self flushExternalPrimitiveTable
snapshotCleanUp "Clean up right before saving an image, sweeping memory and: * nilling out all fields of contexts above the stack pointer. * flushing external primitives * clearing the root bit of any object in the root table " | oop header fmt sz | oop := self firstObject. [self oop: oop isLessThan: endOfMemory] whileTrue: [(self isFreeObject: oop) ifFalse: [header := self longAt: oop. fmt := header >> 8 bitAnd: 15. "Clean out context" (fmt = 3 and: [self isContextHeader: header]) ifTrue: [sz := self sizeBitsOf: oop. (self lastPointerOf: oop) + BytesPerWord to: sz - BaseHeaderSize by: BytesPerWord do: [:i | self longAt: oop + i put: nilObj]]. "Clean out external functions" fmt >= 12 ifTrue: ["This is a compiled method" (self primitiveIndexOf: oop) = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oop]]]. oop := self objectAfter: oop]. self clearRootsTable
-- = = = ======================================================================== John M. McIntosh johnmci@smalltalkconsulting.com Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ========================================================================