<br><br><div class="gmail_quote">On Tue, Nov 16, 2010 at 9:52 PM, Levente Uzonyi <span dir="ltr">&lt;<a href="mailto:leves@elte.hu">leves@elte.hu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On Tue, 16 Nov 2010, Andreas Raab wrote:<br>
<br>
</div><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On 11/16/2010 8:05 PM, Levente Uzonyi wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I wasn&#39;t clear when I said atomic code. I expected #= (and #&lt;, #&gt;, etc)<br>
to _not_ be a real message send when both the receiver and the argument<br>
are SmallIntegers. Otherwise what&#39;s the point of having separate<br>
bytecodes for them?<br>
</blockquote>
<br>
Space. It makes a big difference for the most common selectors (#at:, #at:put:, #size, #+ etc) to be be encoded as bytecodes. It avoids having to allocate a literal every time you see the selector. Often, the special<br>

</blockquote>
<br></div>
I just evaluated this:<br>
<br>
| count specialSelectors |<br>
count := 0.<br>
specialSelectors := Smalltalk specialSelectors select: [ :each | each isSymbol ].<br>
CompiledMethod allInstancesDo: [ :method |<br>
        | messages |<br>
        messages := method messages.<br>
        count := count + (specialSelectors count: [ :selector |<br>
                messages includes: selector ]) ].<br>
count<br>
<br>
The result is 50947 for a slightly modified Trunk image. This means that this technique saves less than 200kB (assuming 32-bit slots in the literal frame), but it uses 32 bytecodes.<br>
<br>
200 kB is not much compared to the size of the image (about 1-2%).<br>
<br>
Also the 32 most frequently used methods are not the 32 special selectors.<br>
<br>
| b mostFrequentSelectors specialSelectors |<br>
b := Bag new.<br>
CompiledMethod allInstancesDo: [ :method | b addAll: method messages ].<br>
mostFrequentSelectors := (b sortedCounts first: 32) replace: #value.<br>
specialSelectors := Smalltalk specialSelectors select: #isSymbol.<br>
{<br>
        specialSelectors difference: mostFrequentSelectors. &quot;Shouldn&#39;t be special&quot;<br>
        mostFrequentSelectors difference: specialSelectors. &quot;Should be special&quot;<br>
}.<br>
<br>
#(<br>
        #(#&#39;&gt;=&#39; #&#39;~=&#39; #/ #&#39;\\&#39; #bitShift: #&#39;//&#39; #bitAnd: #bitOr: #next #atEnd #blockCopy: #value #value: #x #y)<br>
        #(#, #assert: #first #name #add: #nextPutAll: #isEmpty #error: #asString #includes: #default #translated #not #on: #collect:))<br>
<br>
Another 40kB could be saved by changing these.<br>
<br>
Btw, there&#39;s a &quot;free&quot; bytecode: 200 - #blockCopy:.</blockquote><div><br></div><div>I would like to reserve this for a page of new bytecodes, some of which I&#39;d like to use for adaptive optimization/speculative inlining work that Marcus, Colin and I are planning to start in the new year.</div>
<div><br></div><div>best</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 class="im"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
selector bytecodes look like this:<br>
<br>
Interpreter&gt;&gt;bytecodePrimNextPut<br>
        messageSelector := self specialSelector: 20.<br>
        argumentCount := 1.<br>
        self normalSend.<br>
<br>
I.e., it just dispatches to normalSend where the regular lookup takes place. Of course, that also means it&#39;s a prime place for an optimization that will evaluate eagerly for known receiver types and so (over time) optimizations were added, but many of the optimizations that may make sense in an interpreter have very different tradeoffs in the jit. For a jit to generate the level of optimization makes no sense because the code size simply explodes at no benefit if the inline caches are any good (ours *are* the best Eliot knows how to do and that is a meaningful statement).<br>

<br>
On to a finer point. The terminology &quot;real message send&quot; is misleading. Generally, we (the VM hackers) mean by &quot;real&quot; send a send that requires a method activation, i.e., the creation of a context, but *not* the lookup of the method. That excludes for example all (successful) primitives from being &quot;real sends&quot;, and as a consequence writing &quot;1 + 2&quot; is not a real send by that measure (with or without the bytecode present) since the primitive will be executed successfully and no &quot;real&quot; send (method activation) has taken place.<br>

<br>
To make matters more complicated, when we talk about &quot;real&quot; sends in the context of thread switches, semaphores and critical sections, what we mean is whether there is a suspension point in the send or not. Obviously, some primitives (#suspend, #yield) must have suspension points so not all activation-free methods are also suspension-point-free. I am not entirely sure what the current set of rules for suspension points in Cog is; in the interpreter it was part of the activation sequence so any primitive that isn&#39;t process related would not have a suspension point but I don&#39;t know if that&#39;s still true in Cog.<br>

</blockquote>
<br></div>
Thanks, this was very informative.<br>
<br>
<br>
Levente<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Cheers,<br>
 - Andreas<br>
<br>
<br>
</blockquote>
<br>
</blockquote></div><br>