Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1058.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.1058 Author: eem Time: 12 February 2015, 10:06:39.955 am UUID: fdd2ee43-600b-4068-9956-dc6d59e05044 Ancestors: VMMaker.oscog-eem.1057
Revisit primitiveTimesTwoPower. Avoid complications in the 32-bit versions. Clip the argument in the 64-bit versions and avoid the compiler warning with a cast.
=============== Diff against VMMaker.oscog-eem.1057 ===============
Item was changed: ----- Method: FloatMathPlugin>>primitiveTimesTwoPower (in category 'float primitives') ----- primitiveTimesTwoPower + "Multiply the receiver by the power of the argument." + | rcvr arg result | - "Computes E raised to the receiver power." - | rcvr arg twiceMaxExponent result | <export: true> <var: #rcvr type: #double> <var: #result type: #double> arg := interpreterProxy stackIntegerValue: 0. rcvr := interpreterProxy stackFloatValue: 1. interpreterProxy failed ifTrue: [^nil]. + interpreterProxy bytesPerOop > 4 ifTrue: + [| twiceMaxExponent | "clip arg to at most int range; ldexp's last arg is of type int" + twiceMaxExponent := 2 * (1 << self floatExponentBits). + arg < twiceMaxExponent negated + ifTrue: [arg := twiceMaxExponent negated] + ifFalse: [arg > twiceMaxExponent ifTrue: + [arg := twiceMaxExponent]]]. + result := self cCode: '__ieee754_ldexp(rcvr, (int)arg)' + inSmalltalk: [rcvr timesTwoPower: arg]. + (self isnan: result) ifFalse: + [interpreterProxy methodReturnValue: (interpreterProxy floatObjectOf: result)]. + ^nil! - ((self isFinite: rcvr) and: [rcvr ~= 0.0]) - ifFalse: - [result := rcvr] - ifTrue: - [twiceMaxExponent := 2 * (1 << 11). - arg < twiceMaxExponent negated - ifTrue: - [result := rcvr < 0.0 ifTrue: [-0.0] ifFalse: [0.0]] - ifFalse: - [arg > twiceMaxExponent - ifTrue: - [result := rcvr < 0.0 ifTrue: [-1.0e200 / 1.0e-200] ifFalse: [1.0e200 / 1.0e-200]] - ifFalse: - [result := self cCode: '__ieee754_ldexp(rcvr, arg)' - inSmalltalk: [rcvr timesTwoPower: arg]]]]. - (self isnan: result) ifTrue: - [^interpreterProxy primitiveFail]. - interpreterProxy - pop: interpreterProxy methodArgumentCount + 1; - pushFloat: result!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveSmallFloatTimesTwoPower (in category 'arithmetic float primitives') ----- primitiveSmallFloatTimesTwoPower + "Multiply the receiver by the power of the argument." <option: #Spur64BitMemoryManager> | rcvr result arg twiceMaxExponent | - <var: #rcvr type: #double> - <var: #result type: #double> arg := self stackTop. (objectMemory isIntegerObject: arg) ifFalse: [^self primitiveFailFor: PrimErrBadArgument]. + rcvr := self stackValue: 1. + "N.B. SmallFloats are finite. NaN and Infinity overflow into boxed floats. + This is doing range checking work that is done in ldexp, but we include + it explicitly to exemplify bit manipulation of SmallFloats." + (objectMemory isSmallFloatZero: rcvr) - rcvr := objectMemory smallFloatValueOf: (self stackValue: 1). - "N.B. SmallFloats are finite. NaN and Infinity overflow into boxed floats." - rcvr = 0.0 ifTrue: [result := rcvr] ifFalse: [arg := objectMemory integerValueOf: arg. twiceMaxExponent := 2 * (1 << self floatExponentBits). arg < twiceMaxExponent negated ifTrue: + [result := objectMemory mapSignedSmallFloatToSignedSmallFloatZero: rcvr] - [result := rcvr < 0.0 ifTrue: [-0.0] ifFalse: [0.0]] ifFalse: + ["clip arg to at most int range; ldexp's last arg is of type int" + arg > twiceMaxExponent ifTrue: [arg := twiceMaxExponent]. + result := objectMemory floatObjectOf: (self cCode: [self ld: (objectMemory smallFloatValueOf: rcvr) + exp: (self cCoerceSimple: arg to: #int)] + inSmalltalk: [(objectMemory smallFloatValueOf: rcvr) timesTwoPower: arg])]]. + self pop: 2 thenPush: result! - [arg > twiceMaxExponent - ifTrue: - [result := rcvr < 0.0 ifTrue: [-1.0e200 / 1.0e-200] ifFalse: [1.0e200 / 1.0e-200]] - ifFalse: - [result := self cCode: [self ld: rcvr exp: arg] - inSmalltalk: [rcvr timesTwoPower: arg]]]]. - self pop: 2 thenPushFloat: result!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveTimesTwoPower (in category 'arithmetic float primitives') ----- primitiveTimesTwoPower + "Multiply the receiver by the power of the argument." <option: #Spur64BitMemoryManager> + | rcvr result arg | - | rcvr result arg twiceMaxExponent | <var: #rcvr type: #double> <var: #result type: #double> arg := self stackTop. (objectMemory isIntegerObject: arg) ifFalse: [^self primitiveFailFor: PrimErrBadArgument]. + arg := objectMemory integerValueOf: arg. + objectMemory bytesPerOop > 4 ifTrue: + [| twiceMaxExponent | "clip arg to at most int range; ldexp's last arg is of type int" + twiceMaxExponent := 2 * (1 << self floatExponentBits). + arg < twiceMaxExponent negated + ifTrue: [arg := twiceMaxExponent negated] + ifFalse: [arg > twiceMaxExponent ifTrue: + [arg := twiceMaxExponent]]]. rcvr := objectMemory floatValueOf: (self stackValue: 1). + result := self cCode: [self ld: rcvr exp: (self cCoerceSimple: arg to: #int)] + inSmalltalk: [rcvr timesTwoPower: arg]. - ((self isFinite: rcvr) and: [rcvr ~= 0]) - ifFalse: - [result := rcvr] - ifTrue: - [arg := objectMemory integerValueOf: arg. - twiceMaxExponent := 2 * (1 << self floatExponentBits). - arg < twiceMaxExponent negated - ifTrue: - [result := rcvr < 0.0 ifTrue: [-0.0] ifFalse: [0.0]] - ifFalse: - [arg > twiceMaxExponent - ifTrue: - [result := rcvr < 0.0 ifTrue: [-1.0e200 / 1.0e-200] ifFalse: [1.0e200 / 1.0e-200]] - ifFalse: - [result := self cCode: [self ld: rcvr exp: arg] - inSmalltalk: [rcvr timesTwoPower: arg]]]]. self pop: 2 thenPushFloat: result!
Item was added: + ----- Method: Spur64BitMemoryManager>>isNegativeSmallFloat: (in category 'interpreter access') ----- + isNegativeSmallFloat: aSmallFloat + <inline: true> + self assert: (self isImmediateFloat: aSmallFloat). + ^aSmallFloat anyMask: self smallFloatSignBit!
Item was added: + ----- Method: Spur64BitMemoryManager>>isSmallFloatZero: (in category 'interpreter access') ----- + isSmallFloatZero: aSmallFloat + <inline: true> + self assert: (self isImmediateFloat: aSmallFloat). + ^aSmallFloat asUnsignedInteger <= self negativeSmallFloatZero!
Item was added: + ----- Method: Spur64BitMemoryManager>>mapSignedSmallFloatToSignedSmallFloatZero: (in category 'interpreter access') ----- + mapSignedSmallFloatToSignedSmallFloatZero: aSmallFloat + <inline: true> + self assert: (self isImmediateFloat: aSmallFloat). + ^aSmallFloat bitAnd: self smallFloatSignBit + self tagMask!
Item was added: + ----- Method: Spur64BitMemoryManager>>negativeSmallFloatZero (in category 'interpreter access') ----- + negativeSmallFloatZero + <inline: true> + ^self smallFloatSignBit + self smallFloatTag!
Item was added: + ----- Method: Spur64BitMemoryManager>>positiveSmallFloatZero (in category 'interpreter access') ----- + positiveSmallFloatZero + <inline: true> + ^self smallFloatTag!
Item was changed: ----- Method: Spur64BitMemoryManager>>rotatedFloatBitsOf: (in category 'interpreter access') ----- rotatedFloatBitsOf: oop "Answer the signed, but unadjusted value of a SmallFloat64, suitable for use as a hash. Keeping the exponent unadjusted keeps the value in the SmallInteger range. See section 61-bit Immediate Floats in the SpurMemoryManager class comment. msb lsb Decode: [8expsubset][52mantissa][1s][3tags] shift away tags & sign: [ 0000 ][8expsubset][52mantissa] add sign: [ ssss ][8expsubset][52mantissa]" self assert: (self isImmediateFloat: oop). ^oop asUnsignedInteger >> (self numTagBits + 1) + + ((oop anyMask: self smallFloatSignBit) - + ((oop anyMask: 1 << self numTagBits) ifTrue: [-1 << (64 - self numTagBits - 1)] ifFalse: [0])!
Item was added: + ----- Method: Spur64BitMemoryManager>>smallFloatSignBit (in category 'interpreter access') ----- + smallFloatSignBit + <inline: true> + ^1 << self numTagBits!
vm-dev@lists.squeakfoundation.org