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.<div>

<br></div><div>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?</div><div><br></div><div>Regards,</div><div>           Javier.<br>

<br><div class="gmail_quote">On Thu, Jun 9, 2011 at 3:34 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

 <br>Hi Javier,<br><br><div class="gmail_quote">On Wed, Jun 8, 2011 at 6:41 PM, Javier Pimás <span dir="ltr">&lt;<a href="mailto:elpochodelagente@gmail.com" target="_blank">elpochodelagente@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 <br>thanks both mariano and you for the quick answers, they helped a lot. Now let&#39;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<div>




<br></div><div><div>0x78c68dd4:     0x779cadf5      0x1848038d      0x00000003      0x78c68e64</div><div>0x78c68de4:     0x77831004      0x77831004      0x77831004      0x77831004</div><div>0x78c68df4:     0x77831004      0x77831004      0x77831004      0x77831004</div>




<div>0x78c68e04:     0x77831004      0x77831004      0x77831004      0x77831004</div><div>0x78c68e14:     0x77831004      0x77831004      0x77831004      0x77831004</div><div>0x78c68e24:     0x77831004      0x77831004      0x77831004      0x77831004</div>




<div>0x78c68e34:     0x77831004      0x77831004      0x77831004      0x77831004</div><div>0x78c68e44:     0x77831004      0x77831004      0x77831004      0x77831004</div><div>0x78c68e54:     0x77831004      0x77831004      0x77831004      0x778cb5d4</div>




<div>0x78c68e64:     0x00da3287      0x77831004      0x77831004      0x77831004</div><div><br></div><div>where the second int (0x1848038d) is the base header (the oop points to 0x78c68dd8). The first fields is a smallint for 1, I guess. </div>


</div></blockquote><div><br></div><div>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.</div><div><br></div><div>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:</div>


<div><br></div><div><div><span style="white-space:pre-wrap">        </span>Breakpoint 1, interpret () at /Users/eliot/Cog/oscogvm/macbuild/../src/vm/gcc3x-cointerp.c:1930</div><div><span style="white-space:pre-wrap">        </span>1930        JUMP_TABLE;</div>


<div><br></div><div>find nil:</div><div><span style="white-space:pre-wrap">        </span>(gdb) call printOop(nilObj)</div><div><span style="white-space:pre-wrap">        </span>0x141fc004: a(n) UndefinedObject</div>
<div><br></div><div>find its class UndefinedObject:</div><div><span style="white-space:pre-wrap">        </span>(gdb) call printOop(fetchClassOf(nilObj))</div><div><span style="white-space:pre-wrap">        </span>0x146f0c34: a(n) UndefinedObject class</div>


<div><span style="white-space:pre-wrap">        </span>0x147ff778 0x14d5cdd8        0x5 0x141fc004 0x14255af0 </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x1438e6e0 0x14696580 0x141fc004 0x141fc004 </div>
<div><span style="white-space:pre-wrap">        </span>0x1438e0cc </div><div><br></div><div>print its method dictionary, the second inst var, 0x14d5cdd8</div><div><span style="white-space:pre-wrap">        </span>(gdb) call printOop(0x14d5cdd8)          </div>


<div><span style="white-space:pre-wrap">        </span>0x14d5cdd8: a(n) MethodDictionary</div><div><span style="white-space:pre-wrap">        </span>      0x55 0x14d5ceec 0x141fc004 0x141fc004 0x141fc004 </div>
<div><span style="white-space:pre-wrap">        </span>0x1438fdac 0x141fc004 0x141fc004 0x141fc004 0x141fc004 </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x141fc004 0x141fc004 0x143a1448 0x141fc004 </div>
<div><span style="white-space:pre-wrap">        </span>0x141fc004 0x141fc004 0x143c8290 0x141fc004 0x14386320 </div><div><span style="white-space:pre-wrap">        </span>0x1511d0ec 0x1438fc90 0x141fc004 0x14386a70 0x1439d52c </div>
<div><span style="white-space:pre-wrap">        </span>0x143b53c8 0x1438db24 0x1483bc30 0x1439d53c 0x143a07c4 </div><div><span style="white-space:pre-wrap">        </span>0x143c9634 0x143e6ca4 0x144095e4 0x14386730 0x14390080 </div>
<div><span style="white-space:pre-wrap">        </span>0x1438ff04 0x14424624 0x14402638 0x1511d004 0x143869c4 </div><div><span style="white-space:pre-wrap">        </span>0x14386530 0x1439f5d4 0x1438ffb4 0x143864b8 0x14386a08 </div>
<div><span style="white-space:pre-wrap">        </span>0x143c20d4 0x14386a18 0x1438647c 0x143868cc 0x141fc004 </div><div><span style="white-space:pre-wrap">        </span>0x1438f800 0x143aba20 0x141fc004 0x141fc004 0x14424608 </div>
<div><span style="white-space:pre-wrap">        </span>0x1438b2f0 0x1438d1b0 0x144095fc 0x141fc004 0x141fc004 </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x143a4ce4 0x143c44e4 0x143c82a4 </div>
<div><br></div><div>and hex 55 is 2 * 42 + 1, so the dictionary has 42 entries (how appropriate) and, by counting, 64 slots.</div><div><span style="white-space:pre-wrap">        </span>...</div><div><span style="white-space:pre-wrap">        </span>(gdb) call printOop(0x14d5ceec)</div>


<div><span style="white-space:pre-wrap">        </span>0x14d5ceec: a(n) Array</div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x141fc004 0x141fc004 0x14661cdc 0x141fc004 </div>
<div><span style="white-space:pre-wrap">        </span>0x141fc004 0x141fc004 0x141fc004 0x141fc004 0x141fc004 </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x14661cf4 0x141fc004 0x141fc004 0x141fc004 </div>
<div><span style="white-space:pre-wrap">        </span>0x14661d0c 0x141fc004 0x1486564c 0x1513faa0 0x14661d28 </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x14661d4c 0x14661d70 0x14661d88 0x14661da0 </div>
<div><span style="white-space:pre-wrap">        </span>0x1483bcb4 0x14661dc0 0x14661dd8 0x14661df0 0x14661e28 </div><div><span style="white-space:pre-wrap">        </span>0x14661e40 0x14661e58 0x14661e6c 0x14661ea4 0x14661ebc </div>
<div><span style="white-space:pre-wrap">        </span>0x14661ed4 0x1513fa80 0x14661ef4 0x14661f18 0x14661f2c </div><div><span style="white-space:pre-wrap">        </span>0x14661f40 0x14661f80 0x14661fa4 0x14661fb8 0x14661fd0 </div>
<div><span style="white-space:pre-wrap">        </span>0x14661fe4 0x14661ff8 0x141fc004 0x1466200c 0x1466202c </div><div><span style="white-space:pre-wrap">        </span>0x141fc004 0x141fc004 0x14662048 0x146620cc 0x14662114 </div>
<div><span style="white-space:pre-wrap">        </span>0x1466212c 0x141fc004 0x141fc004 0x141fc004 0x14865690 </div><div><span style="white-space:pre-wrap">        </span>0x14662150 0x14662164 0x141fc004 0x14662180 </div>
</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>Now the questions: in the header, size bits are 100011, why? </div></div></blockquote><div>


<br></div><div>Does it?  Anyway, the header constants are set forth in ObjectMemory class&gt;&gt;initializeObjectHeaderConstants, and used in ObjectMemory&#39;s header access protocol in methods such as ObjectMemory&gt;&gt;sizeBitsOf:.</div>


<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>Also second object would be the array oop in case the object weren&#39;t flat, but in this case it seems to point to the position past the last variable field, am I guessing right?</div>


</div></blockquote><div><br></div><div>Don&#39;t guess :) Read the source and work it out.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>


 How does the VM manage this flattening of the instance vars?</div></div></blockquote><div><br></div><div>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&#39;s indexing primitive support protocol in methods stObject:at:, stObject:at;put:, subscript:with:format: and subscript:with:storing:format:.</div>


<div><br></div><div>cheers,</div><div>Eliot</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>

<div><br></div><div>Thanks!</div><div>         Javier.</div><br><div class="gmail_quote">On Wed, Jun 8, 2011 at 2:01 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<br>




<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><br><br><div class="gmail_quote">On Wed, Jun 8, 2011 at 8:35 AM, Javier Pimás <span dir="ltr">&lt;<a href="mailto:elpochodelagente@gmail.com" target="_blank">elpochodelagente@gmail.com</a>&gt;</span> wrote:<br>




<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 <br>Hi, this is another simple (I hope) question:<div><br></div><div>I have an instance of MethodDictionary, which is defined as</div><div><br></div><div>Dictionary variableSubclass: #MethodDictionary<div><span style="white-space:pre-wrap">        </span>instanceVariableNames: &#39;&#39;</div>







<div><span style="white-space:pre-wrap">        </span>classVariableNames: &#39;&#39;</div><div><span style="white-space:pre-wrap">        </span>poolDictionaries: &#39;&#39;</div><div><span style="white-space:pre-wrap">        </span>category: &#39;Kernel-Methods&#39;</div>







<div><br></div><div>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?</div>





</div></blockquote><div><br></div><div>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.</div>





<div><br></div><div>When Squeak was implemented it was decided to use flat objects in the VM, following the lead of David Ungar&#39;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&#39;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.</div>





<div><br></div><div>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.</div>





<div><br></div><div>HTH</div><div>Eliot</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>

<div><br></div><div>Also, looking at the header, I see some strange things in the size field (being bigger than what I&#39;d expect). What is the format of size field in this case?</div><div><br></div><div>Thanks!</div><div>







          Javier.</div><br>-- <br>Javier Pimás<br>Ciudad de Buenos Aires<br>
</div>
<br></blockquote></div><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Javier Pimás<br>Ciudad de Buenos Aires<br>
</div>
<br></blockquote></div><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Javier Pimás<br>Ciudad de Buenos Aires<br>
</div>