Igor Stasenko wrote:
[[[[[[ 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.
A stack unwinding, actually could be avoided, if we suppose that VM signaling the exception , by sending SomeExceptionSpecialObject>>#signal: immutableObject
Then Magma could hook there and override that method, to something like: SomeExceptionSpecialObject>>#signal: immutableObject (Magma watchingOverThisObject: immutableObject) ifFalse: [ ^ self new signal: immutableObject ]. Magma markAsDirty: immutableObject. immutableObject beMutable. "retry code here"
This is actually very close to what we do currently. We intercept before the exception is signaled. The generic handler like Eliot describes is what we'd like to move to, as our current scheme would conflict with anyone else who was doing something similar. ---- Eliot Miranda wrote:
Martin could you say something about the dispatch schemes Gemstone uses and what the performance issues have been in practice? (TIA)
The maintainability of the code has been much better than schemes that modify the application's bytecodes, which is what we did previously, similar to what Chris describes. Performance is better also, though I don't have figures. Imagine that you need to track changes to an Array. You either have to make that one Array in reality a different class than all the untracked Arrays, in which case somewhere along the line someone's going to catch you at that trick and some code will break, or you have to instrument basicAt:put: for every Array in the system. As Eliot points out, with VM support you only pay a penalty for writes to clean tracked objects. Untracked objects and already-dirtied objects pay no penalty. Since these are the majority of assignments, it's a clear win. And I believe that Eliot's implementation of the VM support for immutability was clever enough that it carried exactly zero penalty for writes to mutable objects, by combining the immutability check into the already-necessary range check. ---- Igor Stasenko wrote:
Also, one subtle detail about following:
old := foo. foo := newValue. old == foo ifFalse: [ Magma markAsDirty: self ]
that if old == foo, object will not be marked dirty and write will be performed. But in case of NoModificationError, object will be marked dirty, because you don't know what actual value were attempted to be written, and what sits on that
place now.
Actually, the VW VM gives you the value that failed to be assigned (and you need that anyway to re-do the assignment after the mark dirty) so we use that to ignore identical assignment at the Smalltalk level. I probably wouldn't put that in the VM code, it's not a common enough case to warrant the complexity. Regards, -Martin