Saturday, April 6, 2013

Still hacking LargeIntegerPlugins in interpreter VM

First thing, apologies for my bogus link of last post: it seems that
http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.315
triggers a bad bug in CCodeGenerator...
Indeed, the Smalltalk slang code:

    largeClass := isNegative
                    ifTrue: [objectMemory classLargeNegativeInteger]
                    ifFalse: [objectMemory classLargePositiveInteger].


generates this kind of C sentence:

    (test) ? statement1 , statement2 : statement3 , statement4;

which is apparently parsed as:

    ((test) ? statement1 , statement2 : statement3) , statement4;

Since the same slang is working perfectly in COG VM (different code generation) this bug stole me 2 hours of sleep last night, and I only understood the thing while posting an issue to vm-dev this evening.

So I provide a corrected package here if any one want to experiment:
http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.316

While at it last night, I could not resist and gave a try to the little hack which avoids allocation and copy of a new large integer and prefers an in place modification when the normalized integer fits in same number of words.
Since every object is allocated in 32-bit word boundaries in a 32bit VM, it's indeed possible to just modify some header bits which specify the size and leave the LargeInteger data unchanged. To make it short:
  • the byteSize rounded up to next word boundary is stored in a header word
  • the excess byte length (which is to be removed from this rounded byteSize) is stored in bits 8 & 9 of the previous header word (baseHeader >> 8 bitAnd: 3).
  • so we just need to change those 2 bits if (newByteSize+3 bitOr: 3)=(oldByteSize+3 bitOr: 3) - which means unchanged byteSize rounded up to next 4-bytes word boundary.
A similar technique should work for 64-bit word boundary in 64-bit VM which should be even more interesting (but I did not write a portable hack).

Of course such hack is fragile. If ever the object format happens to change (and it surely will), we would have to re-implement or remove it, but it's just for fun.

The code can be found at:
http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.317

As explained in commit comment, it is necessary to hack platform independent files platforms/Cross/vm/sqVirtualMachine.[ch] to register a new interpreterProxy function fixLast2BitsofByteLengthOf(). The function itself is implemented in ObjectMemory and generated in src/vm/interp.c.

This changes my micro-benchmarks a tiny bit:

Number of LargeInt operations per seconds for VM 4.10.10 vs hacked version 317




No comments:

Post a Comment