Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1323.mcz ==================== Summary ==================== Name: Kernel-eem.1323 Author: eem Time: 15 April 2020, 4:46:14.261016 pm UUID: 5ea740f0-f4c6-4808-b7b6-2e3aee87aa91 Ancestors: Kernel-eem.1322 Update the ClassBuilder and instance migration, given the changes in Collections-eem.885. See http://forum.world.st/How-to-become-immediate-objects-td5114931.html. =============== Diff against Kernel-eem.1322 =============== Item was changed: ----- Method: ClassBuilder>>update:to: (in category 'class mutation') ----- update: 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} elementsForwardIdentityAndHashTo: {newClass}. - [oldClass becomeForward: newClass. oldClass updateMethodBindingsTo: oldClass binding] ifFalse: + [{oldClass. oldClass class} elementsForwardIdentityAndHashTo: {newClass. newClass class}. - [{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 changed: ----- Method: ClassDescription>>updateInstances:from:isMeta: (in category 'initialize-release') ----- updateInstances: oldInstances from: oldClass isMeta: isMeta "Recreate any existing instances of the argument, oldClass, as instances of the receiver, which is a newly changed class. Permute variables as necessary, and forward old instances to new instances. Answer nil to defeat old clients that expect an array of old instances. The old behaviour, which necessitated a global GC, exchanged identities and answered the old instances. But no clients used the result. This way we avoid the unnecessary GC," | map variable instSize newInstances | oldInstances isEmpty ifTrue: [^nil]. "no instances to convert" isMeta ifTrue: [(oldInstances size = 1 and: [self soleInstance class == self or: [self soleInstance class == oldClass]]) ifFalse: [^self error: 'Metaclasses can only have one instance']]. map := self instVarMappingFrom: oldClass. variable := self isVariable. instSize := self instSize. newInstances := Array new: oldInstances size. 1 to: oldInstances size do: [:i| newInstances at: i put: (self newInstanceFrom: (oldInstances at: i) variable: variable size: instSize map: map)]. "Now perform a bulk mutation of old instances into new ones" + oldInstances elementsForwardIdentityAndHashTo: newInstances. - oldInstances elementsForwardIdentityTo: newInstances. ^nil! |
Free forum by Nabble | Edit this page |