altering bytecodePrimAdd & friends
John M McIntosh
johnmci at smalltalkconsulting.com
Wed Aug 13 19:12:04 UTC 2003
Now as mentioned in an earlier note the bytecodePrimAdd once it
determines both objects are SmallIntegers does
result _ (self integerValueOf: rcvr) + (self integerValueOf: arg).
(self isIntegerValue: result) ifTrue:
[self internalPop: 2 thenPush: (self integerObjectOf: result).
^ self fetchNextBytecode "success"]
However if we experience an overflow to a large integer, a value >
1073741823, then the fallback is to invoke primitiveAdd via a full
message send, a long time consuming operation.
The interesting thing here is we do have the result in a 32bit register
ready to go, it just needs to be converted to a LargeInteger, say via
signed32BitIntegerFor. So I've changed the code to
result _ (self integerValueOf: rcvr) + (self integerValueOf: arg).
(self isIntegerValue: result)
ifTrue:
[self internalPop: 2 thenPush: (self integerObjectOf: result)]
ifFalse:
[self externalizeIPandSP.
result _ self signed32BitIntegerFor: result.
self internalizeIPandSP.
self internalPop: 2 thenPush: result].
^ self fetchNextBytecode "success"]
In testing we get
Time millisecondsToRun: [100000 timesRepeat: [1073741823 + 1.
1073741823 + 1. 1073741823 + 1. 1073741823 + 1. 1073741823 + 1. ]]
this takes 4012 ms, after the change this now takes 300 ms
The change also affects the primitiveAdd(etc) methods where the
SmallInteger to LargeInteger would cause a primitive failure and
fallback when doing say 1073741823 perform: #+ with: 1
Before releasing a changeset I'm doing a bit more investigation of the
SmallInteger to LargeInteger boundary failures for other possible
optimizations.
--
========================================================================
===
John M. McIntosh <johnmci at smalltalkconsulting.com> 1-800-477-2659
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
========================================================================
===
More information about the Squeak-dev
mailing list
|