[Vm-dev] Does primitiveEqual perform too much job ?

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Fri Aug 31 21:38:55 UTC 2012


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


More information about the Vm-dev mailing list