Hi All, I'v committed the core support for read-only objects, adapted from Clément's Pharo implementation. Enabling read-only literals is a very small step from that (three methods modified in the parser, and one method modified in Symbol class). I would like to do this as soon as possible, but it may break code. Hence my asking for permission/sending out a warning before hand. Note that the only code it will break is bad code; code that writes to literals. With the changes installed doing this: #(1 2 3) at: 2 put: 'nevermore' raises a ModificationForbidden exception with the message text "ModificationForbidden: #(1 2 3) is read-only, hence its field 2 cannot be modified with 'nevermore'" When we added read-only object support to VisualWorks some of the engineering staff were of the opinion that insulating customers from the change was a necessary thing, and so we implemented a preference to allow automatic mutating of read-only literals so that customers whose code did modify literals could set the preference rather than fix their code. I *really* don't ant to do this. It is a lot of complication for little gain; the right fix is just to rewrite the code not to write to literals. Note that that's as easy as: #(1 2 3) copy at: 2 put: 'nevermore'; yourself => #(1 'nevermore' 3) since copies of read-only objects are mutable. So do I have everyone's consent in changing trunk over to read-only literals? If there are no strenuous complaints by tomorrow noon, PST, I shall effect the change. To avoid recompiling (which can produce unbound methods, etc) I shall change literals to be read-only via a pass over all literals and a pass over the Symbol table. Hence the change should be non-invasive. If your code (like probably 99.9% of all code in the system) doesn't write to literals you won't notice. _,,,^..^,,,_ best, Eliot |
Hi Eliot, IMO you can proceed, it's better to introduce this kind of changes in early stages of the release cycle. Anyway, it's 6.0, not 5.x ;) Once upon a time, I did purposely use mutable literal array as shared state with a scope local to single method (that is without leaking the scope thru a class var). It's possible I also saw that trick once or twice, but its really an abuse of undocumented and implementation defined behavior. Anyway, we can decide to later add a defaultAction or better let that responsibility to "clients" unwilling to change their code. IMO, we should start gathering release notes about those important changes, otherwise it's a lot of work that we postpone to the release team. Le mer. 11 mars 2020 à 22:10, Eliot Miranda <[hidden email]> a écrit :
|
In reply to this post by Eliot Miranda-2
Well, *I* like it, so go ahead.
It's definitely a thing that ties nicely to some automating of connecting to repositories and loading projects; an excellent way to find out what potentially still interesting stuff needs changes to make it up to date. I'm giving you the side-eye here, code with underscore assigns or assignments to block arguments. tim -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim Strange OpCodes: PO: Punch Operator |
In reply to this post by Eliot Miranda-2
Hi Eliot
> On 11.03.2020, at 22:10, Eliot Miranda <[hidden email]> wrote: > > Hi All, > > I'v committed the core support for read-only objects, adapted from Clément's Pharo implementation. Enabling read-only literals is a very small step from that (three methods modified in the parser, and one method modified in Symbol class). I would like to do this as soon as possible, but it may break code. Hence my asking for permission/sending out a warning before hand. Note that the only code it will break is bad code; code that writes to literals. > > With the changes installed doing this: > > #(1 2 3) at: 2 put: 'nevermore' > > raises a ModificationForbidden exception with the message text "ModificationForbidden: #(1 2 3) is read-only, hence its field 2 cannot be modified with 'nevermore'" > > > When we added read-only object support to VisualWorks some of the engineering staff were of the opinion that insulating customers from the change was a necessary thing, and so we implemented a preference to allow automatic mutating of read-only literals so that customers whose code did modify literals could set the preference rather than fix their code. I *really* don't ant to do this. It is a lot of complication for little gain; the right fix is just to rewrite the code not to write to literals. Note that that's as easy as: > > #(1 2 3) copy at: 2 put: 'nevermore'; yourself > => > #(1 'nevermore' 3) > > since copies of read-only objects are mutable. > > So do I have everyone's consent in changing trunk over to read-only literals? If there are no strenuous complaints by tomorrow noon, PST, I shall effect the change. > > To avoid recompiling (which can produce unbound methods, etc) I shall change literals to be read-only via a pass over all literals and a pass over the Symbol table. Hence the change should be non-invasive. If your code (like probably 99.9% of all code in the system) doesn't write to literals you won't notice. Short and sweet: Yes, please! :D Best regards -Tobias |
In reply to this post by Nicolas Cellier
Hi Nicolas, On Wed, Mar 11, 2020 at 2:35 PM Nicolas Cellier <[hidden email]> wrote:
That's a really good idea. I'm going to crate a class-side method in Object class documentation that will be a release nots scratch pad. We can delete it as we approach the final release.
_,,,^..^,,,_ best, Eliot |
In reply to this post by Eliot Miranda-2
+1 from me, please do it.
And don't worry about your VisualWorks experience. They were dealing with commercial customers, and if you ever want to see a lot of really bad code, take a look at the in-house code base of just about any commercial organization. In Squeak we have our share of bad code, but it's not *that* bad ;-) Thanks, Dave On Wed, Mar 11, 2020 at 02:10:33PM -0700, Eliot Miranda wrote: > Hi All, > > I'v committed the core support for read-only objects, adapted from > Cl??ment's Pharo implementation. Enabling read-only literals is a very > small step from that (three methods modified in the parser, and one method > modified in Symbol class). I would like to do this as soon as possible, > but it may break code. Hence my asking for permission/sending out a > warning before hand. Note that the only code it will break is bad code; > code that writes to literals. > > With the changes installed doing this: > > #(1 2 3) at: 2 put: 'nevermore' > > raises a ModificationForbidden exception with the message text > "ModificationForbidden: #(1 2 3) is read-only, hence its field 2 cannot be > modified with 'nevermore'" > > > When we added read-only object support to VisualWorks some of the > engineering staff were of the opinion that insulating customers from the > change was a necessary thing, and so we implemented a preference to allow > automatic mutating of read-only literals so that customers whose code did > modify literals could set the preference rather than fix their code. I > *really* don't ant to do this. It is a lot of complication for little > gain; the right fix is just to rewrite the code not to write to literals. > Note that that's as easy as: > > #(1 2 3) copy at: 2 put: 'nevermore'; yourself > => > #(1 'nevermore' 3) > > since copies of read-only objects are mutable. > > So do I have everyone's consent in changing trunk over to read-only > literals? If there are no strenuous complaints by tomorrow noon, PST, I > shall effect the change. > > To avoid recompiling (which can produce unbound methods, etc) I shall > change literals to be read-only via a pass over all literals and a pass > over the Symbol table. Hence the change should be non-invasive. If your > code (like probably 99.9% of all code in the system) doesn't write to > literals you won't notice. > > _,,,^..^,,,_ > best, Eliot > |
In reply to this post by Eliot Miranda-2
Hi Eliot, Can ModificationForbidden be resumed? I certainly hope so. Magma's own WriteBarrier has one place where it dynamically compiles a literal in a method for the sole purpose of providing one extra reference slot needed for the framework. This is a useful feature in a general sense, something I'd hate to see lost. Yes, I understand it's "bad code" to modify a literal, just like using "become:" (which it also uses), but for frameworks that need to work slightly under the hood, these hacks can be very useful when one knows what they're doing. Unfortunately, I don't think the VM-based WriteBarrier can work for Magma due to its "global" nature.
I don't think we need a global preference as much as just let it be #isResumable. Can we do that? Best, Chris |
Hi Chris, On Wed, Mar 11, 2020 at 4:03 PM Chris Muller <[hidden email]> wrote:
Indeed its can. Use in database write barriers is one major use case. However, the framework for convenient use has yet to be designed and implemented. We have lots of experience with this barrier in VisualWorks and some experience in Pharo, so designing the right support should not be hard at all.
If you *do* have to modify a literal, then all you have to do is send beWritableObject to the literal in question and you'll be able to modify it (there is no recursive protection against setting read-only objects to writable).
I'm willing to bet you that it can. For example,e, it works in Gemstone on VisualWorks. The solution is to provide a policy registry hat on a per-object basis specifies how modifications to objects are to be handled. This registry typically/best exists in the exception class (ModificationForbidden), and maps an object to a MessageSend or block. This registry tags specific instances with a retry policy, so e.g. Magma can put all objects it fetches from the database that it wants to be write-through into the registry and sets them to be read-only. Then on an attempted modification the ModificationForbidden exception looks up the object in the registry, and if its there runs whatever code the registry specifies. This would be some method in Magma that would - set the object as writable - ask the exception to retry the modification - write the changed object through to the database - set the object back to read-only - resume the exception with a suitable value Specific classes might implement a message the exception could send rather than require the registry is used. But that's a space-saving optimization. Such a framework allows several orthogonal clients to share the framework, potentially on the same objects because the registry can be engineered to have more than one action per object. (BTW, this is how VisualWorks does things, IIRC) Does that instill more confidence?
Yes, it is, but doing so loses the modification: | l | [(l := #(1 2 3)) at: 2 put: 'nevermore'] on: ModificationForbidden do: [:ex| ex resume]. l => #(1 2 3) whereas one often wants to do something more like this: | lit result | result := [(lit := #(1 2 3)) at: 2 put: 'nevermore'] on: ModificationForbidden do: [:ex| ex object beWritableObject. ex retryModification]. lit -> result #(1 'nevermore' 3)->'nevermore' _,,,^..^,,,_ best, Eliot |
Hi Eliot, Thanks for the great explanation! Quick question: Will a become: cause the handler to be called on all referencing objects?
Oh, good. :)
For this step, above: - write the changed object through to the database I need a reference to the particular MagmaSession which the object belongs, so I can tell it, mySession modified: forbiddenException object and why I use the compiled literal to hold that reference. How would this be accomplished under this model? IIRC, GemBuilder had the luxury / restriction of assuming there was only one backend Stone, so was able to go through a global...
Good, since the registration/unregistration cost would make merely reading objects from the database considerably more expensive than simply changing their class via primChangeClassTo:. But I still need that reference to the Session anyway...
More, yes. All the way there? I'm not sure. I do also have need of #abort -- restore all changed objects to their state as read from the database. This means all WriteBarrier handlers for objects read from that Session need to be temporarily suspended, since restoring the variables of an object require it to once again undergo modification back to its original state. With Avi's / Magma's WriteBarrier, this is just flipping a boolean switch on the Session, but for this, would I have to - unregister all dirty objects, - then do the #abort function (restore all the dirty objects to their former state) - re-register those above objects, no longer dirty, but ready to track further updates ? _______ It's okay. With all on my plate, I doubt I'll ever have time to switch out Magma's WriteBarrier. The ability to keep running Avi's working will be important for Magma in 6.0+, but thankfully sounds like a non-issue with a minor update.
I think I will prefer to take care of it as early as possible, on compilation, as in: class compileSilently: 'writeBarrier ^ #(size) first first' classified: 'access'. ((class methodDictionary at: #writeBarrier) literalAt: 2) beWritableObject ; "<----- can I simply add in this line?" at: 1 put: (WeakArray with: mySession) and then not worry about ModifiedForbidden at all. Best, Chris |
In reply to this post by Eliot Miranda-2
> So do I have everyone's consent in changing trunk over to read-only literals? If there are no strenuous complaints by tomorrow noon, PST, I shall effect the change. +1 :-) Best, Marcel
|
On Thu, 12 Mar 2020 at 12:14 pm, Marcel Taeumel <[hidden email]> wrote:
+1 (we treat them as immutable in GraalSqueak already). Fabio
|
In reply to this post by timrowledge
+1
> On 11. Mar 2020, at 22:39, tim Rowledge <[hidden email]> wrote: > > Well, *I* like it, so go ahead. > > It's definitely a thing that ties nicely to some automating of connecting to repositories and loading projects; an excellent way to find out what potentially still interesting stuff needs changes to make it up to date. I'm giving you the side-eye here, code with underscore assigns or assignments to block arguments. > > > tim > -- > tim Rowledge; [hidden email]; http://www.rowledge.org/tim > Strange OpCodes: PO: Punch Operator > > > |
In reply to this post by Eliot Miranda-2
Thank the gods, finally.
/————————————————————/ For encrypted mail use [hidden email] Get a free account at ProtonMail.com Web: https://objectnets.net and https://objectnets.org https://datascilv.com https://datascilv.org On Mar 11, 2020, at 14:10, Eliot Miranda <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |