[squeak-dev] The Trunk: Kernel-eem.1323.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Apr 15 23:46:18 UTC 2020


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!



More information about the Squeak-dev mailing list