Eliot Miranda uploaded a new version of Cog to project VM Maker: http://source.squeak.org/VMMaker/Cog-eem.155.mcz
==================== Summary ====================
Name: Cog-eem.155 Author: eem Time: 31 May 2014, 8:06:54.424 am UUID: 64eb21e0-b04d-428e-8d2f-5fc5c71f61b5 Ancestors: Cog-tpr.154
Add Spur method prototypes for ClassBuilder>>update:to: & ClassDescription>>updateMethodBindingsTo:
Go some small way towards fixing the bootstrap now that pig compact does the business (no chunks left to create a snapshot full of segments).
=============== Diff against Cog-tpr.154 ===============
Item was added: + ----- Method: SpurBootstrap class>>ClassBuilderPROTOTYPEupdate:to: (in category 'method prototypes') ----- + ClassBuilderPROTOTYPEupdate: oldClass to: newClass + "Convert oldClass, all its instances and possibly its meta class into newClass, + instances of newClass and possibly its meta class. The process is surprisingly + simple in its implementation and surprisingly complex in its nuances and potentially + bad side effects. + We can rely on two assumptions (which are critical): + #1: The method #updateInstancesFrom: will not create any lasting pointers to + 'old' instances ('old' is quote on quote since #updateInstancesFrom: will do + a become of the old vs. the new instances and therefore it will not create + pointers to *new* instances before the #become: which are *old* afterwards) + #2: The non-preemptive execution of the critical piece of code guarantees that + nobody can get a hold by 'other means' (such as process interruption and + reflection) on the old instances. + Given the above two, we know that after #updateInstancesFrom: there are no pointers + to any old instances. After the forwarding become there will be no pointers to the old + class or meta class either. + Andreas Raab, 2/27/2003 23:42" + | meta | + meta := oldClass isMeta. + "Note: Everything from here on will run without the ability to get interrupted + to prevent any other process to create new instances of the old class." + ["Note: The following removal may look somewhat obscure and needs an explanation. + When we mutate the class hierarchy we create new classes for any existing subclass. + So it may look as if we don't have to remove the old class from its superclass. However, + at the top of the hierarchy (the first class we reshape) that superclass itself is not newly + created so therefore it will hold both the oldClass and newClass in its (obsolete or not) + subclasses. Since the #become: below will transparently replace the pointers to oldClass + with newClass the superclass would have newClass in its subclasses TWICE. With rather + unclear effects if we consider that we may convert the meta-class hierarchy itself (which + is derived from the non-meta class hierarchy). + Due to this problem ALL classes are removed from their superclass just prior to converting + them. Here, breaking the superclass/subclass invariant really doesn't matter since we will + effectively remove the oldClass (becomeForward:) just a few lines below." + + oldClass superclass removeSubclass: oldClass. + oldClass superclass removeObsoleteSubclass: oldClass. + + "make sure that the VM cache is clean" + oldClass methodDict do: [:cm | cm flushCache]. + + "Convert the instances of oldClass into instances of newClass" + newClass updateInstancesFrom: oldClass. + + meta + ifTrue: + [oldClass becomeForward: newClass. + oldClass updateMethodBindingsTo: oldClass binding] + ifFalse: + [{oldClass. oldClass class} elementsForwardIdentityTo: {newClass. newClass class}. + oldClass updateMethodBindingsTo: oldClass binding. + oldClass class updateMethodBindingsTo: oldClass class binding]. + + "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."] + valueUnpreemptively!
Item was added: + ----- Method: SpurBootstrap class>>ClassDescriptionPROTOTYPEupdateMethodBindingsTo: (in category 'method prototypes') ----- + ClassDescriptionPROTOTYPEupdateMethodBindingsTo: aBinding + "ClassBuilder support for maintaining valid method bindings." + methodDict do: [:method| method methodClassAssociation: aBinding]!
Item was changed: ----- Method: SpurBootstrap>>on: (in category 'initialize-release') ----- on: imageName StackInterpreter initializeWithOptions: Dictionary new. + (oldInterpreter := StackInterpreterSimulator new) + openOn: imageName extraMemory: 0; + assertValidExecutionPointersAtEachStep: false. - oldInterpreter := StackInterpreterSimulator new. - oldInterpreter openOn: imageName extraMemory: 0. oldHeap := oldInterpreter objectMemory. newHeap := Spur32BitMMLESimulator new. newHeap allocateMemoryOfSize: (oldHeap youngStart * 3 / 2 roundUpTo: 1024 * 1024) newSpaceSize: 2 * 1024 * 1024 stackSize: 1024 * 1024 codeSize: 0. newHeap setCheckForLeaks: 15 - 6. "don't check become; or newSpace; soooo many rehashes in bootstrap" newHeap bootstrapping: true. self initMaps!
Item was changed: ----- Method: SpurBootstrap>>writeSnapshot:ofTransformedImage:headerFlags:screenSize: (in category 'testing') ----- writeSnapshot: imageFileName ofTransformedImage: spurHeap headerFlags: headerFlags screenSize: screenSizeInteger "The bootstrapped image typically contains a few big free chunks and one huge free chunk. Test snapshot writing and loading by turning the largest non-huge chunks into segment bridges and saving." | penultimate ultimate sizes counts barriers sim | sim := StackInterpreterSimulator onObjectMemory: spurHeap. sim bootstrapping: true. spurHeap coInterpreter: sim. sim initializeInterpreter: 0; setImageHeaderFlagsFrom: headerFlags; setDisplayForm: (Form extent: screenSizeInteger >> 16 @ (screenSizeInteger bitAnd: 16rFFFF)). spurHeap allOldSpaceEntitiesDo: [:e| penultimate := ultimate. ultimate := e]. self assert: (spurHeap isFreeObject: penultimate). self assert: (spurHeap isSegmentBridge: ultimate). sizes := Bag new. spurHeap allObjectsInFreeTree: (spurHeap freeLists at: 0) do: [:f| sizes add: (spurHeap bytesInObject: f)]. counts := sizes sortedCounts. self assert: counts last key = 1. "1 huge chunk" counts size > 1 ifTrue: [self assert: ((counts at: counts size - 1) key > 2 and: [(counts at: counts size - 1) value > 1024]). barriers := (1 to: (counts at: counts size - 1) key) collect: [:ign| spurHeap allocateOldSpaceChunkOfExactlyBytes: (counts at: counts size - 1) value]. barriers := barriers, {spurHeap allocateOldSpaceChunkOfExactlyBytes: (spurHeap bytesInObject: penultimate)}] ifFalse: [barriers := {spurHeap allocateOldSpaceChunkOfExactlyBytes: (spurHeap bytesInObject: penultimate)}]. + barriers last ifNotNil: + [:end| + spurHeap setEndOfMemory: end. + spurHeap allOldSpaceEntitiesDo: [:e| penultimate := ultimate. ultimate := e]. + self assert: (spurHeap addressAfter: ultimate) = end]. - spurHeap setEndOfMemory: barriers last. - spurHeap allOldSpaceEntitiesDo: [:e| penultimate := ultimate. ultimate := e]. - self assert: (spurHeap addressAfter: ultimate) = barriers last. spurHeap checkFreeSpace. spurHeap runLeakCheckerForFullGC: true. spurHeap segmentManager initializeFromFreeChunks: (barriers sort collect: [:b| spurHeap objectStartingAt: b]). spurHeap checkFreeSpace. spurHeap runLeakCheckerForFullGC: true. sim bereaveAllMarriedContextsForSnapshotFlushingExternalPrimitivesIf: true. sim imageName: imageFileName. sim writeImageFileIO!
vm-dev@lists.squeakfoundation.org