[squeak-dev] Re: Using #= for integer comparison instead of #==

Eliot Miranda eliot.miranda at gmail.com
Wed Dec 1 03:38:33 UTC 2010


On Tue, Nov 16, 2010 at 9:52 PM, Levente Uzonyi <leves at elte.hu> wrote:

> On Tue, 16 Nov 2010, Andreas Raab wrote:
>
>  On 11/16/2010 8:05 PM, Levente Uzonyi wrote:
>>
>>> I wasn't clear when I said atomic code. I expected #= (and #<, #>, etc)
>>> to _not_ be a real message send when both the receiver and the argument
>>> are SmallIntegers. Otherwise what's the point of having separate
>>> bytecodes for them?
>>>
>>
>> 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
>>
>
> I just evaluated this:
>
> | count specialSelectors |
> count := 0.
> specialSelectors := Smalltalk specialSelectors select: [ :each | each
> isSymbol ].
> CompiledMethod allInstancesDo: [ :method |
>        | messages |
>        messages := method messages.
>        count := count + (specialSelectors count: [ :selector |
>                messages includes: selector ]) ].
> count
>
> 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.
>
> 200 kB is not much compared to the size of the image (about 1-2%).
>
> Also the 32 most frequently used methods are not the 32 special selectors.
>
> | b mostFrequentSelectors specialSelectors |
> b := Bag new.
> CompiledMethod allInstancesDo: [ :method | b addAll: method messages ].
> mostFrequentSelectors := (b sortedCounts first: 32) replace: #value.
> specialSelectors := Smalltalk specialSelectors select: #isSymbol.
> {
>        specialSelectors difference: mostFrequentSelectors. "Shouldn't be
> special"
>        mostFrequentSelectors difference: specialSelectors. "Should be
> special"
> }.
>
> #(
>        #(#'>=' #'~=' #/ #'\\' #bitShift: #'//' #bitAnd: #bitOr: #next
> #atEnd #blockCopy: #value #value: #x #y)
>        #(#, #assert: #first #name #add: #nextPutAll: #isEmpty #error:
> #asString #includes: #default #translated #not #on: #collect:))
>
> Another 40kB could be saved by changing these.
>
> Btw, there's a "free" bytecode: 200 - #blockCopy:.


I would like to reserve this for a page of new bytecodes, some of which I'd
like to use for adaptive optimization/speculative inlining work that Marcus,
Colin and I are planning to start in the new year.

best
Eliot


>
>  selector bytecodes look like this:
>>
>> Interpreter>>bytecodePrimNextPut
>>        messageSelector := self specialSelector: 20.
>>        argumentCount := 1.
>>        self normalSend.
>>
>> I.e., it just dispatches to normalSend where the regular lookup takes
>> place. Of course, that also means it'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).
>>
>> On to a finer point. The terminology "real message send" is misleading.
>> Generally, we (the VM hackers) mean by "real" 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
>> "real sends", and as a consequence writing "1 + 2" is not a real send by
>> that measure (with or without the bytecode present) since the primitive will
>> be executed successfully and no "real" send (method activation) has taken
>> place.
>>
>> To make matters more complicated, when we talk about "real" 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't process related would not have a suspension point but I don't know if
>> that's still true in Cog.
>>
>
> Thanks, this was very informative.
>
>
> Levente
>
>
>> Cheers,
>>  - Andreas
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20101130/f4655975/attachment.htm


More information about the Squeak-dev mailing list