Hi,

Steph, the image logic also has changed in Pharo. There should not be any difference (at least from the list that Eliot gave).

Guille

-------- Original Message --------
Wow, thanks for the detailed explanation!

Cheers,
Bernhard


Am 21.04.2016 um 16:48 schrieb Eliot Miranda <[email protected]>:

Hi Bernhard,

On Apr 20, 2016, at 9:56 PM, Bernhard Pieber <[email protected]> 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 <[email protected]>:

Hi Bernhard,


On Apr 20, 2016, at 5:26 AM, Bernhard Pieber <[email protected]> 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




Reply via email to