allObjectsDo: (was Re: [squeak-dev] The Inbox: System-cwp.662.mcz)

David T. Lewis lewis at mail.msen.com
Mon Jan 13 01:13:40 UTC 2014


On Sun, Jan 12, 2014 at 09:53:27PM +0100, Bert Freudenberg wrote:
> 
> On 12.01.2014, at 20:42, David T. Lewis <lewis at mail.msen.com> wrote:
> 
> > It is worth noting that allObjectsDo: relies on assumptions about how
> > the objects memory works internally. It requires that #someObject will
> > always answer the object at the lowest address in the object memory, and
> > also that a newly allocated object will always be placed at a higher
> > address location than all other objects. Either of these assumptions is
> > likely to be a problem as new and better object memories and garbage
> > collectors are implemented.
> > 
> > Dave
> 
> Right (as Eliot's vm-dev post shows).
> 
> So IMHO the only sensible semantics of allObjectsDo: is as in "allObjects do:" -
> which might be implemented as a primitive in some VMs soonish. It *should not*
> enumerate objects created after calling the method.
> 


On Sun, Jan 12, 2014 at 12:01:00PM -0800, Eliot Miranda wrote:
>
> The bug is in implementing allObjects in terms of someObject and nextObject
> in the first place.  It's cheap and cheerful but horribly error-prone and
> restrictive.  It's cheap because the collection of objects doesn't have to
> be created, and on the original 16-bit Smalltalk machines that was really
> important.  It's horribly restrictive because it assumes much about the
> implementation.
>
> Before closures a sentinel wasn't even needed because enumerating the block
> didn't create a new object (the block context was reused).  So the code had
> to be rewritten just to support closures.
>
> Spur has a generation scavenger operating in a distinct new space and that
> doesn't jive well with a consistent ordering at all.  So far the system is
> limping along by tenuring all objects on someObject and someInstance (so
> that newSpace is either empty, or doesn't contain any instances of a
> specific class) and having nextObject enumerate only objects in oldSpace.
>
> But I think now we can afford a primitive that answers all the objects
> (remember that average object size means that such a collection will be ~
> 10% of the heap, average object size in Squeak V3 is about 10.6 words).  At
> least that's what Spur will do, along with an allInstancesOf: primitive.
>  And then the become example won't cause any problems at all.  Far more
> reliable.  I suppose there are circumstances when enumerating without a
> container is the only feasible approach, but VisualWorks has got along with
> only an allObjects primitive for a long time now.  I suspect we can too.
>

Implementation attached. Works on interpreter VM, not yet tested on Cog but
it should be ok there also. If no objections or better suggestions I will
commit it to VMMaker tomorrow.

InterpreterPrimitives>>primitiveAllObjects
	"Answer an array of all objects that exist when the primitive is called, excluding those
	that may be garbage collected as a side effect of allocating the result array. Multiple
	references to nil in the last slots of the array are an indication that garbage collection
	occured, such that some of the unreferenced objects that existed at the time of calling
	the primitive no longer exist. Sender is responsible for handling multiple references to
	nil in the result array."

Dave

-------------- next part --------------
'From Squeak4.5 of 12 January 2014 [latest update: #13621] on 12 January 2014 at 7:51:15 pm'!
"Change Set:		InterpreterPrimitives-primitiveAllObjects-dtl
Date:			12 January 2014
Author:			David T. Lewis

InterpreterPrimitives>>primitiveAllObjects is a primitive that answers an array of all accessible objects"!


!InterpreterPrimitives methodsFor: 'object access primitives' stamp: 'dtl 1/12/2014 19:49'!
primitiveAllObjects
	"Answer an array of all objects that exist when the primitive is called, excluding those
	that may be garbage collected as a side effect of allocating the result array. Multiple
	references to nil in the last slots of the array are an indication that garbage collection
	occured, such that some of the unreferenced objects that existed at the time of calling
	the primitive no longer exist. Sender is responsible for handling multiple references to
	nil in the result array."

	<export: true>
	| count obj resultArray idx |
	self pop: argumentCount+1.
	"Count the currently accessible objects"
	count := 0.
	obj := objectMemory firstAccessibleObject.
	[obj = nil] whileFalse:
		[count := count + 1.
		obj := objectMemory accessibleObjectAfter: obj].
	resultArray := objectMemory instantiateClass: objectMemory classArray indexableSize: count. "can cause GC"
	resultArray = nil ifTrue:
		[^self primitiveFailFor: PrimErrNoMemory].
	"Store all objects in result array, filling any remaining slots with nil if garbage collection
	occurred during allocation of the result array."
	obj := objectMemory firstAccessibleObject.
	idx := 1.
	[count = 0] whileFalse:
		[count := count - 1.
		obj = nil
			ifTrue: [ "garbage collection happened, fill remaining slots with nil"
				self stObject: resultArray at: idx put: objectMemory nilObject]
			ifFalse: [self stObject: resultArray at: idx put: obj.
				obj := objectMemory accessibleObjectAfter: obj].
		idx := idx + 1].
	self push: resultArray! !



More information about the Squeak-dev mailing list