cyclic looping with [0 == object] whileFalse: [object := object nextObject].

John M McIntosh johnmci at
Mon Nov 5 19:29:06 UTC 2007

Actually if you look at users of nextObject there is a case where you  
iterate over all the objects
doing isMorph then perform some cleanup action. I had also thought  
that doing Morph allSubInstancesDo: would
be faster.

But was surprised to see that iterating over all the object was like  
10x faster.
Why, well the nextObject is really fast...
and if you look at Behavior allInstancesDo: it actually does the  
someInstance, nextInstance dance

allInstancesDo: aBlock
	"Evaluate the argument, aBlock, for each of the current instances of  
	Because aBlock might change the class of inst (for example, using  
	it is essential to compute next before aBlock value: inst."
	| inst next |
	self ==  UndefinedObject ifTrue: [^ aBlock value: nil].
	inst _ self someInstance.
	[inst == nil]
		next _ inst nextInstance.
		aBlock value: inst.
		inst _ next]

That uses the follow primitives in interp.c

instanceAfter: objectPointer
	"Support for instance enumeration. Return the next instance
	of the class of the given object, or nilObj if the enumeration
	is complete."
	| classPointer thisObj thisClass |
	classPointer := self fetchClassOf: objectPointer.
	thisObj := self accessibleObjectAfter: objectPointer.
	[thisObj = nil]
		whileFalse: [thisClass := self fetchClassOf: thisObj.
			thisClass = classPointer ifTrue: [^ thisObj].
			thisObj := self accessibleObjectAfter: thisObj].
	^ nilObj

accessibleObjectAfter: oop
	"Return the accessible object following the given object or
	free chunk in the heap. Return nil when heap is exhausted."
	| obj |
	self inline: false.
	obj := self objectAfter: oop.
	[self oop: obj isLessThan: endOfMemory]
		whileTrue: [(self isFreeObject: obj) ifFalse: [^ obj].
			obj := self objectAfter: obj].
	^ nil

However given you are doing message sends, block evaluations etc in  
allInstancesDo:. Then *MILLIONS* of bytecodes  and 100 of thousands  
of method invocations run
to do the same task.  Thus in a simple loop iterating over an object  
and doing a message send to ask them if they are a Morph is *way faster*

On Nov 5, 2007, at 10:40 AM, Tom Phoenix wrote:

> Let's take care of the Morphs first. You probably want to process all
> of them, not just many of them, so maybe something like this:
>   Morph allSubInstancesDo: [:m |
>     m removeProperty: #undoGrabCommand ].
> If you really want a collection of all (or up to half a million)
> objects from memory, that's easily done as well, built around
> something like
>   SystemNavigation default allObjectsDo: [:ob | "....whatever...." ].
> But there's probably a better way to do what you want to do than to
> build a collection of most of the items in the object memory.
> Cheers!
> --Tom Phoenix

John M. McIntosh <johnmci at>
Corporate Smalltalk Consulting Ltd.

More information about the Squeak-dev mailing list