[Vm-dev] What are classes defined with varibleSubclass?

Javier Pimás elpochodelagente at gmail.com
Thu Jun 9 19:31:51 UTC 2011

Thanks again for your time and the detailed answer. I finally could
understand what was going on. When you said it was flat, I firstly thought
that meant that the whole array of associations instVar was somehow pasted
into the MethodDictionary. Of course I was wrong, what happens is that only
the keys are put there (now I know, this is obvious from the class
description), and the array is just a normal object that holds the values.

One unrelated question: if oops are aligned to 4-byte words, then there is a
free bit in oops (the penultimate one). Is it used for something?


On Thu, Jun 9, 2011 at 3:34 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:

> Hi Javier,
> On Wed, Jun 8, 2011 at 6:41 PM, Javier Pimás <elpochodelagente at gmail.com>wrote:
>> thanks both mariano and you for the quick answers, they helped a lot. Now
>> let's get the hands dirty: I want to understand a bit better the internals
>> of this tiny animals. I have a MethodDictionary, with tally=1 and an array
>> of size 32, filled with all nils except for the last position. Looking at it
>> with gdb, including header I get
>> 0x78c68dd4:     0x779cadf5      0x1848038d      0x00000003      0x78c68e64
>> 0x78c68de4:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68df4:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e04:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e14:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e24:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e34:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e44:     0x77831004      0x77831004      0x77831004      0x77831004
>> 0x78c68e54:     0x77831004      0x77831004      0x77831004      0x778cb5d4
>> 0x78c68e64:     0x00da3287      0x77831004      0x77831004      0x77831004
>> where the second int (0x1848038d) is the base header (the oop points to
>> 0x78c68dd8). The first fields is a smallint for 1, I guess.
> Instead of using raw gdb, you could try using gdb plus the debug routines
> included in the VM (or use the VM simulator).  e.g.
> set a breakpoint in interpret, run your favourite image (in this case an
> updated trunk squeak 4.2) and hence examine it immediately after loading:
> Breakpoint 1, interpret () at
> /Users/eliot/Cog/oscogvm/macbuild/../src/vm/gcc3x-cointerp.c:1930
> 1930        JUMP_TABLE;
> find nil:
> (gdb) call printOop(nilObj)
> 0x141fc004: a(n) UndefinedObject
> find its class UndefinedObject:
> (gdb) call printOop(fetchClassOf(nilObj))
> 0x146f0c34: a(n) UndefinedObject class
>  0x147ff778 0x14d5cdd8        0x5 0x141fc004 0x14255af0
> 0x141fc004 0x1438e6e0 0x14696580 0x141fc004 0x141fc004
>  0x1438e0cc
> print its method dictionary, the second inst var, 0x14d5cdd8
> (gdb) call printOop(0x14d5cdd8)
>  0x14d5cdd8: a(n) MethodDictionary
>       0x55 0x14d5ceec 0x141fc004 0x141fc004 0x141fc004
>  0x1438fdac 0x141fc004 0x141fc004 0x141fc004 0x141fc004
> 0x141fc004 0x141fc004 0x141fc004 0x143a1448 0x141fc004
>  0x141fc004 0x141fc004 0x143c8290 0x141fc004 0x14386320
> 0x1511d0ec 0x1438fc90 0x141fc004 0x14386a70 0x1439d52c
>  0x143b53c8 0x1438db24 0x1483bc30 0x1439d53c 0x143a07c4
> 0x143c9634 0x143e6ca4 0x144095e4 0x14386730 0x14390080
>  0x1438ff04 0x14424624 0x14402638 0x1511d004 0x143869c4
> 0x14386530 0x1439f5d4 0x1438ffb4 0x143864b8 0x14386a08
>  0x143c20d4 0x14386a18 0x1438647c 0x143868cc 0x141fc004
> 0x1438f800 0x143aba20 0x141fc004 0x141fc004 0x14424608
>  0x1438b2f0 0x1438d1b0 0x144095fc 0x141fc004 0x141fc004
> 0x141fc004 0x143a4ce4 0x143c44e4 0x143c82a4
> and hex 55 is 2 * 42 + 1, so the dictionary has 42 entries (how
> appropriate) and, by counting, 64 slots.
> ...
> (gdb) call printOop(0x14d5ceec)
>  0x14d5ceec: a(n) Array
> 0x141fc004 0x141fc004 0x141fc004 0x14661cdc 0x141fc004
>  0x141fc004 0x141fc004 0x141fc004 0x141fc004 0x141fc004
> 0x141fc004 0x14661cf4 0x141fc004 0x141fc004 0x141fc004
>  0x14661d0c 0x141fc004 0x1486564c 0x1513faa0 0x14661d28
> 0x141fc004 0x14661d4c 0x14661d70 0x14661d88 0x14661da0
>  0x1483bcb4 0x14661dc0 0x14661dd8 0x14661df0 0x14661e28
> 0x14661e40 0x14661e58 0x14661e6c 0x14661ea4 0x14661ebc
>  0x14661ed4 0x1513fa80 0x14661ef4 0x14661f18 0x14661f2c
> 0x14661f40 0x14661f80 0x14661fa4 0x14661fb8 0x14661fd0
>  0x14661fe4 0x14661ff8 0x141fc004 0x1466200c 0x1466202c
> 0x141fc004 0x141fc004 0x14662048 0x146620cc 0x14662114
>  0x1466212c 0x141fc004 0x141fc004 0x141fc004 0x14865690
> 0x14662150 0x14662164 0x141fc004 0x14662180
> Now the questions: in the header, size bits are 100011, why?
> Does it?  Anyway, the header constants are set forth in ObjectMemory
> class>>initializeObjectHeaderConstants, and used in ObjectMemory's header
> access protocol in methods such as ObjectMemory>>sizeBitsOf:.
> Also second object would be the array oop in case the object weren't flat,
>> but in this case it seems to point to the position past the last variable
>> field, am I guessing right?
> Don't guess :) Read the source and work it out.
>> How does the VM manage this flattening of the instance vars?
> As far as the GC is concerned there is nothing special about the object; it
> is just a vector of object pointers.  So the flattening (actually the
> stepping over of named inst vars) is actually handled by the at: and at:put:
> code, which is in Interpreter/StackInterpreter's indexing primitive support
> protocol in methods stObject:at:, stObject:at;put:, subscript:with:format:
> and subscript:with:storing:format:.
> cheers,
> Eliot
>> Thanks!
>>          Javier.
>> On Wed, Jun 8, 2011 at 2:01 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:
>>> On Wed, Jun 8, 2011 at 8:35 AM, Javier Pimás <elpochodelagente at gmail.com
>>> > wrote:
>>>> Hi, this is another simple (I hope) question:
>>>> I have an instance of MethodDictionary, which is defined as
>>>> Dictionary variableSubclass: #MethodDictionary
>>>> instanceVariableNames: ''
>>>>  classVariableNames: ''
>>>> poolDictionaries: ''
>>>> category: 'Kernel-Methods'
>>>> looking at the format field it says 3, which I understand is that
>>>> instances have both fixed and indexed oops. The question is, what does that
>>>> mean? or better why is it that way if the class only defines an array an a
>>>> tally as instance variables?
>>> An object with both named and indexed inst vars is flat, i.e. is only a
>>> single object.  For example MethodContext.  An object with an array to hold
>>> its variable objects, e.g. the current OrderedCollection, is not flat, i.e.
>>> two objects.  The distinction is to do with the efficiency of implementing
>>> become.  In the original Smalltalk-80 implementations and in the VisualWorks
>>> VM objects in the heap are split into a header and a body, with the header
>>> containing a pointer to the body (and references to objects are pointers to
>>> object headers). This makes certain algorithms like compaction easy to
>>> implement, but it also results in a cheap become.
>>> When Squeak was implemented it was decided to use flat objects in the VM,
>>> following the lead of David Ungar's Berkeley Smalltalk implementation, and
>>> of the subsequent Self implementations, all of which also use flat objects.
>>>  Flat objects makes for faster allocation and faster inst var access (since
>>> accessing an inst var doesn't require the double indirection of following
>>> the pointer  to the header and then the pointer to the body).  But it makes
>>> become very much more expensive, since in the worst case the VM must scan
>>> the entire heap looking for references to the objects in the become
>>> operation and replacing them by references to their corresponding objects.
>>>  The solution David Ungar developed, which was adopted by Squeak, was to
>>> unflatten objects that used become to grow, such as OrderedCollection, Set
>>> and DIctionary, and use an array to hold their variable part.
>>> A key point is that objects such as OrderedCollection, Set and DIctionary
>>> encapsulate their state and so are free to grow by allocating a larger array
>>> and copying the contents from the old to the new array.  There is still an
>>> issue with streams, which have also been changed not to use become when
>>> growing their collections.  It used to be the case that one could use
>>> streams to grow objects, since in Smalltalk-80 they used become.  But this
>>> was not used very often and easily worked around.
>>> HTH
>>> Eliot
>>>> Also, looking at the header, I see some strange things in the size field
>>>> (being bigger than what I'd expect). What is the format of size field in
>>>> this case?
>>>> Thanks!
>>>>           Javier.
>>>> --
>>>> Javier Pimás
>>>> Ciudad de Buenos Aires
>> --
>> Javier Pimás
>> Ciudad de Buenos Aires

Javier Pimás
Ciudad de Buenos Aires
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20110609/7dffd3b1/attachment.htm

More information about the Vm-dev mailing list