[squeak-dev] The Inbox: Kernel-ul.664.mcz

Bert Freudenberg bert at freudenbergs.de
Mon Jan 9 12:00:38 UTC 2012

On 09.01.2012, at 12:24, Levente Uzonyi wrote:

> On Mon, 9 Jan 2012, Bert Freudenberg wrote:
>> On 09.01.2012, at 01:47, commits at source.squeak.org wrote:
>>> A new version of Kernel was added to project The Inbox:
>>> http://source.squeak.org/inbox/Kernel-ul.664.mcz
>>> ==================== Summary ====================
>>> Name: Kernel-ul.664
>>> Author: ul
>>> Time: 9 January 2012, 2:46:30.214 am
>>> UUID: cc70b7c6-5bbd-4a4e-9bd1-4a22915a61de
>>> Ancestors: Kernel-bf.663
>>> Enhanced pointer tracing:
>>> - handle SmallIntegers correctly (they don't point to any object)
>>> - handle instances of compact classes correctly (they don't point to their class)
>>> - weak references are ignored, because they don't stop the garbage collector in collecting objects
>>> These changes modify the behavior of #pointsTo:, #outboundPointersDo: and #inboundPointersExcluding:.
>> The pointsTo: method used to be the fastest way to test for inclusion in performance-sensitive code. Maybe instead of changing its behavior, make a new method pointsStronglyTo:? I'd revert pointsTo: back to its original which goes straight to the primitive. PointerFinder and Co. could use the new, more exhaustive, but ultimately slower method. The proposed method is still 5x faster than unoptimized code, but the original was more than 10x faster.
> #pointsTo:'s behavior was already changed in 4.3, because the primitive doesn't check the class pointer (I think this change is ok). The fast method with primitive 132 is called #instVarsInclude: in 4.3.

I know, see my example code. I did not load your code but just added your proposed pointsTo: as pointsStronglyTo:, to be able to compare.

I don't like the name "instVarsInclude:" because it is incorrect. For one, it actually applies to all slots in the receiver, both inst vars and indexed fields. And secondly, it's looking for identity. So it's more like "instVarsOrIndexedFieldsIdentityInclude:" (not that I would propose that selector). This slipped by me when Matthew added it.

> I'm not sure if it's a good idea to revert #pointsTo:. I proposed a new primitive to Eliot which would be more useful and could replace primitive 132 without significant loss in performance in long term.

What would the new primitive's behavior be regarding weak refs? And would it answer -1 for the class pointer?

> Most of these changes are just fixes to pointer tracing. The major change (which is the reason why I pushed it to the Inbox) is that weak references will ignored by these methods. I wonder if anyone would miss them.

I wouldn't miss them, I'm just concerned with speed.

> If yes, then we can create new variants of these methods with an additional boolean parameter which defines the behavior of weak references, e.g. #pointsTo:includingWeakReferences:. The default could either be true (to preserve the original behavior) or false (which is what we really need in practice IMHO).

We need something that matches exactly what the garbage collector does, agreed. The question is, is that enough, or is a super-fast "any field points to" method (using primitive 132 directly) still useful, and if so, what should its name be.

>> n := 10000000.
>> {
>> 	'includes:' -> [1 to: n do: [:i |
>> 			#(up down left right) includes: #right]
>> 	] timeToRun.
>> 	'identityIncludes:' -> [1 to: n do: [:i |
>> 			#(up down left right) identityIncludes: #right]
>> 	] timeToRun.
>> 	'proposed pointsTo:' -> [1 to: n do: [:i |
>> 			#(up down left right) pointsStronglyTo: #right]
>> 	] timeToRun.
>> 	'current pointsTo:' -> [1 to: n do: [:i |
>> 			#(up down left right) pointsTo: #right]
>> 	] timeToRun.
>> 	'original pointsTo:' -> [1 to: n do: [:i |
>> 			#(up down left right) instVarsInclude: #right]
>> 	] timeToRun.
>> }
>> ==> {	'includes:'->1668 .
>> 	'identityIncludes:'->1925 .
>> 	'proposed pointsTo:'->314 .
>> 	'current pointsTo:'->178 .
>> 	'original pointsTo:'->131 }
>> - Bert -
>> For reference, this is primitive 132:
> My proposal for the new primitive was to return the index instead of true and 0 instead of false. This change is very simple in the interpreter, but it's a lot more complicated in Cog.
> Levente

Interesting. I thought the object memory was pretty much identical under Cog, except for Float byte order? Why is it more complicated?

- Bert -

>> primitiveObjectPointsTo
>> 	| rcvr thang lastField |
>> 	thang := self popStack.
>> 	rcvr := self popStack.
>> 	(self isIntegerObject: rcvr) ifTrue: [^self pushBool: false].
>> 	lastField := self lastPointerOf: rcvr.
>> 	self baseHeaderSize to: lastField by: self bytesPerWord do:
>> 		[:i | (self longAt: rcvr + i) = thang
>> 			ifTrue: [^ self pushBool: true]].
>> 	self pushBool: false.

More information about the Squeak-dev mailing list