Wow, thanks for the detailed explanation! Cheers, Bernhard
> Am 21.04.2016 um 16:48 schrieb Eliot Miranda <eliot.mira...@gmail.com>: > > Hi Bernhard, > >> On Apr 20, 2016, at 9:56 PM, Bernhard Pieber <bernh...@pieber.com> wrote: >> >> Hi Eliot, >> >> Right, but in the latest Squeak5.1-trunk with the latest CogSpur.r3663.app >> it takes only 3 milliseconds. I guess it’s just an optimized implementation, >> there. (Can’t look right now.) > > Indeed ;-). In most Smalltalk implementations an object's header contains a > direct reference (a pointer) to its class, but in Spur, an object's header > contains a "class index" (as does the Dart VM). IIRC this is an approach > first tried in a system at Xerox PARC, but what follows, I invented for > 64-bit VW, to avoid having 64-bits of class reference in every object. > > The object header contains both a 22-bit classIndex, for up to 4 million > classes, and a 22-bit identityHash field for 4 million hash values. The > classIndex is used in all method caches, which has advantages for the GC, and > means that when sending a message via an inline cache, the object's index is > fetched, not its class. > > Classes are stored in a hidden two-level sparse array (array of arrays), the > class table. If the object's class object is required (for the #class > message or to do a full message lookup searching the inheritance hierarchy) > the classIndex is used to index the class table. > > The classes known to the VM, Array, Message, Context, LargeNegativeInteger, > LargePositiveInteger have known indices and occupy the first page of the > class table. So the VM can allocate instances of these by simply writing a > header containing the relevant classIndex. A conventional implementation > would have to fetch the class from the specialObjectsArray and write it into > the header (and in pre-Spur, there are 31 "compact class indices" of which a > handful are used for a subset of the classes). > > But how does the VM find the classIndex of an arbitrary class? Searching the > table would be very slow. So Spur arranges that a class's identityHash is > also its index in the classTable. Classes have their own special > identityHash primitive, see Behavior>>#identityHash. Whenever the VM tries > to Instantiate a class, or whenever the class's identityHash primitive is > run, if the class's identityHash is zero, the VM assigns an unused index in > the class table as the identityHash and stores the class in the table. So a > class's identityHash is its index in the class table. > > To Instantiate a class its identityHash is copied into the classIndex field > of the new instance's header. To search for all instances of a class, the VM > searches for objects whose classIndex is that class's identityHash. A > consequence is that if a class doesn't yet have an identityHash (identityHash > = 0) it can't have instances, and so there is no need to scan the heap. > > > Note that you can't (easily) tell from the image. If you send identityHash > to a class that will enter it into the table. There's a hidden > hasIdentityHash primitive that can be used, and if you're curious I can post > code to get at it. Note that this implies all the metaclasses are in the > table because they have as their single instance a normal named class, but > Metaclasses holds onto its instance via thisClass and so can also avoid > traversing the heap. > > Some things to try: > > {Array. ByteString. Character. Context. LargeNegativeInteger. > LargePositiveInteger. Message. SmallFloat64. BoxedFloat64. SmallInteger} > collect: #identityHash > > and in a pre-Spur system > > Smalltalk compactClassesArray select: [:c| Smalltalk specialObjectsArray > includes: c] thenCollect: [:c| {c. c indexIfCompact] > > Hope this explains what's going on under the covers. > >> Cheers, >> Bernhard >> >>> Am 20.04.2016 um 17:43 schrieb Eliot Miranda <eliot.mira...@gmail.com>: >>> >>> Hi Bernhard, >>> >>> >>>> On Apr 20, 2016, at 5:26 AM, Bernhard Pieber <bernh...@pieber.com> wrote: >>>> >>>> Dear Pharoers, >>>> >>>> I found something strange: >>>> Time millisecondsToRun: [ Class allSubInstances size ]. „23617" >>> >>> Because it does an allInstances for Class and all its subclasses, and >>> allInstances visits every object in the heap, so this does thousands of >>> scans of the heap. >>> >>> >>>> I did this on a new Pharo 5 image >>>> curl get.pharo.org/alpha+vmLatest | bash >>>> >>>> Can somebody confirm this on their machine? What might be the reason? >>>> >>>> Cheers, >>>> Bernhard >> >> >