[Vm-dev] Integer comparition primitive failures on Cog

Igor Stasenko siguctua at gmail.com
Mon May 2 11:22:07 UTC 2011


On 2 May 2011 13:06, Henrik Sperre Johansen
<henrik.s.johansen at veloxit.no> wrote:
>
> On 02.05.2011 12:48, Igor Stasenko wrote:
>>
>> Hmm.. that's really strange, because as far as i can see,
>> the code there are the same:
>>
>> (primitive: 3)
>>
>> Interpreter>>primitiveLessThan
>>        | integerReceiver integerArgument |
>>        integerArgument := self popInteger.
>>        integerReceiver := self popInteger.
>>        self checkBooleanResult: integerReceiver<  integerArgument
>>
>> InterpreterPrimitives>>primitiveLessThan
>>        | integerReceiver integerArgument |
>>        integerArgument := self popInteger.
>>        integerReceiver := self popInteger.
>>        self checkBooleanResult: integerReceiver<  integerArgument
>>
>> and #popInteger also same (it fails if value on stack are not
>> smallinteger).
>> So, in Squeak VM comparison primitive also fails,
>> which should lead to evaluating failure code.
>
> Cog has translation methods for those primitives in cogit.c, see
> genSmallIntegerComparison.
>
>
>> Also, a primitives for floats accepting a smallintegers as arguments,
>> so by rewriting:
>>
>>
>> SmallInteger>>  <  aNumber
>>        "Primitive. Compare the receiver with the argument and answer with
>>        true if the receiver is less than the argument. Otherwise answer
>> false.
>>        Fail if the argument is not a SmallInteger. Essential. No Lookup.
>> See
>>        Object documentation whatIsAPrimitive."
>>
>>        <primitive: 3>
>>        ^ aNumber>=  self
>>
>>
>>  [1 to: 2000000 do: [:i |
>>     i<  2354.234. ] timeToRun
>>
>> before:
>>
>> 8223
>>
>> after:
>> 20
>>
>> so... 421 times faster :)
>
> Yes, that's basically what I proposed to do in image, albeit in a different
> place.
>

But i really wonder why it falls to normal send..
Consider this:

StackInterpreter>>bytecodePrimLessThan
	| rcvr arg aBool |
	rcvr := self internalStackValue: 1.
	arg := self internalStackValue: 0.
	(self areIntegers: rcvr and: arg) ifTrue:
		["The C code can avoid detagging since tagged integers are still signed.
		 But this means the simulator must override to do detagging."
		^self cCode: [self booleanCheat: rcvr < arg]
			inSmalltalk: [self booleanCheat: (objectMemory integerValueOf:
rcvr) < (objectMemory integerValueOf: arg)]].

	self initPrimCall.
	aBool := self primitiveFloatLess: rcvr thanArg: arg.
	self successful ifTrue: [^ self booleanCheat: aBool].

	messageSelector := self specialSelector: 2.
	argumentCount := 1.
	self normalSend

so, for #< send it tries to avoid doing normal send
and instead tries to do quick int<int comparison first,
and then
float/int < float/int
second (using #primitiveFloatLess:thanArg:)
so it should not fall to normal send.

So , i think the problem is, that  #genSmallIntegerComparison: (and friends)
generating code for comparing integers only and falls back to normal
send when it fails,
without attempting to use #primitiveFloatLess:thanArg: .


> Cheers,
> Henry
>



-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Vm-dev mailing list