On Wed, Jan 13, 2010 at 1:29 PM, Igor Stasenko <siguctua@gmail.com> wrote:
2010/1/13 Eliot Miranda <eliot.miranda@gmail.com>:
On Wed, Jan 13, 2010 at 12:45 PM, Igor Stasenko <siguctua@gmail.com>
wrote:
2010/1/13 Martin McClure <martin@hand2mouse.com>:
Eliot Miranda wrote:
A *much* better way to implement this is to support immutability in
the
VM (I know, I know, but all the code is available in the Newspeak VM), mark objects one wants to mark as dirty as immutable, catch the NoModificationError exception, and proceed after having made the object mutable and marked it dirty. No creating hidden classes, no trying to get change class to work for compact classes, etc. Just a simple VM-implemented write barrier that can also be used for a host of other things (object-database mapping, debugging, immutable literals etc).
Since object dirtying is at the core of the product I work with, and I've worked extensively with both methods of implementing write barriers...
I very strongly agree with Eliot. *So* much nicer a way to do this.
It could be more efficient, in respect that you don't need to create shadow classes. But triggering exception leads to stack unwinding to find a handler, which inevitably leads to deoptimizing all contexts..
Uh, not so. In VW and Cog examining a context does _not_ deoptimize a context. A context will be "deoptimized" (actually converted to a vanilla heap context) only if you write to other than its stack contents or sender. i.e. a context's frame is only discarded if - one assigns to any of its instance variables other than sender - the stack zone runs out of room for new frames and a stack page must be vacated, causing all frames on that page to be converted to stack contexts So exception handling does *not* usually involve converting contexts. It would be very slow if it did.
Ah, cool.. So, even when debugging (and hence accessing context state) does not leads automatically to deoptimization?
and if stack depth is high (between point of writing attempt and hook, where magma will handle exception), this will be much slower than WriteBarrier implementation, described by Cris, which checking the value in-place, without the need of touching exception machinery.
I disagree strongly. Martin's experience with Gemstone (and Gemstone's experience) covers over twenty years and the VM-supported immutability implementations (first in VisualAge IIRC) of Gemstone are far more performant and less problematic than the code-rewriting implementations similar to Magma. Martin really knows what he's talking about.
I'm not saying anything against immutability, but capturing the object state change seem will be less efficient. By reading Cris description i imagine that WriteBarrier rewriting a code like:
SomeClass>>foo: newValue foo := newValue
to:
SomeClass*>>foo: newValue | old | old := foo. foo := newValue. old == foo ifFalse: [ Magma markAsDirty: self ]
now compare performance of evaluating:
[[[[[[ self foo: 5 ]]]]]]
with:
[[[[[[ self foo: 5 ]]]]]] on: ImmutableException do: [:ex | Magma markAsDirty: ex receiver. ex receiver beMutable. ex resume ]
where [[[[[]]]]]] is a call stack, which can be deeeeep.
1. Yes, but there are lots of other ways to go about it. One scheme (which I think Gemstone uses as well the immutability stuff for Newspeak) is to have a policy object control what happens when a NoModificationError occurs. Its function is to decide what to do for the immutable object. It can do things like maintain a mapping from objects (or blocks evaluated on objects) to handlers. Only if there is no handler found for an object is the exception actually delivered. Another scheme is to allow objects to override the basic immutability machinery that by default delivers a NoModificationException. Immutability violations come into the image in two ways. If an attempt is made to assign an inst var the Vm sends attemptToAssign: aValue withIndex: instVarIndex to the immutable object. If an attempt is made to assign to an object in a primitive the primitive fails with a #'no modification error' error code. In Object there is a default: noModificationError: selector arguments: arguments ^NoModificationError signal: self message: (Message selector: selector arguments: arguments) attemptToAssign: aValue withIndex: index "The VM sends this message to objects when attempts are made to assign to inst vars of immutable objects" ^self noModificationError: #instVarAt:put: arguments: {index. aValue} at: index put: aValue <primitive: 61> "primitiveAtPut" index isInteger ifTrue: [self class isVariable ifTrue: [(index >= 1 and: [index <= self size]) ifTrue: [self isImmutable ifTrue: [^ self noModificationError: #at:put: arguments: {index. aValue}]. self errorImproperStore] ifFalse: [self errorSubscriptBounds: index]] ifFalse: [self errorNotIndexable]]. index isNumber ifTrue: [^ self at: index asInteger put: aValue]. self errorNonIntegerIndex So a specific class can implement noModificationError:arguments: to short cut even delivering the exception imn the first place. 2. Yes, but it doesn't cost as much as you think. If one is using immutability to mark objects dirty then the exception only gets delivered once for that object. Once the object is dirty it can remain mutable until a batch of objects are updated, etc. Martin could you say something about the dispatch schemes Gemstone uses and what the performance issues have been in practice? (TIA) best Eliot
Just 2 cents.
Regards,
-Martin
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project