<div dir="ltr">Hi Nicolas,<div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 17, 2016 at 3:24 PM, <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1732.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1732.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-nice.1732<br>
Author: nice<br>
Time: 17 March 2016, 11:22:07.715 pm<br>
UUID: ea9dd158-4847-464e-9642-9786252797dc<br>
Ancestors: VMMaker.oscog-nice.1731<br>
<br>
Use little endian accelerators too for fetching 32 & 64 bits large integers value (like the ones used for storing value).<br>
<br>
Dramatically simplify fetching of signedInteger values by using an intermediate unsigned magnitude.<br>
<br>
Declare the positive32/64BitIntegerFor: and maybeInlinePositive32BitIntegerFor: parameter as unsigned since it is interpreted as positive.<br>
<br>
Use asUnsignedInteger in isIntegerValue: tests, integerObjectOf: and rotatedFloatBitsOf: in order to ban potential UB.<br>
<br>
Simplify bit operations using positiveMachineIntegerValueOf:/positiveMachineIntegerFor: rather than doing 32/64 bits dissertation.<br>
<br>
Fetch magnitude of positive large ints into an unsigned for large int bit ops.<br></blockquote><div><br></div><div><br></div><div>In the following</div><div><br></div> ----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') -----<br> maybeInlinePositive32BitIntegerFor: integerValue<br> "N.B. will *not* cause a GC.<br> integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:."<br> <notOption: #Spur64BitMemoryManager><br>+ <var: 'integerValue' type: #'unsigned int'><br> | newLargeInteger |<br> self deny: objectMemory hasSixtyFourBitImmediates.<br>+ integerValue <= objectMemory maxSmallInteger<br>+ ifTrue: [^ objectMemory integerObjectOf: integerValue].<br>- (integerValue asInteger >= 0<br>- and: [objectMemory isIntegerValue: integerValue]) ifTrue:<br>- [^objectMemory integerObjectOf: integerValue].<br><div><br></div><div>shouldn't we compare against minSmallInteger as well, because e.g. -16r80000000 could overflow SmallInteger and answer 0?</div><div><br></div><div><br></div><div><br></div><div>P.S. Lovely seeing this code getting some good loving.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
=============== Diff against VMMaker.oscog-nice.1731 ===============<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>magnitude64BitIntegerFor:neg: (in category 'primitive support') -----<br>
magnitude64BitIntegerFor: magnitude neg: isNegative<br>
"Return a Large Integer object for the given integer magnitude and sign"<br>
| newLargeInteger largeClass highWord sz isSmall smallVal |<br>
<var: 'magnitude' type: #usqLong><br>
<var: 'highWord' type: #usqInt><br>
<br>
isSmall := isNegative<br>
ifTrue: [magnitude <= (objectMemory maxSmallInteger + 1)]<br>
ifFalse: [magnitude <= objectMemory maxSmallInteger].<br>
isSmall ifTrue:<br>
[smallVal := self cCoerceSimple: magnitude to: #sqInt.<br>
isNegative ifTrue: [smallVal := 0 - smallVal].<br>
^objectMemory integerObjectOf: smallVal].<br>
<br>
largeClass := isNegative<br>
ifTrue: [objectMemory classLargeNegativeInteger]<br>
ifFalse: [objectMemory classLargePositiveInteger].<br>
objectMemory wordSize = 8<br>
ifTrue: [sz := 8]<br>
ifFalse:<br>
[(highWord := magnitude >> 32) = 0<br>
ifTrue: [sz := 4]<br>
ifFalse:<br>
[sz := 5.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]].<br>
newLargeInteger := objectMemory instantiateClass: largeClass indexableSize: sz.<br>
self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[sz > 4 ifTrue:<br>
[objectMemory<br>
storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF);<br>
storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF);<br>
storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF);<br>
storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)].<br>
objectMemory<br>
storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF);<br>
storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF);<br>
storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF);<br>
storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)]<br>
ifFalse:<br>
+ [sz > 4<br>
+ ifTrue: [objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: magnitude]<br>
+ ifFalse: [objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].<br>
- [sz > 4 ifTrue:<br>
- [objectMemory storeLong32: 1 ofObject: newLargeInteger withValue: magnitude >> 32].<br>
- objectMemory<br>
- storeLong32: 0<br>
- ofObject: newLargeInteger<br>
- withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])].<br>
<br>
^newLargeInteger!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>magnitude64BitValueOf: (in category 'primitive support') -----<br>
magnitude64BitValueOf: oop<br>
"Convert the given object into an integer value.<br>
The object may be either a positive SmallInteger or an eight-byte LargeInteger."<br>
| sz value ok smallIntValue |<br>
<returnTypeC: #usqLong><br>
<var: #value type: #usqLong><br>
<br>
(objectMemory isIntegerObject: oop) ifTrue:<br>
[smallIntValue := (objectMemory integerValueOf: oop).<br>
smallIntValue < 0 ifTrue: [smallIntValue := 0 - smallIntValue].<br>
^self cCoerce: smallIntValue to: #usqLong].<br>
<br>
(objectMemory isNonIntegerImmediate: oop) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargePositiveInteger)<br>
compactClassIndex: ClassLargePositiveIntegerCompactIndex.<br>
ok<br>
ifFalse:<br>
[ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargeNegativeInteger)<br>
compactClassIndex: ClassLargeNegativeIntegerCompactIndex.<br>
ok ifFalse:<br>
[self primitiveFail.<br>
^0]].<br>
sz := objectMemory numBytesOfBytes: oop.<br>
sz > (self sizeof: #sqLong) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
+ self cppIf: VMBIGENDIAN<br>
+ ifTrue:<br>
+ [value := objectMemory fetchByte: sz - 1 ofObject: oop.<br>
+ sz - 2 to: 0 by: -1 do:<br>
+ [:i | value := value << 8 + (objectMemory fetchByte: i ofObject: oop)]]<br>
+ ifFalse:<br>
+ [sz > 4<br>
+ ifTrue: [value := self cCoerceSimple: (objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]<br>
+ ifFalse: [value := self cCoerceSimple: (objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].<br>
- value := objectMemory fetchByte: sz - 1 ofObject: oop.<br>
- sz - 2 to: 0 by: -1 do:<br>
- [:i | value := value << 8 + (objectMemory fetchByte: i ofObject: oop)].<br>
^value!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>positive64BitValueOf: (in category 'primitive support') -----<br>
positive64BitValueOf: oop<br>
"Convert the given object into an integer value.<br>
The object may be either a positive SmallInteger or an eight-byte LargePositiveInteger."<br>
<br>
<returnTypeC: #usqLong><br>
| sz value ok |<br>
<var: #value type: #usqLong><br>
(objectMemory isIntegerObject: oop) ifTrue:<br>
[(objectMemory integerValueOf: oop) < 0 ifTrue:<br>
[^self primitiveFail].<br>
^objectMemory integerValueOf: oop].<br>
<br>
(objectMemory isNonIntegerImmediate: oop) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
ok := objectMemory<br>
isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargePositiveInteger)<br>
compactClassIndex: ClassLargePositiveIntegerCompactIndex.<br>
ok ifFalse:<br>
[self primitiveFail.<br>
^0].<br>
sz := objectMemory numBytesOfBytes: oop.<br>
sz > (self sizeof: #sqLong) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
+ self cppIf: VMBIGENDIAN<br>
+ ifTrue:<br>
+ [value := 0.<br>
+ 0 to: sz - 1 do: [:i |<br>
+ value := value + ((self cCoerce: (objectMemory fetchByte: i ofObject: oop) to: #usqLong) << (i*8))]]<br>
+ ifFalse:<br>
+ [sz > 4<br>
+ ifTrue: [value := self cCoerceSimple: (objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]<br>
+ ifFalse: [value := self cCoerceSimple: (objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].<br>
- value := 0.<br>
- 0 to: sz - 1 do: [:i |<br>
- value := value + ((self cCoerce: (objectMemory fetchByte: i ofObject: oop) to: #usqLong) << (i*8))].<br>
^value!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitAnd (in category 'arithmetic integer primitives') -----<br>
primitiveBitAnd<br>
<inline: false><br>
+ <var: 'integerArgument' type: #usqInt><br>
+ <var: 'intergerReceiver' type: #usqInt><br>
| integerReceiver integerArgument |<br>
integerArgument := self stackTop.<br>
integerReceiver := self stackValue: 1.<br>
"Comment out the short-cut. Either the inline interpreter bytecode or the JIT primitive will handle this case.<br>
((objectMemory isIntegerObject: integerArgument)<br>
and: [objectMemory isIntegerObject: integerReceiver])<br>
ifTrue: [self pop: 2 thenPush: (integerArgument bitAnd: integerReceiver)]<br>
ifFalse:<br>
+ ["<br>
+ integerArgument := self positiveMachineIntegerValueOf: integerArgument.<br>
+ integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.<br>
+ self successful ifTrue:<br>
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitAnd: integerReceiver))]<br>
- ["objectMemory wordSize = 8<br>
- ifTrue:<br>
- [integerArgument := self positive64BitValueOf: integerArgument.<br>
- integerReceiver := self positive64BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive64BitIntegerFor: (integerArgument bitAnd: integerReceiver))]]<br>
ifFalse:<br>
+ []"]"!<br>
- [integerArgument := self positive32BitValueOf: integerArgument.<br>
- integerReceiver := self positive32BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive32BitIntegerFor: (integerArgument bitAnd: integerReceiver))]]"]"!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitAndLargeIntegers (in category 'arithmetic largeint primitives') -----<br>
primitiveBitAndLargeIntegers<br>
"Primitive logical operations for large integers in 64 bit range"<br>
| integerRcvr integerArg oopResult |<br>
<export: true><br>
+ <var: 'integerRcvr' type: 'usqLong'><br>
+ <var: 'integerArg' type: 'usqLong'><br>
- <var: 'integerRcvr' type: 'sqLong'><br>
- <var: 'integerArg' type: 'sqLong'><br>
<br>
integerArg := self positive64BitValueOf: (self stackValue: 0).<br>
integerRcvr := self positive64BitValueOf: (self stackValue: 1).<br>
self successful ifFalse:[^nil].<br>
<br>
oopResult := self positive64BitIntegerFor: (integerRcvr bitAnd: integerArg).<br>
self successful ifTrue:[self pop: 2 thenPush: oopResult]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitOr (in category 'arithmetic integer primitives') -----<br>
primitiveBitOr<br>
<inline: false><br>
+ <var: 'integerArgument' type: #usqInt><br>
+ <var: 'intergerReceiver' type: #usqInt><br>
| integerReceiver integerArgument |<br>
integerArgument := self stackTop.<br>
integerReceiver := self stackValue: 1.<br>
"Comment out the short-cut. Either the inline interpreter bytecode or the JIT primitive will handle this case.<br>
((objectMemory isIntegerObject: integerArgument)<br>
and: [objectMemory isIntegerObject: integerReceiver])<br>
ifTrue: [self pop: 2 thenPush: (integerArgument bitOr: integerReceiver)]<br>
ifFalse:<br>
+ ["<br>
+ integerArgument := self positiveMachineIntegerValueOf: integerArgument.<br>
+ integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.<br>
+ self successful ifTrue:<br>
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitOr: integerReceiver))]<br>
- ["objectMemory wordSize = 8<br>
- ifTrue:<br>
- [integerArgument := self positive64BitValueOf: integerArgument.<br>
- integerReceiver := self positive64BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive64BitIntegerFor: (integerArgument bitOr: integerReceiver))]]<br>
ifFalse:<br>
+ []"]"!<br>
- [integerArgument := self positive32BitValueOf: integerArgument.<br>
- integerReceiver := self positive32BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive32BitIntegerFor: (integerArgument bitOr: integerReceiver))]]"]"!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitOrLargeIntegers (in category 'arithmetic largeint primitives') -----<br>
primitiveBitOrLargeIntegers<br>
"Primitive logical operations for large integers in 64 bit range"<br>
| integerRcvr integerArg oopResult |<br>
<export: true><br>
+ <var: 'integerRcvr' type: 'usqLong'><br>
+ <var: 'integerArg' type: 'usqLong'><br>
- <var: 'integerRcvr' type: 'sqLong'><br>
- <var: 'integerArg' type: 'sqLong'><br>
<br>
integerArg := self positive64BitValueOf: (self stackValue: 0).<br>
integerRcvr := self positive64BitValueOf: (self stackValue: 1).<br>
self successful ifFalse:[^nil].<br>
<br>
oopResult := self positive64BitIntegerFor: (integerRcvr bitOr: integerArg).<br>
self successful ifTrue:[self pop: 2 thenPush: oopResult]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitXor (in category 'arithmetic integer primitives') -----<br>
primitiveBitXor<br>
<inline: false><br>
| integerReceiver integerArgument |<br>
integerArgument := self stackTop.<br>
integerReceiver := self stackValue: 1.<br>
((objectMemory isIntegerObject: integerArgument)<br>
and: [objectMemory isIntegerObject: integerReceiver])<br>
ifTrue: "xoring will leave the tag bits zero, whether the tag is 1 or zero, so add it back in."<br>
[self pop: 2 thenPush: (integerArgument bitXor: integerReceiver) + objectMemory smallIntegerTag]<br>
ifFalse:<br>
+ [integerArgument := self positiveMachineIntegerValueOf: integerArgument.<br>
+ integerReceiver := self positiveMachineIntegerValueOf: integerReceiver.<br>
+ self successful ifTrue:<br>
+ [self pop: 2 thenPush: (self positiveMachineIntegerFor: (integerArgument bitXor: integerReceiver))]]!<br>
- [objectMemory wordSize = 8<br>
- ifTrue:<br>
- [integerArgument := self positive64BitValueOf: integerArgument.<br>
- integerReceiver := self positive64BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive64BitIntegerFor: (integerArgument bitXor: integerReceiver))]]<br>
- ifFalse:<br>
- [integerArgument := self positive32BitValueOf: integerArgument.<br>
- integerReceiver := self positive32BitValueOf: integerReceiver.<br>
- self successful ifTrue:<br>
- [self pop: 2 thenPush: (self positive32BitIntegerFor: (integerArgument bitXor: integerReceiver))]]]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveBitXorLargeIntegers (in category 'arithmetic largeint primitives') -----<br>
primitiveBitXorLargeIntegers<br>
"Primitive logical operations for large integers in 64 bit range"<br>
| integerRcvr integerArg oopResult |<br>
<export: true><br>
+ <var: 'integerRcvr' type: 'usqLong'><br>
+ <var: 'integerArg' type: 'usqLong'><br>
- <var: 'integerRcvr' type: 'sqLong'><br>
- <var: 'integerArg' type: 'sqLong'><br>
<br>
integerArg := self positive64BitValueOf: (self stackValue: 0).<br>
integerRcvr := self positive64BitValueOf: (self stackValue: 1).<br>
self successful ifFalse:[^nil].<br>
<br>
oopResult := self positive64BitIntegerFor: (integerRcvr bitXor: integerArg).<br>
self successful ifTrue:[self pop: 2 thenPush: oopResult]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>signed32BitValueOf: (in category 'primitive support') -----<br>
signed32BitValueOf: oop<br>
"Convert the given object into an integer value.<br>
The object may be either a positive SmallInteger or a four-byte LargeInteger."<br>
+ | value negative ok magnitude |<br>
- | value negative ok |<br>
<inline: false><br>
<returnTypeC: #int><br>
<var: #value type: #int><br>
+ <var: #magnitude type: #'unsigned int'><br>
<var: #value64 type: #long><br>
(objectMemory isIntegerObject: oop) ifTrue:<br>
[objectMemory wordSize = 4<br>
ifTrue:<br>
[^objectMemory integerValueOf: oop]<br>
ifFalse: "Must fail for SmallIntegers with digitLength > 4"<br>
[| value64 |<br>
value64 := objectMemory integerValueOf: oop.<br>
(self cCode: [(self cCoerceSimple: value64 to: #int) ~= value64]<br>
inSmalltalk: [value64 >> 31 ~= 0 and: [value64 >> 31 ~= -1]]) ifTrue:<br>
[self primitiveFail. value64 := 0].<br>
^value64]].<br>
<br>
(objectMemory isNonIntegerImmediate: oop) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
ok := objectMemory<br>
isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargePositiveInteger)<br>
compactClassIndex: ClassLargePositiveIntegerCompactIndex.<br>
ok<br>
ifTrue: [negative := false]<br>
ifFalse:<br>
[negative := true.<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargeNegativeInteger)<br>
compactClassIndex: ClassLargeNegativeIntegerCompactIndex.<br>
ok ifFalse:<br>
[self primitiveFail.<br>
^0]].<br>
(objectMemory numBytesOfBytes: oop) > 4 ifTrue:<br>
[^self primitiveFail].<br>
<br>
+ magnitude := self cppIf: VMBIGENDIAN<br>
- value := self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[ (objectMemory fetchByte: 0 ofObject: oop) +<br>
((objectMemory fetchByte: 1 ofObject: oop) << 8) +<br>
((objectMemory fetchByte: 2 ofObject: oop) << 16) +<br>
((objectMemory fetchByte: 3 ofObject: oop) << 24)]<br>
ifFalse:<br>
+ [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger].<br>
+<br>
+ (negative<br>
+ ifTrue: [magnitude > 16r80000000]<br>
+ ifFalse: [magnitude >= 16r80000000])<br>
+ ifTrue:<br>
+ [self primitiveFail.<br>
+ ^0].<br>
+ negative<br>
+ ifTrue: [value := 0 - magnitude]<br>
+ ifFalse: [value := magnitude].<br>
+ ^value!<br>
- [objectMemory fetchLong32: 0 ofObject: oop].<br>
- self cCode: []<br>
- inSmalltalk:<br>
- [(value anyMask: 16r80000000) ifTrue:<br>
- [value := value - 16r100000000]].<br>
- "Filter out values out of range for the signed interpretation such as<br>
- 16rFFFFFFFF (positive w/ bit 32 set) and -16rFFFFFFFF (negative w/ bit<br>
- 32 set). Since the sign is implicit in the class we require that the high<br>
- bit of the magnitude is not set which is a simple test here. Note that<br>
- we have to handle the most negative 32-bit value -2147483648 specially."<br>
- value < 0 ifTrue:<br>
- [self assert: (self sizeof: value) == 4.<br>
- "Don't fail for -16r80000000/-2147483648<br>
- Alas the simple (negative and: [value - 1 > 0]) isn't adequate since in C the result of signed integer<br>
- overflow is undefined and hence under optimization this may fail. The shift, however, is well-defined."<br>
- (negative and: [0 = (self cCode: [value << 1]<br>
- inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:<br>
- [^value].<br>
- self primitiveFail.<br>
- ^0].<br>
- ^negative<br>
- ifTrue: [0 - value]<br>
- ifFalse: [value]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>signed64BitValueOf: (in category 'primitive support') -----<br>
signed64BitValueOf: oop<br>
"Convert the given object into an integer value.<br>
The object may be either a positive SmallInteger or a eight-byte LargeInteger."<br>
+ | sz value negative ok magnitude |<br>
- | sz value negative ok |<br>
<inline: false><br>
<returnTypeC: #sqLong><br>
<var: #value type: #sqLong><br>
+ <var: #magnitude type: #usqLong><br>
(objectMemory isIntegerObject: oop) ifTrue:<br>
[^self cCoerce: (objectMemory integerValueOf: oop) to: #sqLong].<br>
<br>
(objectMemory isNonIntegerImmediate: oop) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargePositiveInteger)<br>
compactClassIndex: ClassLargePositiveIntegerCompactIndex.<br>
ok<br>
ifTrue: [negative := false]<br>
ifFalse:<br>
[negative := true.<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargeNegativeInteger)<br>
compactClassIndex: ClassLargeNegativeIntegerCompactIndex.<br>
ok ifFalse:<br>
[self primitiveFail.<br>
^0]].<br>
sz := objectMemory numBytesOfBytes: oop.<br>
sz > (self sizeof: #sqLong) ifTrue:<br>
[self primitiveFail.<br>
^0].<br>
<br>
self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
+ [magnitude := objectMemory fetchByte: sz - 1 ofObject: oop.<br>
- [value := objectMemory fetchByte: sz - 1 ofObject: oop.<br>
sz - 2 to: 0 by: -1 do: [:i |<br>
+ magnitude := magnitude << 8 + (objectMemory fetchByte: i ofObject: oop)]]<br>
- value := value << 8 + (objectMemory fetchByte: i ofObject: oop)]]<br>
ifFalse:<br>
+ [magnitude := sz > 4<br>
- [value := sz > 4<br>
ifTrue: [objectMemory fetchLong64: 0 ofObject: oop]<br>
ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].<br>
+<br>
+ (negative<br>
+ ifTrue: [magnitude > 16r8000000000000000]<br>
+ ifFalse: [magnitude >= 16r8000000000000000])<br>
+ ifTrue: [self primitiveFail.<br>
+ ^0].<br>
+ negative<br>
+ ifTrue: [value := 0 - magnitude]<br>
+ ifFalse: [value := magnitude].<br>
+ ^value!<br>
- "Filter out values out of range for the signed interpretation such as<br>
- 16rFFFFFFFF... (positive w/ bit 64 set) and -16rFFFFFFFF... (negative w/ bit<br>
- 64 set). Since the sign is implicit in the class we require that the high bit of<br>
- the magnitude is not set which is a simple test here. Note that we have to<br>
- handle the most negative 64-bit value -9223372036854775808 specially."<br>
- self cCode: []<br>
- inSmalltalk:<br>
- [(value anyMask: 16r8000000000000000) ifTrue:<br>
- [value := value - 16r10000000000000000]].<br>
- value < 0 ifTrue:<br>
- [self cCode:<br>
- [self assert: (self sizeof: value) == 8.<br>
- self assert: (self sizeof: value << 1) == 8].<br>
- "Don't fail for -9223372036854775808/-16r8000000000000000.<br>
- Alas the simple (negative and: [value - 1 > 0]) isn't adequate since in C the result of signed integer<br>
- overflow is undefined and hence under optimization this may fail. The shift, however, is well-defined."<br>
- (negative and: [0 = (self cCode: [value << 1]<br>
- inSmalltalk: [value << 1 bitAnd: (1 << 64) - 1])]) ifTrue:<br>
- [^value].<br>
- self primitiveFail.<br>
- ^0].<br>
- ^negative<br>
- ifTrue:[0 - value]<br>
- ifFalse:[value]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>signedMachineIntegerValueOf: (in category 'primitive support') -----<br>
signedMachineIntegerValueOf: oop<br>
"Answer a signed value of an integer up to the size of a machine word.<br>
The object may be either a positive SmallInteger or a LargeInteger of size <= word size."<br>
<returnTypeC: #'long'><br>
+ | negative ok bs value limit magnitude |<br>
- | negative ok bs value bits |<br>
<var: #value type: #long><br>
+ <var: #magnitude type: #usqInt><br>
+ <var: #limit type: #usqInt><br>
(objectMemory isIntegerObject: oop) ifTrue:<br>
[^objectMemory integerValueOf: oop].<br>
<br>
(objectMemory isNonIntegerImmediate: oop) ifTrue:<br>
[^self primitiveFail].<br>
<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargePositiveInteger)<br>
compactClassIndex: ClassLargePositiveIntegerCompactIndex.<br>
ok<br>
ifTrue: [negative := false]<br>
ifFalse:<br>
[negative := true.<br>
ok := objectMemory isClassOfNonImm: oop<br>
equalTo: (objectMemory splObj: ClassLargeNegativeInteger)<br>
compactClassIndex: ClassLargeNegativeIntegerCompactIndex.<br>
ok ifFalse: [^self primitiveFail]].<br>
bs := objectMemory numBytesOf: oop.<br>
bs > (self sizeof: #'unsigned long') ifTrue:<br>
[^self primitiveFail].<br>
<br>
((self sizeof: #'unsigned long') = 8<br>
and: [bs > 4]) ifTrue:<br>
+ [magnitude := self cppIf: VMBIGENDIAN<br>
- [value := self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[ (objectMemory fetchByte: 0 ofObject: oop)<br>
+ ((objectMemory fetchByte: 1 ofObject: oop) << 8)<br>
+ ((objectMemory fetchByte: 2 ofObject: oop) << 16)<br>
+ ((objectMemory fetchByte: 3 ofObject: oop) << 24)<br>
+ ((objectMemory fetchByte: 4 ofObject: oop) << 32)<br>
+ ((objectMemory fetchByte: 5 ofObject: oop) << 40)<br>
+ ((objectMemory fetchByte: 6 ofObject: oop) << 48)<br>
+ ((objectMemory fetchByte: 7 ofObject: oop) << 56)]<br>
ifFalse:<br>
[objectMemory fetchLong64: 0 ofObject: oop]]<br>
ifFalse:<br>
+ [magnitude := self cppIf: VMBIGENDIAN<br>
- [value := self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[ (objectMemory fetchByte: 0 ofObject: oop)<br>
+ ((objectMemory fetchByte: 1 ofObject: oop) << 8)<br>
+ ((objectMemory fetchByte: 2 ofObject: oop) << 16)<br>
+ ((objectMemory fetchByte: 3 ofObject: oop) << 24)]<br>
ifFalse:<br>
[(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].<br>
+<br>
+ limit := 1 asUnsignedInteger << ((self sizeof: #usqInt) * 8 - 1).<br>
+ (negative<br>
+ ifTrue: [magnitude > limit]<br>
+ ifFalse: [magnitude >= limit])<br>
+ ifTrue: [self primitiveFail.<br>
+ ^0].<br>
+ negative<br>
+ ifTrue: [value := 0 - magnitude]<br>
+ ifFalse: [value := magnitude].<br>
+ ^value!<br>
-<br>
- self cCode: []<br>
- inSmalltalk:<br>
- [bits := (self sizeof: #long) * 8.<br>
- (value bitShift: 1 - bits) > 0 ifTrue:<br>
- [value := value - (1 bitShift: bits)]].<br>
- value < 0 ifTrue:<br>
- ["Don't fail for -16r80000000[00000000].<br>
- Alas the simple (negative and: [value - 1 > 0]) isn't adequate since in C the result of signed integer<br>
- overflow is undefined and hence under optimization this may fail. The shift, however, is well-defined."<br>
- (negative and: [0 = (self cCode: [value << 1]<br>
- inSmalltalk: [value << 1 bitAnd: (1 << bits) - 1])]) ifTrue:<br>
- [^value].<br>
- ^self primitiveFail].<br>
- ^negative<br>
- ifTrue: [0 - value]<br>
- ifFalse: [value]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterProxy>>positive32BitIntegerFor: (in category 'converting') -----<br>
positive32BitIntegerFor: integerValue<br>
+ <var: 'integerValue' type: #'unsigned int'><br>
integerValue isInteger ifFalse:[self error:'Not an Integer object'].<br>
^integerValue > 0<br>
ifTrue:[integerValue]<br>
ifFalse:[ (1 bitShift: 32) + integerValue]!<br>
<br>
Item was changed:<br>
----- Method: InterpreterProxy>>positive64BitIntegerFor: (in category 'converting') -----<br>
positive64BitIntegerFor: integerValue<br>
<api><br>
<returnTypeC: #sqInt> "...because answering the 64-bit argument causes the type inferencer to say this answers 64-bits."<br>
+ <var: 'integerValue' type: #usqLong><br>
- <var: 'integerValue' type: #sqLong><br>
integerValue isInteger ifFalse:[self error:'Not an Integer object'].<br>
^integerValue > 0<br>
ifTrue:[integerValue]<br>
ifFalse:[ (1 bitShift: 64) + integerValue]!<br>
<br>
Item was changed:<br>
----- Method: ObjectMemory>>isIntegerValue: (in category 'interpreter access') -----<br>
isIntegerValue: intValue<br>
"Answer if the given value can be represented as a Smalltalk integer value.<br>
In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given<br>
value are the same, then test the sign bit. Note that the top two bits are equal for<br>
exactly those integers in the range that can be represented in 31-bits or 63-bits."<br>
<api><br>
^self<br>
+ cCode: [(intValue asUnsignedInteger bitXor: (intValue asUnsignedInteger << 1)) asInteger >= 0]<br>
+ inSmalltalk: [intValue >= self minSmallInteger and: [intValue <= self maxSmallInteger]]!<br>
- cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]<br>
- inSmalltalk: [intValue >= 16r-40000000 and: [intValue <= 16r3FFFFFFF]]!<br>
<br>
Item was changed:<br>
----- Method: Spur32BitMemoryManager>>isIntegerValue: (in category 'interpreter access') -----<br>
isIntegerValue: intValue<br>
"Answer if the given value can be represented as a Smalltalk integer value.<br>
In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given<br>
value are the same, then test the sign bit. Note that the top two bits are equal for<br>
exactly those integers in the range that can be represented in 31-bits or 63-bits."<br>
<api><br>
^self<br>
+ cCode: [(intValue asUnsignedInteger bitXor: (intValue asUnsignedInteger << 1)) asInteger >= 0]<br>
+ inSmalltalk: [intValue >= self minSmallInteger and: [intValue <= self maxSmallInteger]]!<br>
- cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]<br>
- inSmalltalk: [intValue >= 16r-40000000 and: [intValue <= 16r3FFFFFFF]]!<br>
<br>
Item was changed:<br>
----- Method: Spur64BitMemoryManager>>integerObjectOf: (in category 'immediates') -----<br>
integerObjectOf: value<br>
"Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object.<br>
In C, use a shift and an add to set the tag bit.<br>
In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns."<br>
<returnTypeC: #sqInt><br>
^self<br>
+ cCode: [value asUnsignedInteger << self numTagBits + 1]<br>
- cCode: [value << self numTagBits + 1]<br>
inSmalltalk: [value << self numTagBits<br>
+ (value >= 0<br>
ifTrue: [1]<br>
ifFalse: [16r10000000000000001])]!<br>
<br>
Item was changed:<br>
----- Method: Spur64BitMemoryManager>>isIntegerValue: (in category 'interpreter access') -----<br>
isIntegerValue: intValue<br>
"Answer if the given value can be represented as a Smalltalk integer value.<br>
In 64-bits we use a 3 bit tag which leaves 61 bits for 2's complement signed<br>
integers. In C, use a shift add and mask to test if the top 4 bits are all the same.<br>
Since 16rFFFFFFFFFFFFFFFF >> 60 = 16rF the computation intValue >> 60 + 1 bitAnd: 16rF<br>
maps in-range -ve values to 0 and in-range +ve values to 1."<br>
<api><br>
^self<br>
cCode: [(intValue >> 60 + 1 bitAnd: 16rF) <= 1] "N.B. (16rFFFFFFFFFFFFFFFF >> 60) + 1 = 16"<br>
+ inSmalltalk: [intValue >= self minSmallInteger and: [intValue <= self maxSmallInteger]]!<br>
- inSmalltalk: [intValue >= -16r1000000000000000 and: [intValue <= 16rFFFFFFFFFFFFFFF]]!<br>
<br>
Item was changed:<br>
----- Method: Spur64BitMemoryManager>>rotatedFloatBitsOf: (in category 'interpreter access') -----<br>
rotatedFloatBitsOf: oop<br>
"Answer the signed, but unadjusted value of a SmallFloat64, suitable for use as a hash.<br>
Keeping the exponent unadjusted keeps the value in the SmallInteger range.<br>
See section 61-bit Immediate Floats in the SpurMemoryManager class comment.<br>
msb lsb<br>
Decode: [8expsubset][52mantissa][1s][3tags]<br>
shift away tags & sign: [ 0000 ][8expsubset][52mantissa]<br>
add sign: [ ssss ][8expsubset][52mantissa]"<br>
self assert: (self isImmediateFloat: oop).<br>
^oop asUnsignedInteger >> (self numTagBits + 1)<br>
+ ((oop anyMask: self smallFloatSignBit)<br>
+ ifTrue: [-1 asUnsignedInteger << (64 - self numTagBits - 1)]<br>
- ifTrue: [-1 << (64 - self numTagBits - 1)]<br>
ifFalse: [0])!<br>
<br>
Item was changed:<br>
----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') -----<br>
maybeInlinePositive32BitIntegerFor: integerValue<br>
"N.B. will *not* cause a GC.<br>
integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:."<br>
<notOption: #Spur64BitMemoryManager><br>
+ <var: 'integerValue' type: #'unsigned int'><br>
| newLargeInteger |<br>
self deny: objectMemory hasSixtyFourBitImmediates.<br>
+ integerValue <= objectMemory maxSmallInteger<br>
+ ifTrue: [^ objectMemory integerObjectOf: integerValue].<br>
- (integerValue asInteger >= 0<br>
- and: [objectMemory isIntegerValue: integerValue]) ifTrue:<br>
- [^objectMemory integerObjectOf: integerValue].<br>
newLargeInteger := objectMemory<br>
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex<br>
format: (objectMemory byteFormatForNumBytes: 4)<br>
numSlots: 1.<br>
self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[objectMemory<br>
storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF);<br>
storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF);<br>
storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF);<br>
storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)]<br>
ifFalse:<br>
[objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: integerValue].<br>
^newLargeInteger!<br>
<br>
Item was changed:<br>
----- Method: StackInterpreter>>positive32BitIntegerFor: (in category 'primitive support') -----<br>
positive32BitIntegerFor: integerValue<br>
"integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:.<br>
N.B. Returning in each arm separately enables Slang inlining.<br>
/Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed."<br>
<inline: true><br>
+ <var: 'integerValue' type: #'unsigned int'><br>
objectMemory hasSixtyFourBitImmediates<br>
ifTrue:<br>
[^objectMemory integerObjectOf: (integerValue bitAnd: 16rFFFFFFFF)]<br>
ifFalse:<br>
[^self maybeInlinePositive32BitIntegerFor: integerValue]!<br>
<br>
Item was changed:<br>
----- Method: StackInterpreter>>positive64BitIntegerFor: (in category 'primitive support') -----<br>
positive64BitIntegerFor: integerValue<br>
<api><br>
+ <var: 'integerValue' type: #usqLong><br>
+ <var: 'highWord' type: #'unsigned int'><br>
- <var: 'integerValue' type: #sqLong><br>
"Answer a Large Positive Integer object for the given integer value. N.B. will *not* cause a GC."<br>
| newLargeInteger highWord sz |<br>
objectMemory hasSixtyFourBitImmediates<br>
ifTrue:<br>
+ [integerValue <= objectMemory maxSmallInteger ifTrue:<br>
- [(integerValue >= 0 and: [objectMemory isIntegerValue: integerValue]) ifTrue:<br>
[^objectMemory integerObjectOf: integerValue].<br>
sz := 8]<br>
ifFalse:<br>
+ [(highWord := integerValue >> 32) = 0 ifTrue:<br>
- [(highWord := integerValue >>> 32) = 0 ifTrue:<br>
[^self positive32BitIntegerFor: integerValue].<br>
sz := 5.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse:[sz := sz + 1]]]].<br>
newLargeInteger := objectMemory<br>
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex<br>
format: (objectMemory byteFormatForNumBytes: sz)<br>
numSlots: 8 / objectMemory bytesPerOop.<br>
self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[objectMemory<br>
storeByte: 7 ofObject: newLargeInteger withValue: (integerValue >> 56 bitAnd: 16rFF);<br>
storeByte: 6 ofObject: newLargeInteger withValue: (integerValue >> 48 bitAnd: 16rFF);<br>
storeByte: 5 ofObject: newLargeInteger withValue: (integerValue >> 40 bitAnd: 16rFF);<br>
storeByte: 4 ofObject: newLargeInteger withValue: (integerValue >> 32 bitAnd: 16rFF);<br>
storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF);<br>
storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF);<br>
storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF);<br>
storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)]<br>
ifFalse:<br>
[objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: integerValue].<br>
^newLargeInteger<br>
!<br>
<br>
Item was changed:<br>
----- Method: StackInterpreter>>signed64BitIntegerFor: (in category 'primitive support') -----<br>
signed64BitIntegerFor: integerValue<br>
<var: 'integerValue' type: #sqLong><br>
"Answer a Large Integer object for the given integer value. N.B. will *not* cause a GC."<br>
| newLargeInteger magnitude largeClass highWord sz |<br>
<inline: false><br>
+ <var: 'magnitude' type: #usqLong><br>
- <var: 'magnitude' type: #sqLong><br>
<var: 'highWord' type: #usqInt><br>
<br>
- objectMemory wordSize = 8 ifTrue:<br>
- [(objectMemory isIntegerValue: integerValue) ifTrue:<br>
- [^objectMemory integerObjectOf: integerValue].<br>
- sz := 8].<br>
-<br>
integerValue < 0<br>
+ ifTrue:[ integerValue >= objectMemory minSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].<br>
+ largeClass := ClassLargeNegativeIntegerCompactIndex.<br>
+ magnitude := 0 - (self cCoerceSimple: integerValue to: #usqLong)]<br>
+ ifFalse:[ integerValue <= objectMemory maxSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].<br>
+ largeClass := ClassLargePositiveIntegerCompactIndex.<br>
- ifTrue:[ largeClass := ClassLargeNegativeIntegerCompactIndex.<br>
- magnitude := 0 - integerValue]<br>
- ifFalse:[ largeClass := ClassLargePositiveIntegerCompactIndex.<br>
magnitude := integerValue].<br>
<br>
+ objectMemory wordSize = 8<br>
+ ifTrue: [sz := 8]<br>
+ ifFalse: [<br>
- "Make sure to handle the most -ve value correctly. 0 - most -ve = most -ve and most -ve - 1<br>
- is +ve. Alas the simple (negative or: [integerValue - 1 < 0]) fails with contemporary gcc and icc<br>
- versions with optimization and sometimes without. The shift works on all, touch wood."<br>
-<br>
- objectMemory wordSize = 4 ifTrue:<br>
- [(magnitude <= 16r7FFFFFFF<br>
- and: [integerValue >= 0<br>
- or: [0 ~= (self cCode: [integerValue << 1]<br>
- inSmalltalk: [integerValue << 1 bitAnd: (1 << 64) - 1])]]) ifTrue:<br>
- [^self signed32BitIntegerFor: integerValue].<br>
-<br>
(highWord := magnitude >> 32) = 0<br>
ifTrue: [sz := 4]<br>
ifFalse:<br>
[sz := 5.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1.<br>
(highWord := highWord >> 8) = 0 ifFalse:<br>
[sz := sz + 1]]]]].<br>
<br>
newLargeInteger := objectMemory<br>
eeInstantiateSmallClassIndex: largeClass<br>
format: (objectMemory byteFormatForNumBytes: sz)<br>
numSlots: sz + 3 // objectMemory bytesPerOop.<br>
self cppIf: VMBIGENDIAN<br>
ifTrue:<br>
[sz > 4 ifTrue:<br>
[objectMemory<br>
storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF);<br>
storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF);<br>
storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF);<br>
storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)].<br>
objectMemory<br>
storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF);<br>
storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF);<br>
storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF);<br>
storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)]<br>
ifFalse:<br>
+ [sz > 4<br>
+ ifTrue: [objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: magnitude]<br>
+ ifFalse: [objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].<br>
- [sz > 4 ifTrue:<br>
- [objectMemory storeLong32: 1 ofObject: newLargeInteger withValue: magnitude >> 32.<br>
- magnitude := magnitude bitAnd: 16rFFFFFFFF].<br>
- objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: magnitude].<br>
^newLargeInteger!<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>