On 2 May 2011 13:06, Henrik Sperre Johansen henrik.s.johansen@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