[Vm-dev] usage of bitShift: in VMMaker & plugins
Nicolas Cellier
nicolas.cellier.aka.nice at gmail.com
Fri Jan 8 13:06:09 UTC 2010
2010/1/8 David T. Lewis <lewis at mail.msen.com>:
>
> On Thu, Jan 07, 2010 at 08:07:03PM +0100, Nicolas Cellier wrote:
>>
>> Folks,
>> browsing generated code I see ugly things like this one:
>>
>> byte = jpegDecodeValueFromsize(dcTable, dcTableSize);
>> if (byte < 0) {
>> return interpreterProxy->primitiveFail();
>> }
>> if (byte != 0) {
>> bits = getBits(byte);
>> /* begin scaleAndSignExtend:inFieldWidth: */
>> if (bits < ((((byte - 1) < 0) ? ((usqInt) 1 >> -(byte - 1)) :
>> ((usqInt) 1 << (byte - 1))))) {
>> byte = (bits - (((byte < 0) ? ((usqInt) 1 >> -byte) : ((usqInt) 1
>> << byte)))) + 1;
>> goto l1;
>> } else {
>> byte = bits;
>> goto l1;
>> }
>> l1: /* end scaleAndSignExtend:inFieldWidth: */;
>> }
>>
>> You would never write such code by hand because it costs a useless
>> runtime test ()?:
>> And you know very well that byte > 0 when engaging the bitShift:
>> operation, so it should be:
>>
>> byte = jpegDecodeValueFromsize(dcTable, dcTableSize);
>> if (byte < 0) {
>> return interpreterProxy->primitiveFail();
>> }
>> if (byte != 0) {
>> bits = getBits(byte);
>> /* begin scaleAndSignExtend:inFieldWidth: */
>> if (bits < ((usqInt) 1 << (byte - 1))) {
>> byte = (bits - ((usqInt) 1 << byte)) + 1;
>> goto l1;
>> } else {
>> byte = bits;
>> goto l1;
>> }
>> l1: /* end scaleAndSignExtend:inFieldWidth: */;
>> }
>>
>> Of course, the generator cannot guess that easily when feeded with a
>> bitShift: and a non literal argument...
>> That's why we should use explicit << and >> directly in slang when we
>> know the argument will be positive.
>
> Good tip on the difference in generated code for explicit << and >>.
> However, I would change things like this with caution. The example you
> give above is actually generated from this method:
>
> scaleAndSignExtend: aNumber inFieldWidth: w
> self inline: true.
> aNumber < (1 >> (w - 1))
> ifTrue: [^aNumber - (1 bitShift: w) + 1]
> ifFalse: [^aNumber]
>
> There are no type declarations here, which means that the parameters
> are treated as either signed 32 or 64 integers depending on image
> format. This may or may not get mangled further by the slang inlining
> process, but in any event you are operating on signed values and you
> have no way of even knowing the size of the signed int. If in fact
> the method is only ever used for small positive integer values, then
> it would be fine to optimize it with the explicit shift operators.
>
100% agree, this deserve care.
> In this case there is no method comment, and the method name happens
> to be #blahAndSignExtend, which certainly would not lead anyone to
> expect that it is intended for use only on unsigned values. So it
> might go faster if you optimize it for use for small positive values,
> but you would definitely want to give it a different method name,
> remove the conditional handling for negative values, add some type
> declarations, and give it a method comment before doing so. (I think
> that is exactly the case for this example, and the method actually
> should be renamed and changed to take advantage of this. I'm just
> trying to illustrate a point.)
>
> There are lots of issues like this throughout the VM and the plugins.
> A few of them have been fixed, and many remain. Having personally
> slogged through a few of them in order to get the interpreter and
> a few plugins working on 64-bit machines, I have to say that I would
> generally rather see code that is safe but a little bit slow, and
> optimize it later in the hot spots.
>
Sure, hope this scale is universal:
make it right > make it fast
If in some cases we can make it both + simple, let's just do it :)
Maybe some of the 64bit uncompatibilities can be harvested by tracking
compiler warnings like these:
/Users/nicolas/Smalltalk/Squeak/trunk/src/vm/intplugins/SocketPlugin/SocketPlugin.c:288:0
Implicit declaration of function 'sqResolverGetAddressInfoFamily'
/Users/nicolas/Smalltalk/Squeak/trunk/src/vm/intplugins/AsynchFilePlugin/AsynchFilePlugin.c:237:0
Passing argument 2 of 'asyncFileReadResult' makes integer from pointer
without a cast
>> I did that for example in http://bugs.squeak.org/view.php?id=7109 but
>> see it could be generalized...
>> ... Of course with due care!
>
> Now that looks like a worthwhile optimization for sure. I have not
> looked at it, should it be pulled into the VMMaker package?
>
The speed up is around 30%, so I think it's worth.
It works for me on a custom i386 linux and i386 mac VM.
I can't see why it would not work on a big endian but I just can't test it.
Nicolas
>> Just my 2? tip of the day
>
> Good one, thanks.
>
> Dave
>
>
More information about the Vm-dev
mailing list