Does primitiveEqual perform too much job ?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Does primitiveEqual perform too much job ?

Nicolas Cellier
 
Let's browse this code:

primitiveEqual
        | integerReceiver integerArgument result |
        integerArgument := self popStack.
        integerReceiver := self popStack.
        result := self compare31or32Bits: integerReceiver equal: integerArgument.
        self checkBooleanResult: result

compare31or32Bits: obj1 equal: obj2
        "May set success to false"

        "First compare two ST integers..."
        ((self isIntegerObject: obj1)
                and: [self isIntegerObject: obj2])
                ifTrue: [^ obj1 = obj2].

        "Now compare, assuming positive integers, but setting fail if not"
        ^ (self positive32BitValueOf: obj1) = (self positive32BitValueOf: obj2)

positive32BitValueOf: oop
        "Convert the given object into an integer value.
        The object may be either a positive ST integer or a four-byte
LargePositiveInteger."

        | sz value |
        (self isIntegerObject: oop) ifTrue: [
                value := self integerValueOf: oop.
                value < 0 ifTrue: [^ self primitiveFail].
                ^ value].

        self assertClassOf: oop is: (self splObj: ClassLargePositiveInteger).
        successFlag ifTrue: [
                sz := self lengthOf: oop.
                sz = 4 ifFalse: [^ self primitiveFail]].
        successFlag ifTrue: [
                ^ (self fetchByte: 0 ofObject: oop) +
                  ((self fetchByte: 1 ofObject: oop) <<  8) +
                  ((self fetchByte: 2 ofObject: oop) << 16) +
                  ((self fetchByte: 3 ofObject: oop) << 24) ].

Why do we need to check equality vs 32bit ClassLargePositiveInteger?
Is there any producer of such un-normalized LargePositiveInteger?
If not, a much simpler thing that would work is to just compare the oop:

primitiveEqual
        | integerReceiver integerArgument result |
        integerArgument := self popStack.
        integerReceiver := self popStack.
        (self isIntegerObject: integerArgument) ifFalse: [self primitiveFail. ^nil].
        self checkBooleanResult: integerReceiver = integerArgument

OK, it will fail for LargeInt instead of answering false, if we really
need to accelerate this edge case, just do:

primitiveEqual
        | integerReceiver integerArgument result |
        integerArgument := self popStack.
        integerReceiver := self popStack.
        (self isIntegerObject: integerArgument)
                ifFalse:
                        [self assertClassOf: oop is: (self splObj: ClassLargePositiveInteger)].
        self checkBooleanResult: integerReceiver = integerArgument

It's not very pure, we may compare an encoded signed interger value
xxxx...xxxxxxx1 with a pointer yyyy...yyyyy00, but they will never
equal.
Or maybe we never really call the primitive because we use kinda
special bytecode ?
I'm just curious...

Nicolas