[Vm-dev] vm problem on cog an stack v3

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Sat Mar 26 23:40:23 UTC 2016


Hi,
before I continue, i've noticed that the large integer multiply seems
broken on v3 object memory (cog & stack)
Note that this does not happen on Spur.

This is independent of my recent changes of LargeIntegers plugin as it
happens BEFORE these changes and is related to primitive 29 rather than to
the plugin...
Here are the symptoms:

halfPower := 10000.
s := 111111111111111.
head := s quo: halfPower.
tail := s - (head * halfPower).
{
   head as: ByteArray.
   (1 to: halfPower digitLength) collect: [:i | halfPower digitAt: i] as:
ByteArray.
   (head*halfPower) as: ByteArray.
}.

the correct result is:
 #(#[199 25 70 150 2] #[16 39] #[112 237 78 18 14 101])

the wrong result I obtained with SVN revision 3651 compiled by myself is:
 #(#[199 25 70 150 2] #[16 39] #[112 237 78 18 254 61])

The most significant bits (above 32) are wrong...
The pattern I obtain is (with most significant bit put back left)

2r00111101 << 8 +  2r11111110   "wrong result"
2r01100101 << 8 + 2r00001110  "Correct result"

I completely fail to infer what's going on from this pattern...

This is on MacOSX clang --version
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.4.0

This goes thru primitiveMultiplyLargeIntegers (29)
oopResult := self magnitude64BitIntegerFor: result neg: aIsNegative ~=
bIsNegative.
-> sz > 4
                ifTrue: [objectMemory storeLong64: 0 ofObject:
newLargeInteger withValue: magnitude]
(which I changed recently)

then:
storeLong64: longIndex ofObject: oop withValue: value
    <var: #value type: #sqLong>
    self flag: #endianness.
    self long32At: oop + self baseHeaderSize + (longIndex << 3) put: (self
cCode: [value] inSmalltalk: [value bitAnd: 16rFFFFFFFF]);
        long32At: oop + self baseHeaderSize + (longIndex << 3) + 4 put:
(value >> 32).
    ^value

I don't see anything wrong with this code...
Well, using a shift on signed value is not that good, but it works for at
least 3 reasons:
- we throw the signBit extension away
- slang inlining misses the signedness difference, and the generated C code
is correct.
- Anyway, in our case, the sign bit was 0...

Previous implementation in magnitude64BitIntegerFor:neg: was:
sz > 4 ifTrue:
                [objectMemory storeLong32: 1 ofObject: newLargeInteger
withValue: magnitude >> 32].
            objectMemory
                storeLong32: 0
                ofObject: newLargeInteger
                withValue: (self cCode: [magnitude] inSmalltalk: [magnitude
bitAnd: 16rFFFFFFFF])

Not much different, except that the high 32 bits and low 32 bits are
written in a different order...

If I had a server I'd like to bisect
- from which version does this happens
- for which OS
- for which compiler

Without such information, I think I'll have to debug it either thru
simulator or directly in gdb, but I feel like I'm really losing my time :(

And I've got a 2nd problem like this one...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20160327/ea60f6a7/attachment.htm


More information about the Vm-dev mailing list