<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div><div><div><div><div>Let me think aloud...<br><br>THE CONTEXT:<br><br>backport of LargeIntegersPlugin v2.0 (32 bit native word order) to Interpreter VM<br>
<br></div>THE BUG:<br><br></div>The Vm crashes with <a href="http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.315">http://smalltalkhub.com/#!/~nice/NiceVMExperiments/versions/VMMaker-nice.315</a><br>
<br></div>THE OFFENDING METHOD:<br><br>InterpreterPrimitives>>magnitude64BitIntegerFor: magnitude neg: isNegative<br> "Return a Large Integer object for the given integer magnitude and sign"<br> | newLargeInteger largeClass lowWord highWord sz isSmall smallVal highWord2 |<br>
<var: 'magnitude' type: #usqLong><br> <var: 'lowWord' type: #usqInt><br> <var: 'highWord' type: #usqInt><br> <var: 'highWord2' type: #usqInt><br><br> isSmall := isNegative<br>
ifTrue: [magnitude <= 16r40000000]<br> ifFalse: [magnitude < 16r40000000].<br> isSmall ifTrue:<br> [smallVal := self cCoerceSimple: magnitude to: #sqInt.<br> isNegative ifTrue: [smallVal := 0 - smallVal].<br>
^objectMemory integerObjectOf: smallVal].<br> largeClass := isNegative<br> ifTrue:[self classLargeNegativeInteger]<br> ifFalse:[self classLargePositiveInteger].<br> lowWord := magnitude bitAnd: 16rFFFFFFFF.<br>
highWord := magnitude >> 32.<br> highWord = 0 <br> ifTrue: [sz := 4] <br> ifFalse:<br> [sz := 5.<br> (highWord2 := highWord >> 8) = 0 ifFalse: [sz := sz + 1].<br> (highWord2 := highWord2 >> 8) = 0 ifFalse: [sz := sz + 1].<br>
(highWord2 := highWord2 >> 8) = 0 ifFalse: [sz := sz + 1].].<br> newLargeInteger := objectMemory instantiateClass: largeClass indexableSize: sz.<br> objectMemory storeLong32: 0 ofObject: newLargeInteger withValue: lowWord.<br>
sz > 4 ifTrue: [objectMemory storeLong32: 1 ofObject: newLargeInteger withValue: highWord].<br> ^newLargeInteger<br><br></div>THE CORRECTED METHOD:<br><br></div>just replace the assignment<br><br> isNegative<br>
ifTrue:[ largeClass := self classLargeNegativeInteger]<br> ifFalse:[ largeClass := self classLargePositiveInteger].<br><br></div>THE OFFENDING GENERATED CODE:<br><br></div><div>in src/vm/interp.c<br><br>
sqInt magnitude64BitIntegerForneg(usqLong magnitude, sqInt isNegative) {<br>register struct foo * foo = &fum;<br> usqInt highWord;<br> usqInt highWord2;<br> sqInt isSmall;<br> sqInt largeClass;<br> usqInt lowWord;<br>
sqInt newLargeInteger;<br> sqInt smallVal;<br> sqInt sz;<br> sqInt oop;<br> sqInt oop1;<br><br> isSmall = (isNegative<br> ? magnitude <= 1073741824<br> : magnitude < 1073741824);<br>
if (isSmall) {<br> smallVal = ((sqInt) magnitude);<br> if (isNegative) {<br> smallVal = 0 - smallVal;<br> }<br> return ((smallVal << 1) | 1);<br> }<br> largeClass = (isNegative<br>
? /* begin fetchPointer:ofObject: */(oop = foo->specialObjectsOop),longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD)))<br> : /* begin fetchPointer:ofObject: */(oop1 = foo->specialObjectsOop),longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD))));<br>
lowWord = magnitude & 4294967295U;<br> highWord = magnitude >> 32;<br> if (highWord == 0) {<br> sz = 4;<br> } else {<br> sz = 5;<br> if (!(((highWord2 = ((usqInt) highWord) >> 8)) == 0)) {<br>
sz += 1;<br> }<br> if (!(((highWord2 = ((usqInt) highWord2) >> 8)) == 0)) {<br> sz += 1;<br> }<br> if (!(((highWord2 = ((usqInt) highWord2) >> 8)) == 0)) {<br>
sz += 1;<br> }<br> }<br> newLargeInteger = instantiateClassindexableSize(largeClass, sz);<br> long32Atput((newLargeInteger + (BASE_HEADER_SIZE)) + (0 << 2), lowWord);<br> if (sz > 4) {<br>
long32Atput((newLargeInteger + (BASE_HEADER_SIZE)) + (1 << 2), highWord);<br> }<br> return newLargeInteger;<br>}<br><br></div>THE CORRECTED GENERATED CODE:<br><br></div>Just change the ()?: assignment:<br>
<br> largeClass = (isNegative<br> ? /* begin
fetchPointer:ofObject: */(oop = foo->specialObjectsOop),longAt((oop +
(BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger <<
(SHIFT_FOR_WORD)))<br> : /* begin fetchPointer:ofObject: */(oop1 =
foo->specialObjectsOop),longAt((oop1 + (BASE_HEADER_SIZE)) +
(ClassLargePositiveInteger << (SHIFT_FOR_WORD))));<br><br>with an explicit if:<br><br> if (isNegative) {<br> /* begin fetchPointer:ofObject: */<br> oop = foo->specialObjectsOop;<br> largeClass = longAt((oop + (BASE_HEADER_SIZE)) + (ClassLargeNegativeInteger << (SHIFT_FOR_WORD)));<br>
} else {<br> /* begin fetchPointer:ofObject: */<br> oop1 = foo->specialObjectsOop;<br> largeClass = longAt((oop1 + (BASE_HEADER_SIZE)) + (ClassLargePositiveInteger << (SHIFT_FOR_WORD)));<br>
}<br><br></div>THE OFFENDING METHOD JUST WORKS IN COG BUT GENERATED CODE IS DIFFERENT:<br><br> largeClass = (isNegative<br> ? longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (ClassLargeNegativeInteger << ShiftForWord))<br>
: longAt((GIV(specialObjectsOop) + BaseHeaderSize) + (ClassLargePositiveInteger << ShiftForWord)));<br><br></div>THE QUESTION:<br><br></div>I just don't understand what is incorrect in the (t)?a,b:c,d; construct...<br>
</div>Could it be that it is interpreted:<br><br> ((t)?a,b:c),d;<br><br></div>Ah if so, maybe that would explain the warning about oop1 being potentially used before assigned! (a bulb just enlighten)<br><br></div>In this case we have a bug in the generator (probably a known one since we rearely ever use x := test ifTrue: [] ifFalse: [] in Slang)...<br>
<br></div>Nicolas<br><div><div><div><br><br><div><div><div><br><br></div></div></div></div></div></div></div>