[Vm-dev] Potential issue of primitiveTimesTwoPower in Spur 64

Eliot Miranda eliot.miranda at gmail.com
Thu Feb 12 01:41:04 UTC 2015


Hi Nicolas,

On Wed, Feb 11, 2015 at 2:57 PM, Nicolas Cellier <
nicolas.cellier.aka.nice at gmail.com> wrote:

>
> Some C functions in libm only take an int, not a long.
> In 32 bits int=long, so no problem.
> In 64 bits generally int=32 bits, long=64 bits, so casting a long to int
> might lead to catastrophic loss and unexpected behavior.
>
> This is the case for example in primitiveTimesTwoPower
>     | rcvr arg |
>     <var: #rcvr type: #double>
>     arg := self popInteger.
>     rcvr := self popFloat.
>     self successful
>         ifTrue: [ self pushFloat: (self cCode: 'ldexp(rcvr, arg)'
> inSmalltalk: [rcvr timesTwoPower: arg]) ]
>         ifFalse: [ self unPop: 2 ]
>
> arg will be a long in Spur64, won't it?
> but ldexp only takes an int
>     double ldexp(double x, int exp);.
>
> So guess what if we call (1.0 timesTwoPower: 16r10000000001)...
> Normally there should be a C compiler warning, and we should care of it.
>
> To solve this, maybe we need a
>
>     <var: #arg type: #int>
>     arg := self signed32BitValueOf: stackTop.
>


I think we can check intelligently.  We know that for a finite non-zero
value,  ldexp(value, n) is infinite if n > (2 * max exponent) and zero if n
< (2 * max exponent), that for a NaN value, ldexp(value, n) is NaN and for
an infinite value ldexp(value,n) is infinite, and for a 0 value, it is
zero.  So I propose

primitiveTimesTwoPower
| rcvr result arg twiceMaxExponent |
<var: #rcvr type: #double>
<var: #result type: #double>
arg := self stackTop.
(objectMemory isIntegerObject: arg) ifFalse:
[^self primitiveFailFor: PrimErrBadArgument].
rcvr := objectMemory floatValueOf: (self stackValue: 1).
(self isFinite: rcvr) ifFalse:
[result := rcvr] ifTrue:
[arg := objectMemory integerValueOf: arg.
 twiceMaxExponent := 2 * (1 << self floatExponentBits).
 arg < twiceMaxExponent ifTrue:
[result := 0.0] ifFalse:
[arg > twiceMaxExponent ifTrue:
[result := 1.0e200 / 1.0e-200] ifFalse:
[result := self cCode: [self ld: rcvr exp: arg]
inSmalltalk: [rcvr timesTwoPower: arg]]]].
self pop: 2 thenPushFloat: result
-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20150211/192a372f/attachment.htm


More information about the Vm-dev mailing list