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