I noted the the current VMs don't handle the case of storing
−2,147,483,648 (primitive failure) via signed32BitValueOf: usually called via FFI signedLongAt:put: For plugin writers who used signed64BitValueOf: (primitive failure) and signed64BitIntegerFor: returned zero if passed −9,223,372,036,854,775,808. signed64BitIntegerFor: is the one that is nasty since your value of 0x8000000000000000 silently turns in 0. I reopened problem http://bugs.squeak.org/view.php?id=6987 and wrote some SUnits. I also provided a suggested fix, which allows me to run the SUnits. Lastly for Alien I added long long (signed/unsigned) support which is still missing in the FFI plugin so I could do some testing. -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
Hi John,
here's the fix for signed32BitValueOf: On Tue, Nov 25, 2008 at 11:15 PM, John M McIntosh <[hidden email]> wrote: I noted the the current VMs don't handle the case of storing −2,147,483,648 (primitive failure) via signed32BitValueOf: usually called via FFI signedLongAt:put: Interpreter-signed32BitValueOf.st (2K) Download Attachment |
Eliot thanks for this. I went with
(negative and: [value = (1<<31)]) ifTrue: [^value]. versus (negative and: [value - 1 > 0]) ifTrue: [^value]. I had hardcoded -2147483648 but got some ansi 99 compiler warning so I did the shift, I'd *think* the compiler will do the 1<<31 constant resolving and use the final value so we only have the compare, versus a subtraction and compare. Not that you could measure any performance differences In the Alien Sunits I cover the cases of 0 4294967295 -2147483648 2147483647 (for signed/unsigned) then do random sampling (10,000) elements of unsignedIntegerIntervalue := (0 to: 4294967295). signedIntegerIntervalue := (-2147483648 to: 2147483647). signedIntegerIntervalue := (-4294967295 to: -2147483649). should prim value signedIntegerIntervalue := (2147483648 to: 4294967295). should prim fail If someone wants to try they could run *all* the values from -0xFFFFFFFF 0xFFFFFFFF just to confirm *every* value works as expected since that would only take a few hours or less on the fast machines today. I note I do the 0xFFFFFFFF * (-1) because it's possible someone might pass that in and ask for a signed integer, in that case we of course fail until we reach the lowest 32bit signed integer value of -2147483648 (I so I assume) since I've not run the entire range, which is feasible. Obviously running the 64bit range could take a while. Anyone want to estimate? On 2-Dec-08, at 11:32 AM, Eliot Miranda wrote: > Hi John, > > here's the fix for signed32BitValueOf: > > > On Tue, Nov 25, 2008 at 11:15 PM, John M McIntosh <[hidden email] > > wrote: -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
2008/12/2 John M McIntosh <[hidden email]> Eliot thanks for this. I went with But value doesn't equal 1 << 31. It equals -(1 << 31). It only appears to equal 1 << 31 because 1 << 31 overflows. I think therefore mine is clearer.
Think about it, all less negative values must still be negative when one subtracts one. Only the most negative value will no longer be negative if one subtracts one. So I think mine also clearly selects the most negative value and only the most negative value.
I've attached the analogous fix for signed64BitValueOf:
The problem is that 1<<31 is a large constant whereas -1 is small. So the cost is not really in the arithmetic but in the memory fetch :) I bet there will be more bytes in the instructions for 1 << 31 than for the - 1 on most architectures. On the ARM 1<<31 is cheap, but TTBOMK only on ARM :)
Interpreter-signed64BitValueOf.st (2K) Download Attachment |
Also needed to be fixed are Interpreter>>signed64BitIntegerFor: and Interpreter>>primitiveSubtractLargeIntegers:. Find attached.
Once one fixes signed64BitValueFor: you'll find that (2 raisedToInteger: 63) negated - ((2 raisedToInteger: 63)-1) is zero :) i.e. subtract the most +ve integer from the most -ve and you get zero, because primitiveSubtractLargeIntegers: falls into exactly the same trap of assuming
0 - aValue is +ve for all -ve values, which isn't the case for the most -ve value. 2008/12/2 Eliot Miranda <[hidden email]>
Interpreter-signed64BitIntegerFor.st (1K) Download Attachment Interpreter-primitiveSubtractLargeIntegers.st (2K) Download Attachment MostNegativeVMFixes.cs (8K) Download Attachment |
I'm not sure I've seen a problem logged about that. On 2-Dec-08, at 1:57 PM, Eliot Miranda wrote: > Also needed to be fixed are Interpreter>>signed64BitIntegerFor: and > Interpreter>>primitiveSubtractLargeIntegers:. Find attached. > > Once one fixes signed64BitValueFor: you'll find that (2 > raisedToInteger: 63) negated - ((2 raisedToInteger: 63)-1) is > zero :) i.e. subtract the most +ve integer from the most -ve and > you get zero, because primitiveSubtractLargeIntegers: falls into > exactly the same trap of assuming > > 0 - aValue > > is +ve for all -ve values, which isn't the case for the most -ve > value. > -- = = = ======================================================================== John M. McIntosh <[hidden email]> Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com = = = ======================================================================== |
Free forum by Nabble | Edit this page |