The Trunk: Kernel-eem.1323.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Kernel-eem.1323.mcz

commits-2
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!