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

John M McIntosh johnmci at
Mon Nov 5 18:26:59 UTC 2007

Consider that memory is allocated from a low address to a high address.

Given the method below, we invoke "someObject" which technically is  
misnamed since it actually returns the first object at the lowest  
memory address. It's doubtful that object
will ever be garbage collected so asking for self someObject will  
always return the same object across every image startup.

allObjectsDo: aBlock
	"Evaluate the argument, aBlock, for each object in the system
	excluding SmallIntegers."
	| object |
	object _ self someObject.
	[0 == object]
		whileFalse: [aBlock value: object.
			object _ object nextObject]

nextObject then returns the object found after the location of the  
object that is the receiver. In theory this object is older.

Now the trick here is that as we are iterating over objects from old  
to new, we must NOT be creating objects that will continue to
grow the image, if for example you allocate a new object for each  
nextObject processing you won't complete the loop.


I believe if you become object, thus changing object from an new  
object to an old object, thus changing the memory location from
an new higher address to an older object in lower address space you  
are making a cycle.

In the code below I wonder what removeProperty does?

On Nov 5, 2007, at 9:39 AM, Rob Withers wrote:

> What gaurantees that doing loops with #nextObject won't cause  
> cyclic looping whereby you process the same set of objects over and  
> over again?
> The work I was doing was testing changing the parser to eliminate  
> #ifTrue: macros from compiled methods and recompiled the entire  
> image.  I saved the image.  When I started the image it was  
> frozen.  I broke into it and it was looping in the method  
> CommandHistory class>>#forgetAllGrabCommandsFrom:.  I took the loop  
> and modified it slightly to see what it was processing:
>    | object count objects |
>    objects := OrderedCollection new: 1000000.
>    count := 0.
>    object _ nil.
>    [0 == object or: [count > 500000]] whileFalse: [
>        count := count + 1.
>        objects add: object.
>        object isMorph ifTrue: [object removeProperty:  
> #undoGrabCommand].
>        object _ object nextObject].
>    objects
> It was looping through objects defined by this loop, block contexts  
> defined by my change to #ifTrue: bytecodes - they now create block  
> contexts.
> [] in UndefinedObject>>DoIt {[object removeProperty:  
> #undoGrabCommand]}
> [] in UndefinedObject>>DoIt {[count > 500000]}
> OrderedCollection>>add:
> OrderedCollection>>addLast:
> [] in OrderedCollection>>addLast: {[self makeRoomAtLast]}
> False>>or:
> [] in UndefinedObject>>DoIt {[object removeProperty:  
> #undoGrabCommand]}
> [] in UndefinedObject>>DoIt {[count > 500000]}
> . . .
> What guarantee is there supposed to be that #nextObject won't loop  
> back into a cycle?  What did I do to break that guarantee and how  
> can I reestablish it?
> cheers,
> Rob

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

More information about the Squeak-dev mailing list