Commits

Anonymous committed 9c71d03

Kludge to get over an optimization that's suspicious?

  • Participants
  • Parent commits c8a3b2b

Comments (0)

Files changed (1)

AtomicInstaller.ns3

-Newspeak3
+Newspeak3
+'Mirrors'
+class AtomicInstaller usingPlatform: platform = NewspeakObject (
+"Initial version of atomic install. This handles adding, removing and modifying stuff. 
 
-'Mirrors'
+What remains unaddressed is changing classes of individual objects, and changing superclasses of individual classes. These can of course be handled elsewhere, but not as part of a broader atomic transaction as is done here. The API of this class should be extended to deal with these requirements.
 
-
+The process of an atomic install is as follows:
 
-class AtomicInstaller usingPlatform: platform = NewspeakObject (
-"Initial version of atomic install. This handles adding, removing and modifying stuff. 
-
-What remains unaddressed is changing classes of individual objects, and changing superclasses of individual classes. These can of course be handled elsewhere, but not as part of a broader atomic transaction as is done here. The API of this class should be extended to deal with these requirements.
-
-The process of an atomic install is as follows:
-
-We construct a list of old objects, and another of revised objects.  These two lists parallel each other: the i'th element of the revised object list is the revised version of the i'th element in the old objects list. Eventually, we will do a one way become: of the old objects into the new ones.
-The list is populated with mixins, classes and instances that need to be modified.
-
-The input consists of a tuple of MixinReps, and a map containing any existing outermost mixins being processed . Each element in the tuple describes an ''outermost'' mixin and its nested mixins. By ''outermost mixin'' we mean a mixin that is not nested within any other mixin being processed at this time. It could be a top level mixin, but it could also be a nested mixin provided its enclosing mixins are not subject to change.
-
-We distinguish between new and existing mixins. We use the map in order to do this.  This is essential, since we cannot assume a global namespace in which to look up mixins to see if they exist or not. 
-
-New mixins are simply created per their description, recursively including their nested mixins. These new mixins are gathered in the newMixins array.
-
-If the mixin described by the MixinRep exists, we store the existing mixin in the old object array, and create a new one per the description. The new mixin is then placed in the revised objects array.  
-
-The recursive processing of each MixinRep yields a MixinList: a list of classes, the head of which corresponds to the outermost mixin described by the MixinRep, and the tail being a list of MixinLists corresponding the MixinReps of outermost mixin's nested mixins. This list is returned at the end.
-
-For each existing mixin, we also go through all its invocations. We note that the invocation is associated with a modified mixin by adding an entry to a map, definingMirrors, that maps classes to mirrors that describe their mixin. We also collect the invocation and all its subclasses  These are stored in a map called existingClasses, which maps  depth in the inheritance hierarchy to sets of existing classes classes at that depth. This gives us the set of existing classes that will require modification - either because their mixin has changed, or their superclass has changed. The data structure allows us to easily traverse the set of existing classes in order, base classes first.
-
-We then recursively process the nested mixins of each mixin being processed. Each nested mixin is processed with a namespace consisting of the nested mixins of its enclosing mixin (which allows us again to determine whether a mixin being described is new or pre-existing).
-
-Next, we go through the existing classes. For each class we produce a new class, which we store in a map, newClasses, keyed by the old class.  It is important not to use the class name as a key, as we cannot assume a global namespace in Newspeak.
-The new class may differ in its own structure (because its mixin differs) or only in having a revised superclass. 
-
-We also store the old class in the old objects array, and the new class in the revised objects array. Because we traverse the classes in increasing depth order we are assured that a class' superclass has either already been processed, and can be looked up in newClasses, or it has not changed. This is essential, because the new class points at its up-to-date superclass and uses data derived from it.
-
-If the layout of a class has changed, we also process all its instances. For each existing instance of an old class whose shape has changed, we create an instance of the new class, taking care to copy the data of fields shared between the old and new classes from the old instance to the new one. Each such processed object is placed in the old objects array, with the new version in the revised objects array.
-
-At this point, we can do the one way become:  and the installation is complete.
-
-One more detail: we track what mixins have been removed from existing mixins. We then make sure these mixins are removed from the subclasses array of ProtoObject (though this is not done atomically). Our goal is to ensure that the Class object level data structure is consistent at the end of the operation
-
-One concern is the involvement of this class with metadata issues such as the class organization. For new code,  AtomicInstaller produces an organization based on the information available in the mirrors provided.  For existing ones it copies the information that was already in place.  
-
-Now it seems that, ideally, a higher level layer should be dealing with this kind of metadata and AtomicInstaller should be completely oblivious to it.  Alas, it isn't quite so simple.
-
-The installer processes classes whose mixin has not been modified, it is important that it clones them in their entirety so that their organization does not get lost.  Higher level layers aren't in a good position to deal with these classes without replicating much of the installer's work.  
-
-Likewise, high level layers aren't really well situated to track down mixin applications of mixins that have been modified.  They only deal with the mixins themselves. However, the organization of a mixin invocation is a special object that actually bases its definitions on the organization of the defining class. So copying these is ok as well.
-
-In principle, metadata should be kept at the mixin level, and individual classes should just refer to their mixin for it. In that case, higher level mirrors could deal with the metadata, and the installer would not have to do anything at all about it  - neither for new or old code.
-In that scenario, even if a class has unique metadata, then it would only change of the class itself were changed individually (which amounts to changing its superclass) and then the higher layers would know about it and deal with it.
-
-Until that happy day, it looks like the installer has no choice but to take care of this. That is why low level squeak mirrors carry metadata such as category information with them, making it available to the installer. 
-
-What could be improved is the handling of new mixins. Higher level mirrors could take care of setting up the organization of these.  This is part of the pending overall mirror reform.  Then we could take #setOrganizationOfClass;BasedOn: out of AtomicInstaller, along with the import of ClassOrganizer.
-
-Copyright (c) 2009-2010 Gilad Bracha
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the ''Software''), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED ''AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE."
-|	"imports"
-	Map = platform Collections Dictionary.
-	List = platform Collections OrderedCollection.
-	Set = platform Collections Set.
-	ProtoObject = platform Kernel ProtoObject.
-	MethodDictionary = platform Kernel MethodDictionary.
-	Metaclass = platform Kernel Metaclass.
-	ClassOrganizer = platform Kernel ClassOrganizer.
-	SystemMetadata = platform NewsqueakMixins SystemMetadata.
-	DefiningClassMetadata = platform NewsqueakMixins DefiningClassMetadata.
-	Mixin = platform NewsqueakMixins Mixin.
-	MixinManager = platform NewsqueakMixins MixinManager.
-	NewspeakObject = platform NewspeakCore NewspeakObject.
-	vmmirror = platform NewspeakCore VMMirror new.
-	
-	"module variables"
-	newMixins <List[Mixin]>
-	revisedObjects <List[Object]>
-	oldObjects <List[Object]>
-	existingClasses <Map[Integer, Set[Class]]>
-	newClasses <Map[Class, Class]>
-	deletedClasses <List[Class]>
-	definingMirrors <Map[Class, LowLevelMixinMirror]> 
-|
-)
+We construct a list of old objects, and another of revised objects.  These two lists parallel each other: the i'th element of the revised object list is the revised version of the i'th element in the old objects list. Eventually, we will do a one way become: of the old objects into the new ones.
+The list is populated with mixins, classes and instances that need to be modified.
 
-(
+The input consists of a tuple of MixinReps, and a map containing any existing outermost mixins being processed . Each element in the tuple describes an ''outermost'' mixin and its nested mixins. By ''outermost mixin'' we mean a mixin that is not nested within any other mixin being processed at this time. It could be a top level mixin, but it could also be a nested mixin provided its enclosing mixins are not subject to change.
 
-
+We distinguish between new and existing mixins. We use the map in order to do this.  This is essential, since we cannot assume a global namespace in which to look up mixins to see if they exist or not. 
 
-class MixinList  head: hd <Class>  tail: tl <MixinList> = (
-"MxinList =  (Class, MixinList) | Nil."
-|
-	head <Class> = hd.
-	tail <MixinList> = tl.
-|
-)
+New mixins are simply created per their description, recursively including their nested mixins. These new mixins are gathered in the newMixins array.
 
-()'private'
+If the mixin described by the MixinRep exists, we store the existing mixin in the old object array, and create a new one per the description. The new mixin is then placed in the revised objects array.  
 
-adjust: newObj to: oldObj = (
+The recursive processing of each MixinRep yields a MixinList: a list of classes, the head of which corresponds to the outermost mixin described by the MixinRep, and the tail being a list of MixinLists corresponding the MixinReps of outermost mixin's nested mixins. This list is returned at the end.
 
-
+For each existing mixin, we also go through all its invocations. We note that the invocation is associated with a modified mixin by adding an entry to a map, definingMirrors, that maps classes to mirrors that describe their mixin. We also collect the invocation and all its subclasses  These are stored in a map called existingClasses, which maps  depth in the inheritance hierarchy to sets of existing classes classes at that depth. This gives us the set of existing classes that will require modification - either because their mixin has changed, or their superclass has changed. The data structure allows us to easily traverse the set of existing classes in order, base classes first.
 
-cleanup = (
+We then recursively process the nested mixins of each mixin being processed. Each nested mixin is processed with a namespace consisting of the nested mixins of its enclosing mixin (which allows us again to determine whether a mixin being described is new or pre-existing).
 
-
+Next, we go through the existing classes. For each class we produce a new class, which we store in a map, newClasses, keyed by the old class.  It is important not to use the class name as a key, as we cannot assume a global namespace in Newspeak.
+The new class may differ in its own structure (because its mixin differs) or only in having a revised superclass. 
 
-cloneClass: oldClass <Class> ^ <Class> = (
   	newMeta:: Metaclass new.
                 methodDictionary: oldClass class methodDictionary
                 format: oldClass class format.	
+We also store the old class in the old objects array, and the new class in the revised objects array. Because we traverse the classes in increasing depth order we are assured that a class' superclass has either already been processed, and can be looked up in newClasses, or it has not changed. This is essential, because the new class points at its up-to-date superclass and uses data derived from it.
 
-
+If the layout of a class has changed, we also process all its instances. For each existing instance of an old class whose shape has changed, we create an instance of the new class, taking care to copy the data of fields shared between the old and new classes from the old instance to the new one. Each such processed object is placed in the old objects array, with the new version in the revised objects array.
 
-depthFor: klass <Class> = (
+At this point, we can do the one way become:  and the installation is complete.
 
-
+One more detail: we track what mixins have been removed from existing mixins. We then make sure these mixins are removed from the subclasses array of ProtoObject (though this is not done atomically). Our goal is to ensure that the Class object level data structure is consistent at the end of the operation
 
-existingMixinFor: m <LowLevelMixinMirror> in: ns <Map[Symbol, Class]> ^ <Class | Nil> = (
+One concern is the involvement of this class with metadata issues such as the class organization. For new code,  AtomicInstaller produces an organization based on the information available in the mirrors provided.  For existing ones it copies the information that was already in place.  
 
-
+Now it seems that, ideally, a higher level layer should be dealing with this kind of metadata and AtomicInstaller should be completely oblivious to it.  Alas, it isn't quite so simple.
 
-install: newObjects <Array> insteadOf: old <Array>  = (
+The installer processes classes whose mixin has not been modified, it is important that it clones them in their entirety so that their organization does not get lost.  Higher level layers aren't in a good position to deal with these classes without replicating much of the installer's work.  
 
-
+Likewise, high level layers aren't really well situated to track down mixin applications of mixins that have been modified.  They only deal with the mixins themselves. However, the organization of a mixin invocation is a special object that actually bases its definitions on the organization of the defining class. So copying these is ok as well.
 
-installAll = (
+In principle, metadata should be kept at the mixin level, and individual classes should just refer to their mixin for it. In that case, higher level mirrors could deal with the metadata, and the installer would not have to do anything at all about it  - neither for new or old code.
+In that scenario, even if a class has unique metadata, then it would only change of the class itself were changed individually (which amounts to changing its superclass) and then the higher layers would know about it and deal with it.
 
-
+Until that happy day, it looks like the installer has no choice but to take care of this. That is why low level squeak mirrors carry metadata such as category information with them, making it available to the installer. 
 
-installNewMixins = (
+What could be improved is the handling of new mixins. Higher level mirrors could take care of setting up the organization of these.  This is part of the pending overall mirror reform.  Then we could take #setOrganizationOfClass;BasedOn: out of AtomicInstaller, along with the import of ClassOrganizer.
 
-
+Copyright (c) 2009-2010 Gilad Bracha
 
-layoutHasChangedBetween: oldClass <Class> and: newClass <Class> ^ <Boolean> = (
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the ''Software''), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
-methodDictionaryFor: c <Class> from: m <LowLevelMixinMirror> ^ <MethodDictionary> = (
+THE SOFTWARE IS PROVIDED ''AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE."|	"imports"
+	Map = platform Collections Dictionary.
+	List = platform Collections OrderedCollection.
+	Set = platform Collections Set.
+	ProtoObject = platform Kernel ProtoObject.
+	MethodDictionary = platform Kernel MethodDictionary.
+	Metaclass = platform Kernel Metaclass.
+	ClassOrganizer = platform Kernel ClassOrganizer.
+	SystemMetadata = platform NewsqueakMixins SystemMetadata.
+	DefiningClassMetadata = platform NewsqueakMixins DefiningClassMetadata.
+	Mixin = platform NewsqueakMixins Mixin.
+	MixinManager = platform NewsqueakMixins MixinManager.
+	NewspeakObject = platform NewspeakCore NewspeakObject.
+	vmmirror = platform NewspeakCore VMMirror new.
+	
+	"module variables"
+	newMixins <List[Mixin]>
+	revisedObjects <List[Object]>
+	oldObjects <List[Object]>
+	existingClasses <Map[Integer, Set[Class]]>
+	newClasses <Map[Class, Class]>
+	deletedClasses <List[Class]>
+	definingMirrors <Map[Class, LowLevelMixinMirror]> 
+|)
+(
+class MixinList head: hd <Class>  tail: tl <MixinList> = (
+"MxinList =  (Class, MixinList) | Nil."|
+	head <Class> = hd.
+	tail <MixinList> = tl.
+|)
+()'accessing'
+atomicallyInstallMixinReps: mixins <List[LowLevelMixinRep]> namespace: ns <Map[Symbol, Class]> ^ <List[MixinList]> = (
+"Install all elements of mixins, correctly modifying their applications and the subclasses thereof, and any metadata. Return a list of outermost  classes corresponding to said mixins and their nested classes recursively. In other words, we take a list of MixinReps and return a corresponding list of MixinLists, such that
 
-
+MixinList = {Class. List[MixinList]}
 
-mixinLayoutHasChangedBetween: oldMixin <Mixin> and: newMixin <Mixin> ^ <Boolean> = (
+Ergo, the outermost class whose mirror heads the rep is returned at the head of the corresponding list, and a list of mixin lists that matches the nested classes of said outermost class follows, echoing the structure of the incoming rep.
 
-
+ "
+	| results <List[MixinList]> |
+	setup.
+	results:: mixins collect:[:rep <LowLevelMixinRep> |  processOutermostRep: rep in: ns].
+	processExistingClasses.
+	installAll.
+	Object flushCache. "Clear all lookup caches"
+	removeDeletedClasses.
+	cleanup.
+	^results
+)'private'
+adjust: newObj to: oldObj = (
+	| newInstVarNames <Array[String]> oldInstVarNames <Array[String]> sharedInstVarNames <Array[String]> |
+	newInstVarNames:: newObj class allInstVarNames.
+	oldInstVarNames:: oldObj class allInstVarNames.
+	sharedInstVarNames:: oldInstVarNames select:[:n <String> | newInstVarNames includes: n ].
+	"find intersection of slots names between oldObj and newObj"
+	sharedInstVarNames do:[: n <String> | 
+		"for each slot in the intersection set newObj's value to that in oldObj"
+		| oldIndex newIndex val |
+		oldIndex:: oldInstVarNames indexOf: n.
+		newIndex:: newInstVarNames indexOf: n.
+		val:: vmmirror namedSlotOf: oldObj at: oldIndex ifFail: [halt].
+		vmmirror namedSlotOf: newObj at: newIndex put: val ifFail: [halt].
+	]. 
+)
+cleanup = (
+	newMixins:: nil.
+	revisedObjects:: nil.
+	oldObjects:: nil.
+	existingClasses:: nil.
+	newClasses:: nil.
+	deletedClasses: nil.
+	definingMirrors:: nil.	
+)
+cloneClass: oldClass <Class> ^ <Class> = (
+	| newMeta <Metaclass>  newClass <Class> superKlass <Class> |
+	
+	superKlass::  newClasses at: oldClass superclass ifAbsent:[oldClass superclass].
+   	newMeta:: Metaclass new.
+	newMeta superclass: NewspeakObject class
+                 methodDictionary: oldClass class methodDictionary
+                 format: oldClass class format.	
+	newClass:: newMeta new.
+	newClass superclass: superKlass
+			methodDictionary: oldClass methodDictionary
+			format: (Mixin new pointerFormatNumberOfInstVars: superKlass instSize + oldClass instVarNames size).
+	newClass setInstVarNames: oldClass instVarNames.
+	superKlass instSize ~= oldClass superclass instSize ifTrue:[
+			#MARK yourself.
+			Mixin new generateAccessorsFor: newClass offset: superKlass instSize.
+		].
+	setupDataFor: newClass basedOn: oldClass.
+	^newClass
+)
+depthFor: klass <Class> = (
+	klass isNil ifTrue:[^0].
+	^1 + (depthFor: klass superclass) "Mirrors!"
+)
+existingMixinFor: m <LowLevelMixinMirror> in: ns <Map[Symbol, Class]> ^ <Class | Nil> = (
+	"Find an existing mixin corresponding to me, or nil if there is none"
+	^ns at: m name ifAbsent:[]
+)
+install: newObjects <Array> insteadOf: old <Array>  = (
+	assert:[newObjects size = old size] message: 'New objects array size ', newObjects size printString, ' differs from old objects array size ', oldObjects size printString.
+		oldObjects asArray elementsForwardIdentityToEvenIfImmutable: revisedObjects asArray
+	"one way become of oldObjects to revisedObjects"
+)
+installAll = (
+	installNewMixins.
+	install: revisedObjects asArray insteadOf: oldObjects asArray
+)
+installNewMixins = (
+	newMixins do:[:m <Mixin>  | MixinManager soleInstance addMixinFor: m definingClass].
+	"this makes little sense. We should just manufacture a defining class, not a mixin. Yet this might work anyway"
+	"Moreover, it is not atomic! Do we care?"
+)
+layoutHasChangedBetween: oldClass <Class> and: newClass <Class> ^ <Boolean> = (
+	oldClass ifNil:[
+			newClass ifNil:[^false].
+			^newClass size ~= 0
+			].
+	newClass ifNil:[^oldClass size ~= 0].
+	^(layoutHasChangedBetween: oldClass superclass and: newClass superclass)
+		or:[mixinLayoutHasChangedBetween: (mixinOf: oldClass) and: (mixinOf: newClass)]
+)
+methodDictionaryFor: c <Class> from: m <LowLevelMixinMirror> ^ <MethodDictionary> = (
+	| md <MethodDictionary> methods <List[LowLevelMethodMirror]> |
+	methods:: m methods collect:[:mtd <LowLevelMethodMirror> | mtd].
+	md:: MethodDictionary new: methods size.
+	methods do:[:cm <LowLevelMethodMirror> | 
+		cm klass: c.
+		md at: cm selector put: cm compiledMethod
+		].
+	^md
+)
+mixinLayoutHasChangedBetween: oldMixin <Mixin> and: newMixin <Mixin> ^ <Boolean> = (
+	oldMixin isNil ifTrue:[^false].
+	^oldMixin instVarNames ~= newMixin instVarNames
+)
+mixinOf: invocation <Class> ^ <Class> = (
+	^SystemMetadata mixinOf: invocation
+)
+newClassFor: oldClass <Class> ^ <Class> = (
+	| m <LowLevelMixinMirror> |
+	m:: definingMirrors at: oldClass ifAbsent:[nil].
+	^m isNil ifTrue:[cloneClass: oldClass] ifFalse: [newClassFor: oldClass basedOn: m].
+)
+newClassFor: oldClass <Class> basedOn: m <LowLevelMixinMirror> ^ <Class> = (
+	| 
+	newMeta <Metaclass> 
+	newClass <Class> 
+	instVarNames <List[String]>
+	superKlass <Class>
+	|
+	superKlass::  newClasses at: oldClass superclass ifAbsent:[oldClass superclass].
+	instVarNames:: m instVars collect:[:ivm <InstanceVariableMirror> | ivm name].
+   	newMeta:: Metaclass new.
+	newMeta superclass: NewspeakObject class
+                 methodDictionary: (methodDictionaryFor: newMeta from: m classMixin)
+                 format: oldClass class format.	
+	newClass:: newMeta new.
+	newClass superclass: superKlass
+			methodDictionary: (methodDictionaryFor: newClass from: m)
+			format:  (Mixin new pointerFormatNumberOfInstVars: superKlass instSize + instVarNames size).
+	newClass setInstVarNames:  instVarNames.
+	superKlass instSize ~= 0 ifTrue:[
+			#MARK yourself.
+			Mixin new generateAccessorsFor: newClass offset: superKlass instSize.
+		].
+	setupDataFor: newClass basedOn: oldClass.
+	^newClass
+)
+newFor: old = (
+	^[revisedObjects at: (oldObjects indexOf: old) ifAbsent:[old]] ifError: [old]
+)
+newMixinFrom: m <LowLevelMixinMirror> ^ <Mixin> = (
+	| 
+	mixin <Mixin> 
+	fmt <Integer> 
+	newMeta <Metaclass> 
+	newClass <Class> 
+	instVarNames <List[String]>
+	unSyntheticMethods
+	|
+	
+   	newMeta:: Metaclass new.
+	newMeta superclass: NewspeakObject class
+                 methodDictionary: (methodDictionaryFor: newMeta from: m classMixin)
+                 format: NewspeakObject class format.	"Newspeak classes never add class instance variables"
+	newClass:: newMeta new.
+	setOrganizationOfClass: newMeta basedOn: m classMixin.
 
-mixinOf: invocation <Class> ^ <Class> = (
+	instVarNames:: m instVars collect:[:ivm <InstanceVariableMirror> | ivm name].
+	mixin:: Mixin new.
+	fmt:: mixin pointerFormatNumberOfInstVars: instVarNames size.
+	newClass superclass: ProtoObject
+			methodDictionary: (methodDictionaryFor: newClass from: m)
+			format: fmt.
+	newClass setInstVarNames: instVarNames.
+	newClass setName: m name.
 
-
+	"This is slow and will be handled in post install, so don't do it here
+	setOrganizationOfClass: newClass basedOn: m."
 
-newClassFor: oldClass <Class> ^ <Class> = (
+	"override existing metadata"
+	SystemMetadata systemMetadataOf: newClass put: (
+		DefiningClassMetadata new definingClass: newClass
+		).
+	mixin definingClass: newClass.
+	^mixin
+)
+noteDeletedClass: c <Class>  = (
+"Recursively note all mixins that must be deleted"
+	deletedClasses add: c.
+	(SystemMetadata systemMetadataOf: c) nestedClasses do:[:nc | noteDeletedClass: nc].
+)
+noteNestedMixinsOf: existingMixin <Class> deletedIn: nested <List[MixinList]> = (
+	| survivors <List[LowLevelMixinMirror]> |
+	
+	survivors::nested collect:[:r <MixinList> | r head name].
+	(SystemMetadata systemMetadataOf: existingMixin) nestedMixins do:[:nm <Class> |
+		 (survivors includes: nm name) ifFalse:[noteDeletedClass: nm]
+		]
+)
+processClass: c <Class> = (
+	| newClass <Class> |
+	newClass:: newClassFor: c.
+	newClasses at: c  put: newClass.
+	oldObjects add: c.
+	revisedObjects add: newClass.
+	oldObjects add: c class.
+	revisedObjects add: newClass class.
+	(layoutHasChangedBetween: c and: newClass) 
+		ifTrue:[processInstancesOf: c withNewClass: newClass]
+)
+processExistingClasses = (
+	existingClasses keys asSortedCollection do:[: k <Integer> |
+		(existingClasses at: k) do:[:c <Class> | processClass: c]
+		]
+)
+processExistingMixin: m <LowLeveMixinMirror> withExistingMixin: existingMixin <Class> ^ <Class> = (
+	| newMixin <Mixin> |
+	newMixin:: newMixinFrom: m.
+	SystemMetadata 
+		enclosingMixinOf: newMixin definingClass put: (SystemMetadata mixinOf: existingMixin).
+	SystemMetadata 
+		enclosingMixinOf: newMixin definingClass class put: (SystemMetadata mixinOf: existingMixin class).
+		"set enclosing mixin, in case this was not a top level mixin"
+	revisedObjects addLast: newMixin definingClass.
+	oldObjects addLast: existingMixin.
+	revisedObjects addLast: newMixin definingClass class.
+	oldObjects addLast: existingMixin class.
+	 existingMixin mixin applications do:[: app <Class> | 
+		definingMirrors at: app put: m.
+		sortClass: app
+		].
+	^newMixin definingClass
+)
+processExistingOutermostClass: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]>  ^ <MixinList> = (
+	| existingOutermostClass <Class> results <MixinList> |
 
-
+	existingOutermostClass:: existingMixinFor: rep first in: ns.
+	assert: [existingOutermostClass superclass = ProtoObject]
+	message: 'Class ', rep first name, ' is not a mixin; it has a non-trivial superclass'.
+	results:: processMixinRep: rep in: ns.
+	(SystemMetadata systemMetadataOf: results head) enclosingClass: (SystemMetadata mixinOf: existingOutermostClass).
+	"existingOutermostClass may not be a top level class. In that case, we need to adjust  the new versions metadata to point at its enclosing class"
+	^results
+)
+processInstancesOf: c <Class> withNewClass: newClass <Class> = (
+	c allInstances do:[: o  | | newObj |
+		"create new instance of newClass"
+		newObj:: newClass basicNew.
+		adjust: newObj to: o. "copy state from o to newObj as needed"
+		oldObjects add: o.
+		revisedObjects add: newObj
+	]
+)
+processMixinRep: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]> ^ <MixinList> = (
+	| existingMixin <Class> |
+	rep isNil ifTrue:[^nil].
+	rep isEmpty ifTrue:[^nil].
+	existingMixin:: existingMixinFor: rep first in: ns.
+	^existingMixin isNil
+		ifTrue:[processNewMixinRep: rep]
+		ifFalse: [processMixinRep: rep withExistingMixin: existingMixin]
+)
+processMixinRep: rep <LowLevelMixinRep> withExistingMixin: existingMixin <Class> ^ <MixinList> = (
+"existingMixin is the mixin being redefined by rep. The resulting MixinList will include the new version of existingMixin and all its nested mixins as described by rep "
+	| enclosing <Class> nested <List[MixinList]> ns <Map[Symbol, Class]> |
+	enclosing:: processExistingMixin: rep first withExistingMixin: existingMixin.
+	ns:: Map new.
+	((SystemMetadata systemMetadataOf: existingMixin) nestedClasses) do:[:c <Class> |
+		ns at: c name put: c.
+		].
+	nested:: rep last collect:[:r <LowLevelMixinRep> | processMixinRep: r in: ns].
+	nested do:[:nm <MixinList> |  SystemMetadata nestedClass: nm head within: enclosing].
+	noteNestedMixinsOf: existingMixin deletedIn: nested.
+	^MixinList head: enclosing
+			 tail: nested.
+)
+processNewMixin: m <LowLevelMixinMirror> ^ <Class> = (
+	"create mixin and add to new mixins"
+	| newMixin <Mixin> definingClass <Class> |
+	newMixin:: newMixinFrom: m.
+	newMixins addLast: newMixin.
+	definingClass:: newMixin definingClass.
+	ProtoObject addSubclass: definingClass.
+	^definingClass.
+)
+processNewMixinRep: rep <LowLevelMixinRep> ^ <MixinList> = (
+	| enclosing <Class> nested <List[MixinList]> |
+	rep isNil ifTrue:[^nil].
+	rep isEmpty ifTrue:[^nil].
+	enclosing:: processNewMixin: rep first.
+	nested:: rep last collect:[:r <LowLevelMixinRep> | processNewMixinRep: r].
+	nested do:[:nm <MixinList> |  SystemMetadata nestedClass: nm head within: enclosing].
+	^MixinList head: enclosing
+			 tail: nested.
+)
+processOutermostRep: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]> ^ <MixinList> = (
+	ns at: rep first name asSymbol ifAbsent:[^processNewMixinRep: rep].
+	^processExistingOutermostClass: rep in: ns.
+)
+removeDeletedClasses = (
+	deletedClasses do:[:dc <Class> | ProtoObject removeSubclass: dc]
+)
+setOrganizationOfClass: cls <Class>
+basedOn: lm <LowLevelMixinMirror> = (
+	| nonSyntheticMethods <LowLevelMethodMirror> |
+	nonSyntheticMethods:: (lm methods select: [ :mt | mt isSynthetic not]).
+	
+	"manually set organization, excluding synthetic methods"
+	cls organization:  (ClassOrganizer defaultList: (nonSyntheticMethods collect: [:ea | ea selector])).
 
-newClassFor: oldClass <Class> basedOn: m <LowLevelMixinMirror> ^ <Class> = (
   	newMeta:: Metaclass new.
                 methodDictionary: (methodDictionaryFor: newMeta from: m classMixin)
                 format: oldClass class format.	
+	"classify (non-synthetic) elements if mirror includes category information"
+	(nonSyntheticMethods 
+		select: [ :um | um metadata includesKey: #category ])
+		do: [ :cm | cls organization
+						classify: cm selector
+						under: (cm metadata at: #category) ].
+)
+setup = (
+	newMixins:: List new.
+	revisedObjects:: List new.
+	oldObjects:: List new.
+	existingClasses:: Map new.
+	newClasses:: Map new.
+	deletedClasses:: List new.
+	definingMirrors:: Map new.	
+)
+setupDataFor: newClass <Class> basedOn: oldClass <Class> = (
+	| newMeta <Metaclass> |
+	newMeta:: newClass class.
 
-
-
-newFor: old = (
-
-
-
-newMixinFrom: m <LowLevelMixinMirror> ^ <Mixin> = (
   	newMeta:: Metaclass new.
                 methodDictionary: (methodDictionaryFor: newMeta from: m classMixin)
                 format: NewspeakObject class format.	"Newspeak classes never add class instance variables"
-
-
-
-noteDeletedClass: c <Class>  = (
-
-
-
-noteNestedMixinsOf: existingMixin <Class> deletedIn: nested <List[MixinList]> = (
-
-
-
-processClass: c <Class> = (
-
-
-
-processExistingClasses = (
-
-
-
-processExistingMixin: m <LowLeveMixinMirror> withExistingMixin: existingMixin <Class> ^ <Class> = (
-
-
-
-processExistingOutermostClass: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]>  ^ <MixinList> = (
-
-
-
-processInstancesOf: c <Class> withNewClass: newClass <Class> = (
-
-
-
-processMixinRep: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]> ^ <MixinList> = (
-
-
-
-processMixinRep: rep <LowLevelMixinRep> withExistingMixin: existingMixin <Class> ^ <MixinList> = (
-
-
-
-processNewMixin: m <LowLevelMixinMirror> ^ <Class> = (
-
-
-
-processNewMixinRep: rep <LowLevelMixinRep> ^ <MixinList> = (
-
-
-
-processOutermostRep: rep <LowLevelMixinRep> in: ns <Map[Symbol, Class]> ^ <MixinList> = (
-
-
-
-removeDeletedClasses = (
-
-
-
-setOrganizationOfClass: cls <Class>
-
-
-
-setup = (
-
-
-
-setupDataFor: newClass <Class> basedOn: oldClass <Class> = (
-
-
-
-sortClass: app <Class>  = (
-
-
-
-'accessing'
-
-atomicallyInstallMixinReps: mixins <List[LowLevelMixinRep]> namespace: ns <Map[Symbol, Class]> ^ <List[MixinList]> = (
 "
-
-
-
-)
+	#MARK yourself.
+	SystemMetadata mixinOf: newClass put: (newFor: (SystemMetadata mixinOf: oldClass)).
+	SystemMetadata mixinOf: newMeta put: (newFor: (SystemMetadata mixinOf: oldClass class)).
+	SystemMetadata enclose: newClass inObject: (SystemMetadata enclosingObjectOf: oldClass).
+	SystemMetadata enclose: newMeta inObject: (SystemMetadata enclosingObjectOf: oldClass class).
+	SystemMetadata systemMetadataOf: newClass put:(SystemMetadata systemMetadataOf: oldClass).
+	newClass organization: oldClass organization.
+	newMeta organization: oldClass class organization.
+	newClass setName: oldClass name.		
+)
+sortClass: app <Class>  = (
+| classes <Set[Class]> depth <Integer> |
+	depth:: depthFor: app.
+	classes:: existingClasses 
+		at: depth 
+		ifAbsent:[existingClasses at: depth put: Set new].
+	classes add: app. "optimize? If app is already there, no need to recurse on subclasses"
+	app subclasses do:[: sc <Class> | sortClass: sc]. "use mirrors"
+))