Hi Nicolas,
On Thu, Mar 17, 2016 at 3:24 PM, commits@source.squeak.org wrote:
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1732.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1732 Author: nice Time: 17 March 2016, 11:22:07.715 pm UUID: ea9dd158-4847-464e-9642-9786252797dc Ancestors: VMMaker.oscog-nice.1731
Use little endian accelerators too for fetching 32 & 64 bits large integers value (like the ones used for storing value).
Dramatically simplify fetching of signedInteger values by using an intermediate unsigned magnitude.
Declare the positive32/64BitIntegerFor: and maybeInlinePositive32BitIntegerFor: parameter as unsigned since it is interpreted as positive.
Use asUnsignedInteger in isIntegerValue: tests, integerObjectOf: and rotatedFloatBitsOf: in order to ban potential UB.
Simplify bit operations using positiveMachineIntegerValueOf:/positiveMachineIntegerFor: rather than doing 32/64 bits dissertation.
Fetch magnitude of positive large ints into an unsigned for large int bit ops.
In the following
----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager> + <var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates. + integerValue <= objectMemory maxSmallInteger + ifTrue: [^ objectMemory integerObjectOf: integerValue]. - (integerValue asInteger >= 0 - and: [objectMemory isIntegerValue: integerValue]) ifTrue: - [^objectMemory integerObjectOf: integerValue].
shouldn't we compare against minSmallInteger as well, because e.g. -16r80000000 could overflow SmallInteger and answer 0?
P.S. Lovely seeing this code getting some good loving.
=============== Diff against VMMaker.oscog-nice.1731 ===============
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitIntegerFor:neg: (in category 'primitive support') ----- magnitude64BitIntegerFor: magnitude neg: isNegative "Return a Large Integer object for the given integer magnitude and sign" | newLargeInteger largeClass highWord sz isSmall smallVal | <var: 'magnitude' type: #usqLong> <var: 'highWord' type: #usqInt>
isSmall := isNegative ifTrue: [magnitude <= (objectMemory
maxSmallInteger + 1)] ifFalse: [magnitude <= objectMemory maxSmallInteger]. isSmall ifTrue: [smallVal := self cCoerceSimple: magnitude to: #sqInt. isNegative ifTrue: [smallVal := 0 - smallVal]. ^objectMemory integerObjectOf: smallVal].
largeClass := isNegative ifTrue: [objectMemory
classLargeNegativeInteger] ifFalse: [objectMemory classLargePositiveInteger]. objectMemory wordSize = 8 ifTrue: [sz := 8] ifFalse: [(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]]. newLargeInteger := objectMemory instantiateClass: largeClass indexableSize: sz. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32].
objectMemory
storeLong32: 0
ofObject: newLargeInteger
withValue: (self cCode: [magnitude]
inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])].
^newLargeInteger!
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitValueOf: (in category 'primitive support') ----- magnitude64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargeInteger." | sz value ok smallIntValue | <returnTypeC: #usqLong> <var: #value type: #usqLong>
(objectMemory isIntegerObject: oop) ifTrue: [smallIntValue := (objectMemory integerValueOf: oop). smallIntValue < 0 ifTrue: [smallIntValue := 0 -
smallIntValue]. ^self cCoerce: smallIntValue to: #usqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger) compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := objectMemory fetchByte: sz - 1 ofObject:
oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 + (objectMemory
fetchByte: i ofObject: oop)]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := objectMemory fetchByte: sz - 1 ofObject: oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 + (objectMemory fetchByte: i
ofObject: oop)]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>positive64BitValueOf: (in category 'primitive support') ----- positive64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargePositiveInteger."
<returnTypeC: #usqLong> | sz value ok | <var: #value type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [(objectMemory integerValueOf: oop) < 0 ifTrue: [^self primitiveFail]. ^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce:
(objectMemory fetchByte: i ofObject: oop) to: #usqLong) << (i*8))]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce: (objectMemory fetchByte:
i ofObject: oop) to: #usqLong) << (i*8))]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAnd (in category 'arithmetic integer primitives') ----- primitiveBitAnd <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitAnd: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitAnd: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitAnd: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitAnd: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAndLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitAndLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitAnd:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOr (in category 'arithmetic integer primitives') ----- primitiveBitOr <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitOr: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitOr: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitOr: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitOr: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOrLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitOrLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitOr:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXor (in category 'arithmetic integer primitives') ----- primitiveBitXor <inline: false> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: "xoring will leave the tag bits zero, whether the tag is 1 or zero, so add it back in." [self pop: 2 thenPush: (integerArgument bitXor: integerReceiver) + objectMemory smallIntegerTag] ifFalse:
[integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitXor: integerReceiver))]]!
[objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitXor: integerReceiver))]]
ifFalse:
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitXor: integerReceiver))]]]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXorLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitXorLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitXor:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>signed32BitValueOf: (in category 'primitive support') ----- signed32BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a four-byte LargeInteger."
| value negative ok magnitude |
| value negative ok | <inline: false> <returnTypeC: #int> <var: #value type: #int>
<var: #magnitude type: #'unsigned int'> <var: #value64 type: #long> (objectMemory isIntegerObject: oop) ifTrue: [objectMemory wordSize = 4 ifTrue: [^objectMemory integerValueOf: oop] ifFalse: "Must fail for SmallIntegers with
digitLength > 4" [| value64 | value64 := objectMemory integerValueOf: oop. (self cCode: [(self cCoerceSimple: value64 to: #int) ~= value64] inSmalltalk: [value64 >> 31 ~= 0 and: [value64 >> 31 ~= -1]]) ifTrue: [self primitiveFail. value64 := 0]. ^value64]].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger) compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. (objectMemory numBytesOfBytes: oop) > 4 ifTrue: [^self primitiveFail].
magnitude := self cppIf: VMBIGENDIAN
value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory fetchByte: 0
ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse:
[(objectMemory fetchLong32: 0
ofObject: oop) asUnsignedInteger].
(negative
ifTrue: [magnitude > 16r80000000]
ifFalse: [magnitude >= 16r80000000])
ifTrue:
[self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
[objectMemory fetchLong32: 0
ofObject: oop].
self cCode: []
inSmalltalk:
[(value anyMask: 16r80000000) ifTrue:
[value := value - 16r100000000]].
"Filter out values out of range for the signed interpretation such
as
16rFFFFFFFF (positive w/ bit 32 set) and -16rFFFFFFFF (negative
w/ bit
32 set). Since the sign is implicit in the class we require that
the high
bit of the magnitude is not set which is a simple test here.
Note that
we have to handle the most negative 32-bit value -2147483648
specially."
value < 0 ifTrue:
[self assert: (self sizeof: value) == 4.
"Don't fail for -16r80000000/-2147483648
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterPrimitives>>signed64BitValueOf: (in category 'primitive support') ----- signed64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a eight-byte LargeInteger."
| sz value negative ok magnitude |
| sz value negative ok | <inline: false> <returnTypeC: #sqLong> <var: #value type: #sqLong>
<var: #magnitude type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [^self cCoerce: (objectMemory integerValueOf: oop) to:
#sqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger) compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN ifTrue:
[magnitude := objectMemory fetchByte: sz - 1
ofObject: oop.
[value := objectMemory fetchByte: sz - 1 ofObject:
oop. sz - 2 to: 0 by: -1 do: [:i |
magnitude := magnitude << 8 +
(objectMemory fetchByte: i ofObject: oop)]]
value := value << 8 + (objectMemory
fetchByte: i ofObject: oop)]] ifFalse:
[magnitude := sz > 4
[value := sz > 4 ifTrue: [objectMemory
fetchLong64: 0 ofObject: oop] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
(negative
ifTrue: [magnitude > 16r8000000000000000]
ifFalse: [magnitude >= 16r8000000000000000])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
"Filter out values out of range for the signed interpretation such
as
16rFFFFFFFF... (positive w/ bit 64 set) and -16rFFFFFFFF...
(negative w/ bit
64 set). Since the sign is implicit in the class we require that
the high bit of
the magnitude is not set which is a simple test here. Note that
we have to
handle the most negative 64-bit value -9223372036854775808
specially."
self cCode: []
inSmalltalk:
[(value anyMask: 16r8000000000000000) ifTrue:
[value := value - 16r10000000000000000]].
value < 0 ifTrue:
[self cCode:
[self assert: (self sizeof: value) == 8.
self assert: (self sizeof: value << 1) == 8].
"Don't fail for -9223372036854775808/-16r8000000000000000.
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 64) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue:[0 - value]
ifFalse:[value]!
Item was changed: ----- Method: InterpreterPrimitives>>signedMachineIntegerValueOf: (in category 'primitive support') ----- signedMachineIntegerValueOf: oop "Answer a signed value of an integer up to the size of a machine word. The object may be either a positive SmallInteger or a LargeInteger of size <= word size." <returnTypeC: #'long'>
| negative ok bs value limit magnitude |
| negative ok bs value bits | <var: #value type: #long>
<var: #magnitude type: #usqInt>
<var: #limit type: #usqInt> (objectMemory isIntegerObject: oop) ifTrue: [^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [^self primitiveFail]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger) compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [^self primitiveFail]]. bs := objectMemory numBytesOf: oop. bs > (self sizeof: #'unsigned long') ifTrue: [^self primitiveFail].
((self sizeof: #'unsigned long') = 8 and: [bs > 4]) ifTrue:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory
fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24) + ((objectMemory fetchByte: 4 ofObject: oop) << 32) + ((objectMemory fetchByte: 5 ofObject: oop) << 40) + ((objectMemory fetchByte: 6 ofObject: oop) << 48) + ((objectMemory fetchByte: 7 ofObject: oop) << 56)] ifFalse: [objectMemory fetchLong64: 0 ofObject: oop]] ifFalse:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory
fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
limit := 1 asUnsignedInteger << ((self sizeof: #usqInt) * 8 - 1).
(negative
ifTrue: [magnitude > limit]
ifFalse: [magnitude >= limit])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
self cCode: []
inSmalltalk:
[bits := (self sizeof: #long) * 8.
(value bitShift: 1 - bits) > 0 ifTrue:
[value := value - (1 bitShift: bits)]].
value < 0 ifTrue:
["Don't fail for -16r80000000[00000000].
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << bits) - 1])]) ifTrue:
[^value].
^self primitiveFail].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterProxy>>positive32BitIntegerFor: (in category 'converting') ----- positive32BitIntegerFor: integerValue
<var: 'integerValue' type: #'unsigned int'> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 32) + integerValue]!
Item was changed: ----- Method: InterpreterProxy>>positive64BitIntegerFor: (in category 'converting') ----- positive64BitIntegerFor: integerValue <api> <returnTypeC: #sqInt> "...because answering the 64-bit argument causes the type inferencer to say this answers 64-bits."
<var: 'integerValue' type: #usqLong>
<var: 'integerValue' type: #sqLong> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 64) + integerValue]!
Item was changed: ----- Method: ObjectMemory>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur32BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur64BitMemoryManager>>integerObjectOf: (in category 'immediates') ----- integerObjectOf: value "Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object. In C, use a shift and an add to set the tag bit. In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns." <returnTypeC: #sqInt> ^self
cCode: [value asUnsignedInteger << self numTagBits + 1]
cCode: [value << self numTagBits + 1] inSmalltalk: [value << self numTagBits + (value >= 0 ifTrue: [1] ifFalse:
[16r10000000000000001])]!
Item was changed: ----- Method: Spur64BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In 64-bits we use a 3 bit tag which leaves 61 bits for 2's complement signed integers. In C, use a shift add and mask to test if the top 4 bits are all the same. Since 16rFFFFFFFFFFFFFFFF >> 60 = 16rF the computation intValue
60 + 1 bitAnd: 16rF
maps in-range -ve values to 0 and in-range +ve values to 1." <api> ^self cCode: [(intValue >> 60 + 1 bitAnd: 16rF) <= 1] "N.B.
(16rFFFFFFFFFFFFFFFF >> 60) + 1 = 16"
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
inSmalltalk: [intValue >= -16r1000000000000000 and:
[intValue <= 16rFFFFFFFFFFFFFFF]]!
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)
ifTrue: [-1 asUnsignedInteger << (64 - self numTagBits -
1)]
ifTrue: [-1 << (64 - self numTagBits - 1)] ifFalse: [0])!
Item was changed: ----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates.
integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
(integerValue asInteger >= 0
and: [objectMemory isIntegerValue: integerValue]) ifTrue:
[^objectMemory integerObjectOf: integerValue]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: 4) numSlots: 1. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger!
Item was changed: ----- Method: StackInterpreter>>positive32BitIntegerFor: (in category 'primitive support') ----- positive32BitIntegerFor: integerValue "integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:. N.B. Returning in each arm separately enables Slang inlining. /Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed." <inline: true>
<var: 'integerValue' type: #'unsigned int'> objectMemory hasSixtyFourBitImmediates ifTrue: [^objectMemory integerObjectOf: (integerValue
bitAnd: 16rFFFFFFFF)] ifFalse: [^self maybeInlinePositive32BitIntegerFor: integerValue]!
Item was changed: ----- Method: StackInterpreter>>positive64BitIntegerFor: (in category 'primitive support') ----- positive64BitIntegerFor: integerValue <api>
<var: 'integerValue' type: #usqLong>
<var: 'highWord' type: #'unsigned int'>
<var: 'integerValue' type: #sqLong> "Answer a Large Positive Integer object for the given integer
value. N.B. will *not* cause a GC." | newLargeInteger highWord sz | objectMemory hasSixtyFourBitImmediates ifTrue:
[integerValue <= objectMemory maxSmallInteger
ifTrue:
[(integerValue >= 0 and: [objectMemory
isIntegerValue: integerValue]) ifTrue: [^objectMemory integerObjectOf: integerValue]. sz := 8] ifFalse:
[(highWord := integerValue >> 32) = 0 ifTrue:
[(highWord := integerValue >>> 32) = 0 ifTrue: [^self positive32BitIntegerFor:
integerValue]. sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse:[sz := sz + 1]]]]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: sz) numSlots: 8 / objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (integerValue >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (integerValue >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (integerValue >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (integerValue >> 32 bitAnd: 16rFF); storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger !
Item was changed: ----- Method: StackInterpreter>>signed64BitIntegerFor: (in category 'primitive support') ----- signed64BitIntegerFor: integerValue <var: 'integerValue' type: #sqLong> "Answer a Large Integer object for the given integer value. N.B. will *not* cause a GC." | newLargeInteger magnitude largeClass highWord sz | <inline: false>
<var: 'magnitude' type: #usqLong>
<var: 'magnitude' type: #sqLong> <var: 'highWord' type: #usqInt>
objectMemory wordSize = 8 ifTrue:
[(objectMemory isIntegerValue: integerValue) ifTrue:
[^objectMemory integerObjectOf: integerValue].
sz := 8].
integerValue < 0
ifTrue:[ integerValue >= objectMemory
minSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - (self cCoerceSimple:
integerValue to: #usqLong)]
ifFalse:[ integerValue <= objectMemory
maxSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargePositiveIntegerCompactIndex.
ifTrue:[ largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - integerValue]
ifFalse:[ largeClass :=
ClassLargePositiveIntegerCompactIndex. magnitude := integerValue].
objectMemory wordSize = 8
ifTrue: [sz := 8]
ifFalse: [
"Make sure to handle the most -ve value correctly. 0 - most -ve =
most -ve and most -ve - 1
is +ve. Alas the simple (negative or: [integerValue - 1 < 0])
fails with contemporary gcc and icc
versions with optimization and sometimes without. The shift
works on all, touch wood."
objectMemory wordSize = 4 ifTrue:
[(magnitude <= 16r7FFFFFFF
and: [integerValue >= 0
or: [0 ~= (self cCode: [integerValue << 1]
inSmalltalk:
[integerValue << 1 bitAnd: (1 << 64) - 1])]]) ifTrue:
[^self signed32BitIntegerFor:
integerValue].
(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0
ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]].
newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: largeClass format: (objectMemory byteFormatForNumBytes: sz) numSlots: sz + 3 // objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32.
magnitude := magnitude bitAnd:
16rFFFFFFFF].
objectMemory storeLong32: 0 ofObject:
newLargeInteger withValue: magnitude]. ^newLargeInteger!
2016-03-18 21:40 GMT+01:00 Eliot Miranda eliot.miranda@gmail.com:
Hi Nicolas,
On Thu, Mar 17, 2016 at 3:24 PM, commits@source.squeak.org wrote:
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1732.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1732 Author: nice Time: 17 March 2016, 11:22:07.715 pm UUID: ea9dd158-4847-464e-9642-9786252797dc Ancestors: VMMaker.oscog-nice.1731
Use little endian accelerators too for fetching 32 & 64 bits large integers value (like the ones used for storing value).
Dramatically simplify fetching of signedInteger values by using an intermediate unsigned magnitude.
Declare the positive32/64BitIntegerFor: and maybeInlinePositive32BitIntegerFor: parameter as unsigned since it is interpreted as positive.
Use asUnsignedInteger in isIntegerValue: tests, integerObjectOf: and rotatedFloatBitsOf: in order to ban potential UB.
Simplify bit operations using positiveMachineIntegerValueOf:/positiveMachineIntegerFor: rather than doing 32/64 bits dissertation.
Fetch magnitude of positive large ints into an unsigned for large int bit ops.
In the following
----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates.
integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
(integerValue asInteger >= 0
and: [objectMemory isIntegerValue: integerValue]) ifTrue:
[^objectMemory integerObjectOf: integerValue].
shouldn't we compare against minSmallInteger as well, because e.g. -16r80000000 could overflow SmallInteger and answer 0?
P.S. Lovely seeing this code getting some good loving.
Hi Eliot, the idea is that every sender of positive32BitIntegerFor: will pass an unsigned int. At least that's the intention of every sender.
Unfortunately, slang inlining does not force a parameter variable copy in case of sign mismatch That's the case of primitiveBitShift in which a variable is declare signed sqInt shifted; Then the send: shifted := self positiveMachineIntegerFor: shifted. is translated into: if (shifted <= (MaxSmallInteger)) { shifted = ((shifted << 1) | 1); instead of: unsigned int integerValue = shifted; if (integerValue <= (MaxSmallInteger)) { shifted = ((integerValue << 1) | 1); ...
Here we have 3 options: 1) fix slang inlining 2) patch every sender of positiveMachineIntegerFor: to make sure that effective parameter is unsigned 3) revert this change
In my branch I have opted for 2), but completely failed to backport the patch in trunk (this change is 2 years old...). Right now I'm testing that the patch work and I will commit ASAP.
Sorry for breaking, I've not tested enough because I'm too much focused on 64bits brand. But testing all the flavours is not a task for a human anyway, more for a bot like a Jenkins server.
=============== Diff against VMMaker.oscog-nice.1731 ===============
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitIntegerFor:neg: (in category 'primitive support') ----- magnitude64BitIntegerFor: magnitude neg: isNegative "Return a Large Integer object for the given integer magnitude and sign" | newLargeInteger largeClass highWord sz isSmall smallVal | <var: 'magnitude' type: #usqLong> <var: 'highWord' type: #usqInt>
isSmall := isNegative ifTrue: [magnitude <= (objectMemory
maxSmallInteger + 1)] ifFalse: [magnitude <= objectMemory maxSmallInteger]. isSmall ifTrue: [smallVal := self cCoerceSimple: magnitude to: #sqInt. isNegative ifTrue: [smallVal := 0 - smallVal]. ^objectMemory integerObjectOf: smallVal].
largeClass := isNegative ifTrue: [objectMemory
classLargeNegativeInteger] ifFalse: [objectMemory classLargePositiveInteger]. objectMemory wordSize = 8 ifTrue: [sz := 8] ifFalse: [(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]]. newLargeInteger := objectMemory instantiateClass: largeClass indexableSize: sz. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32].
objectMemory
storeLong32: 0
ofObject: newLargeInteger
withValue: (self cCode: [magnitude]
inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])].
^newLargeInteger!
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitValueOf: (in category 'primitive support') ----- magnitude64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargeInteger." | sz value ok smallIntValue | <returnTypeC: #usqLong> <var: #value type: #usqLong>
(objectMemory isIntegerObject: oop) ifTrue: [smallIntValue := (objectMemory integerValueOf: oop). smallIntValue < 0 ifTrue: [smallIntValue := 0 -
smallIntValue]. ^self cCoerce: smallIntValue to: #usqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := objectMemory fetchByte: sz - 1
ofObject: oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 + (objectMemory
fetchByte: i ofObject: oop)]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := objectMemory fetchByte: sz - 1 ofObject: oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 + (objectMemory fetchByte: i
ofObject: oop)]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>positive64BitValueOf: (in category 'primitive support') ----- positive64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargePositiveInteger."
<returnTypeC: #usqLong> | sz value ok | <var: #value type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [(objectMemory integerValueOf: oop) < 0 ifTrue: [^self primitiveFail]. ^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce:
(objectMemory fetchByte: i ofObject: oop) to: #usqLong) << (i*8))]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce: (objectMemory fetchByte:
i ofObject: oop) to: #usqLong) << (i*8))]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAnd (in category 'arithmetic integer primitives') ----- primitiveBitAnd <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitAnd: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitAnd: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitAnd: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitAnd: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAndLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitAndLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitAnd:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOr (in category 'arithmetic integer primitives') ----- primitiveBitOr <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitOr: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitOr: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitOr: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitOr: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOrLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitOrLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitOr:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXor (in category 'arithmetic integer primitives') ----- primitiveBitXor <inline: false> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: "xoring will leave the tag bits zero, whether the tag is 1 or zero, so add it back in." [self pop: 2 thenPush: (integerArgument bitXor: integerReceiver) + objectMemory smallIntegerTag] ifFalse:
[integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitXor: integerReceiver))]]!
[objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitXor: integerReceiver))]]
ifFalse:
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitXor: integerReceiver))]]]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXorLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitXorLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitXor:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>signed32BitValueOf: (in category 'primitive support') ----- signed32BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a four-byte LargeInteger."
| value negative ok magnitude |
| value negative ok | <inline: false> <returnTypeC: #int> <var: #value type: #int>
<var: #magnitude type: #'unsigned int'> <var: #value64 type: #long> (objectMemory isIntegerObject: oop) ifTrue: [objectMemory wordSize = 4 ifTrue: [^objectMemory integerValueOf: oop] ifFalse: "Must fail for SmallIntegers with
digitLength > 4" [| value64 | value64 := objectMemory integerValueOf: oop. (self cCode: [(self cCoerceSimple: value64 to: #int) ~= value64] inSmalltalk: [value64 >> 31 ~= 0 and: [value64 >> 31 ~= -1]]) ifTrue: [self primitiveFail. value64 := 0]. ^value64]].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. (objectMemory numBytesOfBytes: oop) > 4 ifTrue: [^self primitiveFail].
magnitude := self cppIf: VMBIGENDIAN
value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory fetchByte: 0
ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse:
[(objectMemory fetchLong32: 0
ofObject: oop) asUnsignedInteger].
(negative
ifTrue: [magnitude > 16r80000000]
ifFalse: [magnitude >= 16r80000000])
ifTrue:
[self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
[objectMemory fetchLong32: 0
ofObject: oop].
self cCode: []
inSmalltalk:
[(value anyMask: 16r80000000) ifTrue:
[value := value - 16r100000000]].
"Filter out values out of range for the signed interpretation
such as
16rFFFFFFFF (positive w/ bit 32 set) and -16rFFFFFFFF (negative
w/ bit
32 set). Since the sign is implicit in the class we require that
the high
bit of the magnitude is not set which is a simple test here.
Note that
we have to handle the most negative 32-bit value -2147483648
specially."
value < 0 ifTrue:
[self assert: (self sizeof: value) == 4.
"Don't fail for -16r80000000/-2147483648
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterPrimitives>>signed64BitValueOf: (in category 'primitive support') ----- signed64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a eight-byte LargeInteger."
| sz value negative ok magnitude |
| sz value negative ok | <inline: false> <returnTypeC: #sqLong> <var: #value type: #sqLong>
<var: #magnitude type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [^self cCoerce: (objectMemory integerValueOf: oop) to:
#sqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN ifTrue:
[magnitude := objectMemory fetchByte: sz - 1
ofObject: oop.
[value := objectMemory fetchByte: sz - 1
ofObject: oop. sz - 2 to: 0 by: -1 do: [:i |
magnitude := magnitude << 8 +
(objectMemory fetchByte: i ofObject: oop)]]
value := value << 8 + (objectMemory
fetchByte: i ofObject: oop)]] ifFalse:
[magnitude := sz > 4
[value := sz > 4 ifTrue: [objectMemory
fetchLong64: 0 ofObject: oop] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
(negative
ifTrue: [magnitude > 16r8000000000000000]
ifFalse: [magnitude >= 16r8000000000000000])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
"Filter out values out of range for the signed interpretation
such as
16rFFFFFFFF... (positive w/ bit 64 set) and -16rFFFFFFFF...
(negative w/ bit
64 set). Since the sign is implicit in the class we require that
the high bit of
the magnitude is not set which is a simple test here. Note that
we have to
handle the most negative 64-bit value -9223372036854775808
specially."
self cCode: []
inSmalltalk:
[(value anyMask: 16r8000000000000000) ifTrue:
[value := value - 16r10000000000000000]].
value < 0 ifTrue:
[self cCode:
[self assert: (self sizeof: value) == 8.
self assert: (self sizeof: value << 1) == 8].
"Don't fail for -9223372036854775808/-16r8000000000000000.
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 64) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue:[0 - value]
ifFalse:[value]!
Item was changed: ----- Method: InterpreterPrimitives>>signedMachineIntegerValueOf: (in category 'primitive support') ----- signedMachineIntegerValueOf: oop "Answer a signed value of an integer up to the size of a machine word. The object may be either a positive SmallInteger or a LargeInteger of size <= word size." <returnTypeC: #'long'>
| negative ok bs value limit magnitude |
| negative ok bs value bits | <var: #value type: #long>
<var: #magnitude type: #usqInt>
<var: #limit type: #usqInt> (objectMemory isIntegerObject: oop) ifTrue: [^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [^self primitiveFail]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [^self primitiveFail]]. bs := objectMemory numBytesOf: oop. bs > (self sizeof: #'unsigned long') ifTrue: [^self primitiveFail].
((self sizeof: #'unsigned long') = 8 and: [bs > 4]) ifTrue:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory
fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24) + ((objectMemory fetchByte: 4 ofObject: oop) << 32) + ((objectMemory fetchByte: 5 ofObject: oop) << 40) + ((objectMemory fetchByte: 6 ofObject: oop) << 48) + ((objectMemory fetchByte: 7 ofObject: oop) << 56)] ifFalse: [objectMemory fetchLong64: 0 ofObject: oop]] ifFalse:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [
(objectMemory fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
limit := 1 asUnsignedInteger << ((self sizeof: #usqInt) * 8 - 1).
(negative
ifTrue: [magnitude > limit]
ifFalse: [magnitude >= limit])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
self cCode: []
inSmalltalk:
[bits := (self sizeof: #long) * 8.
(value bitShift: 1 - bits) > 0 ifTrue:
[value := value - (1 bitShift: bits)]].
value < 0 ifTrue:
["Don't fail for -16r80000000[00000000].
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << bits) - 1])]) ifTrue:
[^value].
^self primitiveFail].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterProxy>>positive32BitIntegerFor: (in category 'converting') ----- positive32BitIntegerFor: integerValue
<var: 'integerValue' type: #'unsigned int'> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 32) + integerValue]!
Item was changed: ----- Method: InterpreterProxy>>positive64BitIntegerFor: (in category 'converting') ----- positive64BitIntegerFor: integerValue <api> <returnTypeC: #sqInt> "...because answering the 64-bit argument causes the type inferencer to say this answers 64-bits."
<var: 'integerValue' type: #usqLong>
<var: 'integerValue' type: #sqLong> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 64) + integerValue]!
Item was changed: ----- Method: ObjectMemory>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur32BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >= 0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur64BitMemoryManager>>integerObjectOf: (in category 'immediates') ----- integerObjectOf: value "Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object. In C, use a shift and an add to set the tag bit. In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns." <returnTypeC: #sqInt> ^self
cCode: [value asUnsignedInteger << self numTagBits + 1]
cCode: [value << self numTagBits + 1] inSmalltalk: [value << self numTagBits + (value >= 0 ifTrue: [1] ifFalse:
[16r10000000000000001])]!
Item was changed: ----- Method: Spur64BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In 64-bits we use a 3 bit tag which leaves 61 bits for 2's complement signed integers. In C, use a shift add and mask to test if the top 4 bits are all the same. Since 16rFFFFFFFFFFFFFFFF >> 60 = 16rF the computation intValue
60 + 1 bitAnd: 16rF
maps in-range -ve values to 0 and in-range +ve values to 1." <api> ^self cCode: [(intValue >> 60 + 1 bitAnd: 16rF) <= 1] "N.B.
(16rFFFFFFFFFFFFFFFF >> 60) + 1 = 16"
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
inSmalltalk: [intValue >= -16r1000000000000000 and:
[intValue <= 16rFFFFFFFFFFFFFFF]]!
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)
ifTrue: [-1 asUnsignedInteger << (64 - self numTagBits -
1)]
ifTrue: [-1 << (64 - self numTagBits - 1)] ifFalse: [0])!
Item was changed: ----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates.
integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
(integerValue asInteger >= 0
and: [objectMemory isIntegerValue: integerValue]) ifTrue:
[^objectMemory integerObjectOf: integerValue]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: 4) numSlots: 1. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger!
Item was changed: ----- Method: StackInterpreter>>positive32BitIntegerFor: (in category 'primitive support') ----- positive32BitIntegerFor: integerValue "integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:. N.B. Returning in each arm separately enables Slang inlining. /Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed." <inline: true>
<var: 'integerValue' type: #'unsigned int'> objectMemory hasSixtyFourBitImmediates ifTrue: [^objectMemory integerObjectOf: (integerValue
bitAnd: 16rFFFFFFFF)] ifFalse: [^self maybeInlinePositive32BitIntegerFor: integerValue]!
Item was changed: ----- Method: StackInterpreter>>positive64BitIntegerFor: (in category 'primitive support') ----- positive64BitIntegerFor: integerValue <api>
<var: 'integerValue' type: #usqLong>
<var: 'highWord' type: #'unsigned int'>
<var: 'integerValue' type: #sqLong> "Answer a Large Positive Integer object for the given integer
value. N.B. will *not* cause a GC." | newLargeInteger highWord sz | objectMemory hasSixtyFourBitImmediates ifTrue:
[integerValue <= objectMemory maxSmallInteger
ifTrue:
[(integerValue >= 0 and: [objectMemory
isIntegerValue: integerValue]) ifTrue: [^objectMemory integerObjectOf: integerValue]. sz := 8] ifFalse:
[(highWord := integerValue >> 32) = 0 ifTrue:
[(highWord := integerValue >>> 32) = 0 ifTrue: [^self positive32BitIntegerFor:
integerValue]. sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse:[sz := sz + 1]]]]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: sz) numSlots: 8 / objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (integerValue >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (integerValue >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (integerValue >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (integerValue >> 32 bitAnd: 16rFF); storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger !
Item was changed: ----- Method: StackInterpreter>>signed64BitIntegerFor: (in category 'primitive support') ----- signed64BitIntegerFor: integerValue <var: 'integerValue' type: #sqLong> "Answer a Large Integer object for the given integer value. N.B. will *not* cause a GC." | newLargeInteger magnitude largeClass highWord sz | <inline: false>
<var: 'magnitude' type: #usqLong>
<var: 'magnitude' type: #sqLong> <var: 'highWord' type: #usqInt>
objectMemory wordSize = 8 ifTrue:
[(objectMemory isIntegerValue: integerValue) ifTrue:
[^objectMemory integerObjectOf: integerValue].
sz := 8].
integerValue < 0
ifTrue:[ integerValue >= objectMemory
minSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - (self cCoerceSimple:
integerValue to: #usqLong)]
ifFalse:[ integerValue <= objectMemory
maxSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargePositiveIntegerCompactIndex.
ifTrue:[ largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - integerValue]
ifFalse:[ largeClass :=
ClassLargePositiveIntegerCompactIndex. magnitude := integerValue].
objectMemory wordSize = 8
ifTrue: [sz := 8]
ifFalse: [
"Make sure to handle the most -ve value correctly. 0 - most -ve =
most -ve and most -ve - 1
is +ve. Alas the simple (negative or: [integerValue - 1 < 0])
fails with contemporary gcc and icc
versions with optimization and sometimes without. The shift
works on all, touch wood."
objectMemory wordSize = 4 ifTrue:
[(magnitude <= 16r7FFFFFFF
and: [integerValue >= 0
or: [0 ~= (self cCode: [integerValue << 1]
inSmalltalk:
[integerValue << 1 bitAnd: (1 << 64) - 1])]]) ifTrue:
[^self signed32BitIntegerFor:
integerValue].
(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0
ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]].
newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: largeClass format: (objectMemory byteFormatForNumBytes: sz) numSlots: sz + 3 // objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32.
magnitude := magnitude bitAnd:
16rFFFFFFFF].
objectMemory storeLong32: 0 ofObject:
newLargeInteger withValue: magnitude]. ^newLargeInteger!
-- _,,,^..^,,,_ best, Eliot
2016-03-18 23:28 GMT+01:00 Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com>:
2016-03-18 21:40 GMT+01:00 Eliot Miranda eliot.miranda@gmail.com:
Hi Nicolas,
On Thu, Mar 17, 2016 at 3:24 PM, commits@source.squeak.org wrote:
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1732.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1732 Author: nice Time: 17 March 2016, 11:22:07.715 pm UUID: ea9dd158-4847-464e-9642-9786252797dc Ancestors: VMMaker.oscog-nice.1731
Use little endian accelerators too for fetching 32 & 64 bits large integers value (like the ones used for storing value).
Dramatically simplify fetching of signedInteger values by using an intermediate unsigned magnitude.
Declare the positive32/64BitIntegerFor: and maybeInlinePositive32BitIntegerFor: parameter as unsigned since it is interpreted as positive.
Use asUnsignedInteger in isIntegerValue: tests, integerObjectOf: and rotatedFloatBitsOf: in order to ban potential UB.
Simplify bit operations using positiveMachineIntegerValueOf:/positiveMachineIntegerFor: rather than doing 32/64 bits dissertation.
Fetch magnitude of positive large ints into an unsigned for large int bit ops.
In the following
----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates.
integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
(integerValue asInteger >= 0
and: [objectMemory isIntegerValue: integerValue]) ifTrue:
[^objectMemory integerObjectOf: integerValue].
shouldn't we compare against minSmallInteger as well, because e.g. -16r80000000 could overflow SmallInteger and answer 0?
P.S. Lovely seeing this code getting some good loving.
Hi Eliot, the idea is that every sender of positive32BitIntegerFor: will pass an unsigned int. At least that's the intention of every sender.
Unfortunately, slang inlining does not force a parameter variable copy in case of sign mismatch That's the case of primitiveBitShift in which a variable is declare signed sqInt shifted; Then the send: shifted := self positiveMachineIntegerFor: shifted. is translated into: if (shifted <= (MaxSmallInteger)) { shifted = ((shifted << 1) | 1); instead of: unsigned int integerValue = shifted; if (integerValue <= (MaxSmallInteger)) { shifted = ((integerValue << 1) | 1); ...
Here we have 3 options:
- fix slang inlining
- patch every sender of positiveMachineIntegerFor: to make sure that
effective parameter is unsigned 3) revert this change
In my branch I have opted for 2), but completely failed to backport the patch in trunk (this change is 2 years old...). Right now I'm testing that the patch work and I will commit ASAP.
Ah, I think it will be 4) force a coercion "force coercion because slang inliner sometimes incorrectly pass a signed int without converting to unsigned" (self cCoerceSimple: integerValue to: #'unsigned int') <= objectMemory maxSmallInteger
Sorry for breaking, I've not tested enough because I'm too much focused on
64bits brand. But testing all the flavours is not a task for a human anyway, more for a bot like a Jenkins server.
=============== Diff against VMMaker.oscog-nice.1731 ===============
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitIntegerFor:neg: (in category 'primitive support') ----- magnitude64BitIntegerFor: magnitude neg: isNegative "Return a Large Integer object for the given integer magnitude and sign" | newLargeInteger largeClass highWord sz isSmall smallVal | <var: 'magnitude' type: #usqLong> <var: 'highWord' type: #usqInt>
isSmall := isNegative ifTrue: [magnitude <= (objectMemory
maxSmallInteger + 1)] ifFalse: [magnitude <= objectMemory maxSmallInteger]. isSmall ifTrue: [smallVal := self cCoerceSimple: magnitude to: #sqInt. isNegative ifTrue: [smallVal := 0 - smallVal]. ^objectMemory integerObjectOf: smallVal].
largeClass := isNegative ifTrue: [objectMemory
classLargeNegativeInteger] ifFalse: [objectMemory classLargePositiveInteger]. objectMemory wordSize = 8 ifTrue: [sz := 8] ifFalse: [(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord
- = 0 ifFalse:
[sz := sz + 1. (highWord :=
highWord >> 8) = 0 ifFalse: [sz := sz + 1]]]]]. newLargeInteger := objectMemory instantiateClass: largeClass indexableSize: sz. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32].
objectMemory
storeLong32: 0
ofObject: newLargeInteger
withValue: (self cCode: [magnitude]
inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])].
^newLargeInteger!
Item was changed: ----- Method: InterpreterPrimitives>>magnitude64BitValueOf: (in category 'primitive support') ----- magnitude64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargeInteger." | sz value ok smallIntValue | <returnTypeC: #usqLong> <var: #value type: #usqLong>
(objectMemory isIntegerObject: oop) ifTrue: [smallIntValue := (objectMemory integerValueOf: oop). smallIntValue < 0 ifTrue: [smallIntValue := 0 -
smallIntValue]. ^self cCoerce: smallIntValue to: #usqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := objectMemory fetchByte: sz - 1
ofObject: oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 +
(objectMemory fetchByte: i ofObject: oop)]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := objectMemory fetchByte: sz - 1 ofObject: oop.
sz - 2 to: 0 by: -1 do:
[:i | value := value << 8 + (objectMemory fetchByte: i
ofObject: oop)]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>positive64BitValueOf: (in category 'primitive support') ----- positive64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or an eight-byte LargePositiveInteger."
<returnTypeC: #usqLong> | sz value ok | <var: #value type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [(objectMemory integerValueOf: oop) < 0 ifTrue: [^self primitiveFail]. ^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN
ifTrue:
[value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce:
(objectMemory fetchByte: i ofObject: oop) to: #usqLong) << (i*8))]]
ifFalse:
[sz > 4
ifTrue: [value := self cCoerceSimple:
(objectMemory fetchLong64: 0 ofObject: oop) to: #usqLong]
ifFalse: [value := self cCoerceSimple:
(objectMemory fetchLong32: 0 ofObject: oop) to: #'unsigned int'].].
value := 0.
0 to: sz - 1 do: [:i |
value := value + ((self cCoerce: (objectMemory
fetchByte: i ofObject: oop) to: #usqLong) << (i*8))]. ^value!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAnd (in category 'arithmetic integer primitives') ----- primitiveBitAnd <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitAnd: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitAnd: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitAnd: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitAnd: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitAndLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitAndLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitAnd:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOr (in category 'arithmetic integer primitives') ----- primitiveBitOr <inline: false>
<var: 'integerArgument' type: #usqInt>
<var: 'intergerReceiver' type: #usqInt> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. "Comment out the short-cut. Either the inline interpreter
bytecode or the JIT primitive will handle this case. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: [self pop: 2 thenPush: (integerArgument bitOr: integerReceiver)] ifFalse:
["
integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitOr: integerReceiver))]
["objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitOr: integerReceiver))]] ifFalse:
[]"]"!
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitOr: integerReceiver))]]"]"!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitOrLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitOrLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitOr:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXor (in category 'arithmetic integer primitives') ----- primitiveBitXor <inline: false> | integerReceiver integerArgument | integerArgument := self stackTop. integerReceiver := self stackValue: 1. ((objectMemory isIntegerObject: integerArgument) and: [objectMemory isIntegerObject: integerReceiver]) ifTrue: "xoring will leave the tag bits zero, whether the tag is 1 or zero, so add it back in." [self pop: 2 thenPush: (integerArgument bitXor: integerReceiver) + objectMemory smallIntegerTag] ifFalse:
[integerArgument := self
positiveMachineIntegerValueOf: integerArgument.
integerReceiver := self
positiveMachineIntegerValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush: (self
positiveMachineIntegerFor: (integerArgument bitXor: integerReceiver))]]!
[objectMemory wordSize = 8
ifTrue:
[integerArgument := self
positive64BitValueOf: integerArgument.
integerReceiver := self
positive64BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive64BitIntegerFor: (integerArgument bitXor: integerReceiver))]]
ifFalse:
[integerArgument := self
positive32BitValueOf: integerArgument.
integerReceiver := self
positive32BitValueOf: integerReceiver.
self successful ifTrue:
[self pop: 2 thenPush:
(self positive32BitIntegerFor: (integerArgument bitXor: integerReceiver))]]]!
Item was changed: ----- Method: InterpreterPrimitives>>primitiveBitXorLargeIntegers (in category 'arithmetic largeint primitives') ----- primitiveBitXorLargeIntegers "Primitive logical operations for large integers in 64 bit range" | integerRcvr integerArg oopResult | <export: true>
<var: 'integerRcvr' type: 'usqLong'>
<var: 'integerArg' type: 'usqLong'>
<var: 'integerRcvr' type: 'sqLong'>
<var: 'integerArg' type: 'sqLong'> integerArg := self positive64BitValueOf: (self stackValue: 0). integerRcvr := self positive64BitValueOf: (self stackValue: 1). self successful ifFalse:[^nil]. oopResult := self positive64BitIntegerFor: (integerRcvr bitXor:
integerArg). self successful ifTrue:[self pop: 2 thenPush: oopResult]!
Item was changed: ----- Method: InterpreterPrimitives>>signed32BitValueOf: (in category 'primitive support') ----- signed32BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a four-byte LargeInteger."
| value negative ok magnitude |
| value negative ok | <inline: false> <returnTypeC: #int> <var: #value type: #int>
<var: #magnitude type: #'unsigned int'> <var: #value64 type: #long> (objectMemory isIntegerObject: oop) ifTrue: [objectMemory wordSize = 4 ifTrue: [^objectMemory integerValueOf: oop] ifFalse: "Must fail for SmallIntegers with
digitLength > 4" [| value64 | value64 := objectMemory integerValueOf: oop. (self cCode: [(self cCoerceSimple: value64 to: #int) ~= value64] inSmalltalk: [value64 >> 31 ~= 0 and: [value64 >> 31 ~= -1]]) ifTrue: [self primitiveFail. value64 := 0]. ^value64]].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. (objectMemory numBytesOfBytes: oop) > 4 ifTrue: [^self primitiveFail].
magnitude := self cppIf: VMBIGENDIAN
value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory fetchByte: 0
ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse:
[(objectMemory fetchLong32: 0
ofObject: oop) asUnsignedInteger].
(negative
ifTrue: [magnitude > 16r80000000]
ifFalse: [magnitude >= 16r80000000])
ifTrue:
[self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
[objectMemory fetchLong32: 0
ofObject: oop].
self cCode: []
inSmalltalk:
[(value anyMask: 16r80000000) ifTrue:
[value := value - 16r100000000]].
"Filter out values out of range for the signed interpretation
such as
16rFFFFFFFF (positive w/ bit 32 set) and -16rFFFFFFFF (negative
w/ bit
32 set). Since the sign is implicit in the class we require
that the high
bit of the magnitude is not set which is a simple test here.
Note that
we have to handle the most negative 32-bit value -2147483648
specially."
value < 0 ifTrue:
[self assert: (self sizeof: value) == 4.
"Don't fail for -16r80000000/-2147483648
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization
this may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterPrimitives>>signed64BitValueOf: (in category 'primitive support') ----- signed64BitValueOf: oop "Convert the given object into an integer value. The object may be either a positive SmallInteger or a eight-byte LargeInteger."
| sz value negative ok magnitude |
| sz value negative ok | <inline: false> <returnTypeC: #sqLong> <var: #value type: #sqLong>
<var: #magnitude type: #usqLong> (objectMemory isIntegerObject: oop) ifTrue: [^self cCoerce: (objectMemory integerValueOf: oop) to:
#sqLong].
(objectMemory isNonIntegerImmediate: oop) ifTrue: [self primitiveFail. ^0]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [self primitiveFail. ^0]]. sz := objectMemory numBytesOfBytes: oop. sz > (self sizeof: #sqLong) ifTrue: [self primitiveFail. ^0].
self cppIf: VMBIGENDIAN ifTrue:
[magnitude := objectMemory fetchByte: sz - 1
ofObject: oop.
[value := objectMemory fetchByte: sz - 1
ofObject: oop. sz - 2 to: 0 by: -1 do: [:i |
magnitude := magnitude << 8 +
(objectMemory fetchByte: i ofObject: oop)]]
value := value << 8 + (objectMemory
fetchByte: i ofObject: oop)]] ifFalse:
[magnitude := sz > 4
[value := sz > 4 ifTrue: [objectMemory
fetchLong64: 0 ofObject: oop] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
(negative
ifTrue: [magnitude > 16r8000000000000000]
ifFalse: [magnitude >= 16r8000000000000000])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
"Filter out values out of range for the signed interpretation
such as
16rFFFFFFFF... (positive w/ bit 64 set) and -16rFFFFFFFF...
(negative w/ bit
64 set). Since the sign is implicit in the class we require that
the high bit of
the magnitude is not set which is a simple test here. Note that
we have to
handle the most negative 64-bit value -9223372036854775808
specially."
self cCode: []
inSmalltalk:
[(value anyMask: 16r8000000000000000) ifTrue:
[value := value - 16r10000000000000000]].
value < 0 ifTrue:
[self cCode:
[self assert: (self sizeof: value) == 8.
self assert: (self sizeof: value << 1) == 8].
"Don't fail for
-9223372036854775808/-16r8000000000000000.
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization this
may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 64) - 1])]) ifTrue:
[^value].
self primitiveFail.
^0].
^negative
ifTrue:[0 - value]
ifFalse:[value]!
Item was changed: ----- Method: InterpreterPrimitives>>signedMachineIntegerValueOf: (in category 'primitive support') ----- signedMachineIntegerValueOf: oop "Answer a signed value of an integer up to the size of a machine word. The object may be either a positive SmallInteger or a LargeInteger of size <= word size." <returnTypeC: #'long'>
| negative ok bs value limit magnitude |
| negative ok bs value bits | <var: #value type: #long>
<var: #magnitude type: #usqInt>
<var: #limit type: #usqInt> (objectMemory isIntegerObject: oop) ifTrue: [^objectMemory integerValueOf: oop]. (objectMemory isNonIntegerImmediate: oop) ifTrue: [^self primitiveFail]. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj:
ClassLargePositiveInteger) compactClassIndex: ClassLargePositiveIntegerCompactIndex. ok ifTrue: [negative := false] ifFalse: [negative := true. ok := objectMemory isClassOfNonImm: oop equalTo: (objectMemory splObj: ClassLargeNegativeInteger)
compactClassIndex: ClassLargeNegativeIntegerCompactIndex. ok ifFalse: [^self primitiveFail]]. bs := objectMemory numBytesOf: oop. bs > (self sizeof: #'unsigned long') ifTrue: [^self primitiveFail].
((self sizeof: #'unsigned long') = 8 and: [bs > 4]) ifTrue:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [ (objectMemory
fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24) + ((objectMemory fetchByte: 4 ofObject: oop) << 32) + ((objectMemory fetchByte: 5 ofObject: oop) << 40) + ((objectMemory fetchByte: 6 ofObject: oop) << 48) + ((objectMemory fetchByte: 7 ofObject: oop) << 56)] ifFalse: [objectMemory fetchLong64: 0 ofObject: oop]] ifFalse:
[magnitude := self cppIf: VMBIGENDIAN
[value := self cppIf: VMBIGENDIAN ifTrue: [
(objectMemory fetchByte: 0 ofObject: oop) + ((objectMemory fetchByte: 1 ofObject: oop) << 8) + ((objectMemory fetchByte: 2 ofObject: oop) << 16) + ((objectMemory fetchByte: 3 ofObject: oop) << 24)] ifFalse: [(objectMemory fetchLong32: 0 ofObject: oop) asUnsignedInteger]].
limit := 1 asUnsignedInteger << ((self sizeof: #usqInt) * 8 - 1).
(negative
ifTrue: [magnitude > limit]
ifFalse: [magnitude >= limit])
ifTrue: [self primitiveFail.
^0].
negative
ifTrue: [value := 0 - magnitude]
ifFalse: [value := magnitude].
^value!
self cCode: []
inSmalltalk:
[bits := (self sizeof: #long) * 8.
(value bitShift: 1 - bits) > 0 ifTrue:
[value := value - (1 bitShift: bits)]].
value < 0 ifTrue:
["Don't fail for -16r80000000[00000000].
Alas the simple (negative and: [value - 1 > 0]) isn't
adequate since in C the result of signed integer
overflow is undefined and hence under optimization
this may fail. The shift, however, is well-defined."
(negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << bits) - 1])]) ifTrue:
[^value].
^self primitiveFail].
^negative
ifTrue: [0 - value]
ifFalse: [value]!
Item was changed: ----- Method: InterpreterProxy>>positive32BitIntegerFor: (in category 'converting') ----- positive32BitIntegerFor: integerValue
<var: 'integerValue' type: #'unsigned int'> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 32) + integerValue]!
Item was changed: ----- Method: InterpreterProxy>>positive64BitIntegerFor: (in category 'converting') ----- positive64BitIntegerFor: integerValue <api> <returnTypeC: #sqInt> "...because answering the 64-bit argument causes the type inferencer to say this answers 64-bits."
<var: 'integerValue' type: #usqLong>
<var: 'integerValue' type: #sqLong> integerValue isInteger ifFalse:[self error:'Not an Integer
object']. ^integerValue > 0 ifTrue:[integerValue] ifFalse:[ (1 bitShift: 64) + integerValue]!
Item was changed: ----- Method: ObjectMemory>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >=
0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur32BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In C, use a shift and XOR to set the sign bit if and only if the top two bits of the given value are the same, then test the sign bit. Note that the top two bits are equal for exactly those integers in the range that can be represented in 31-bits or 63-bits." <api> ^self
cCode: [(intValue asUnsignedInteger bitXor: (intValue
asUnsignedInteger << 1)) asInteger >= 0]
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
cCode: [(intValue bitXor: (intValue << 1)) asInteger >=
0]
inSmalltalk: [intValue >= 16r-40000000 and: [intValue <=
16r3FFFFFFF]]!
Item was changed: ----- Method: Spur64BitMemoryManager>>integerObjectOf: (in category 'immediates') ----- integerObjectOf: value "Convert the integer value, assumed to be in SmallInteger range, into a tagged SmallInteger object. In C, use a shift and an add to set the tag bit. In Smalltalk we have to work harder because the simulator works with strictly positive bit patterns." <returnTypeC: #sqInt> ^self
cCode: [value asUnsignedInteger << self numTagBits + 1]
cCode: [value << self numTagBits + 1] inSmalltalk: [value << self numTagBits + (value >= 0 ifTrue: [1] ifFalse:
[16r10000000000000001])]!
Item was changed: ----- Method: Spur64BitMemoryManager>>isIntegerValue: (in category 'interpreter access') ----- isIntegerValue: intValue "Answer if the given value can be represented as a Smalltalk integer value. In 64-bits we use a 3 bit tag which leaves 61 bits for 2's complement signed integers. In C, use a shift add and mask to test if the top 4 bits are all the same. Since 16rFFFFFFFFFFFFFFFF >> 60 = 16rF the computation intValue
60 + 1 bitAnd: 16rF
maps in-range -ve values to 0 and in-range +ve values to 1." <api> ^self cCode: [(intValue >> 60 + 1 bitAnd: 16rF) <= 1] "N.B.
(16rFFFFFFFFFFFFFFFF >> 60) + 1 = 16"
inSmalltalk: [intValue >= self minSmallInteger and:
[intValue <= self maxSmallInteger]]!
inSmalltalk: [intValue >= -16r1000000000000000 and:
[intValue <= 16rFFFFFFFFFFFFFFF]]!
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)
ifTrue: [-1 asUnsignedInteger << (64 - self numTagBits -
1)]
ifTrue: [-1 << (64 - self numTagBits - 1)] ifFalse: [0])!
Item was changed: ----- Method: StackInterpreter>>maybeInlinePositive32BitIntegerFor: (in category 'primitive support') ----- maybeInlinePositive32BitIntegerFor: integerValue "N.B. will *not* cause a GC. integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:." <notOption: #Spur64BitMemoryManager>
<var: 'integerValue' type: #'unsigned int'> | newLargeInteger | self deny: objectMemory hasSixtyFourBitImmediates.
integerValue <= objectMemory maxSmallInteger
ifTrue: [^ objectMemory integerObjectOf: integerValue].
(integerValue asInteger >= 0
and: [objectMemory isIntegerValue: integerValue]) ifTrue:
[^objectMemory integerObjectOf: integerValue]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: 4) numSlots: 1. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger!
Item was changed: ----- Method: StackInterpreter>>positive32BitIntegerFor: (in category 'primitive support') ----- positive32BitIntegerFor: integerValue "integerValue is interpreted as POSITIVE, e.g. as the result of Bitmap>at:. N.B. Returning in each arm separately enables Slang inlining. /Don't/ return the ifTrue:ifFalse: unless Slang inlining of conditionals is fixed." <inline: true>
<var: 'integerValue' type: #'unsigned int'> objectMemory hasSixtyFourBitImmediates ifTrue: [^objectMemory integerObjectOf: (integerValue
bitAnd: 16rFFFFFFFF)] ifFalse: [^self maybeInlinePositive32BitIntegerFor: integerValue]!
Item was changed: ----- Method: StackInterpreter>>positive64BitIntegerFor: (in category 'primitive support') ----- positive64BitIntegerFor: integerValue <api>
<var: 'integerValue' type: #usqLong>
<var: 'highWord' type: #'unsigned int'>
<var: 'integerValue' type: #sqLong> "Answer a Large Positive Integer object for the given integer
value. N.B. will *not* cause a GC." | newLargeInteger highWord sz | objectMemory hasSixtyFourBitImmediates ifTrue:
[integerValue <= objectMemory maxSmallInteger
ifTrue:
[(integerValue >= 0 and: [objectMemory
isIntegerValue: integerValue]) ifTrue: [^objectMemory integerObjectOf: integerValue]. sz := 8] ifFalse:
[(highWord := integerValue >> 32) = 0 ifTrue:
[(highWord := integerValue >>> 32) = 0 ifTrue: [^self positive32BitIntegerFor:
integerValue]. sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0 ifFalse:[sz := sz + 1]]]]. newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: ClassLargePositiveIntegerCompactIndex format: (objectMemory byteFormatForNumBytes: sz) numSlots: 8 / objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (integerValue >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (integerValue >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (integerValue >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (integerValue >> 32 bitAnd: 16rFF); storeByte: 3 ofObject: newLargeInteger withValue: (integerValue >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (integerValue >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (integerValue >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (integerValue ">> 0" bitAnd: 16rFF)] ifFalse: [objectMemory storeLong64: 0 ofObject: newLargeInteger withValue: integerValue]. ^newLargeInteger !
Item was changed: ----- Method: StackInterpreter>>signed64BitIntegerFor: (in category 'primitive support') ----- signed64BitIntegerFor: integerValue <var: 'integerValue' type: #sqLong> "Answer a Large Integer object for the given integer value. N.B. will *not* cause a GC." | newLargeInteger magnitude largeClass highWord sz | <inline: false>
<var: 'magnitude' type: #usqLong>
<var: 'magnitude' type: #sqLong> <var: 'highWord' type: #usqInt>
objectMemory wordSize = 8 ifTrue:
[(objectMemory isIntegerValue: integerValue) ifTrue:
[^objectMemory integerObjectOf: integerValue].
sz := 8].
integerValue < 0
ifTrue:[ integerValue >= objectMemory
minSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - (self cCoerceSimple:
integerValue to: #usqLong)]
ifFalse:[ integerValue <= objectMemory
maxSmallInteger ifTrue: [^objectMemory integerObjectOf: integerValue asInteger].
largeClass :=
ClassLargePositiveIntegerCompactIndex.
ifTrue:[ largeClass :=
ClassLargeNegativeIntegerCompactIndex.
magnitude := 0 - integerValue]
ifFalse:[ largeClass :=
ClassLargePositiveIntegerCompactIndex. magnitude := integerValue].
objectMemory wordSize = 8
ifTrue: [sz := 8]
ifFalse: [
"Make sure to handle the most -ve value correctly. 0 - most -ve
= most -ve and most -ve - 1
is +ve. Alas the simple (negative or: [integerValue - 1 < 0])
fails with contemporary gcc and icc
versions with optimization and sometimes without. The shift
works on all, touch wood."
objectMemory wordSize = 4 ifTrue:
[(magnitude <= 16r7FFFFFFF
and: [integerValue >= 0
or: [0 ~= (self cCode: [integerValue << 1]
inSmalltalk:
[integerValue << 1 bitAnd: (1 << 64) - 1])]]) ifTrue:
[^self signed32BitIntegerFor:
integerValue].
(highWord := magnitude >> 32) = 0 ifTrue: [sz := 4] ifFalse: [sz := 5. (highWord := highWord >> 8) = 0 ifFalse: [sz := sz + 1. (highWord := highWord >> 8) = 0
ifFalse: [sz := sz + 1. (highWord := highWord
- = 0 ifFalse:
[sz := sz +
1]]]]].
newLargeInteger := objectMemory
eeInstantiateSmallClassIndex: largeClass format: (objectMemory byteFormatForNumBytes: sz) numSlots: sz + 3 // objectMemory bytesPerOop. self cppIf: VMBIGENDIAN ifTrue: [sz > 4 ifTrue: [objectMemory storeByte: 7 ofObject: newLargeInteger withValue: (magnitude >> 56 bitAnd: 16rFF); storeByte: 6 ofObject: newLargeInteger withValue: (magnitude >> 48 bitAnd: 16rFF); storeByte: 5 ofObject: newLargeInteger withValue: (magnitude >> 40 bitAnd: 16rFF); storeByte: 4 ofObject: newLargeInteger withValue: (magnitude >> 32 bitAnd: 16rFF)]. objectMemory storeByte: 3 ofObject: newLargeInteger withValue: (magnitude >> 24 bitAnd: 16rFF); storeByte: 2 ofObject: newLargeInteger withValue: (magnitude >> 16 bitAnd: 16rFF); storeByte: 1 ofObject: newLargeInteger withValue: (magnitude >> 8 bitAnd: 16rFF); storeByte: 0 ofObject: newLargeInteger withValue: (magnitude ">> 0" bitAnd: 16rFF)] ifFalse:
[sz > 4
ifTrue: [objectMemory storeLong64: 0
ofObject: newLargeInteger withValue: magnitude]
ifFalse: [objectMemory storeLong32: 0
ofObject: newLargeInteger withValue: (self cCode: [magnitude] inSmalltalk: [magnitude bitAnd: 16rFFFFFFFF])]].
[sz > 4 ifTrue:
[objectMemory storeLong32: 1 ofObject:
newLargeInteger withValue: magnitude >> 32.
magnitude := magnitude bitAnd:
16rFFFFFFFF].
objectMemory storeLong32: 0 ofObject:
newLargeInteger withValue: magnitude]. ^newLargeInteger!
-- _,,,^..^,,,_ best, Eliot
vm-dev@lists.squeakfoundation.org