<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">2018-01-13 20:04 GMT+01:00 Bert Freudenberg <span dir="ltr"><<a href="mailto:bert@freudenbergs.de" target="_blank">bert@freudenbergs.de</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div dir="ltr"><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><span style="font-family:arial,sans-serif;color:rgb(34,34,34)">On Thu, Jan 11, 2018 at 2:57 AM, Eliot Miranda </span><span dir="ltr" style="font-family:arial,sans-serif;color:rgb(34,34,34)"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span><span style="font-family:arial,sans-serif;color:rgb(34,34,34)"> wrote:</span><br></div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br><div dir="ltr">Hi Denis,<div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 10, 2018 at 2:46 AM, Denis Kudriashov <span dir="ltr"><<a href="mailto:dionisiydk@gmail.com" target="_blank">dionisiydk@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> <br><div dir="ltr"><div>Now if p1 will be read only object then become will fail:</div><div><br></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 := 10@20.</div><div>p2 := 40@50.</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 beReadOnlyObject.</div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>p1 becomeForward: p2. "==> fail by modification error"<br></div><div><br></div></blockquote>My question is why this logic is valid? As simple user I do not see how become modifies the state of receiver p1.</div></div></blockquote><div><br></div><div>Well, the reason is to prevent changing literals.</div></div></div></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​I don't find this reason compelling. If the CompiledMethod itself was read-only​, then yes, trying to change a literal in it should be an error, just like trying to change any slot in any read-only object.</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Let's say you have a method like</div><div><br></div><div>Object>>printOn: aStream</div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>"Append to the argument, aStream, a sequence of characters that  </div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>identifies the receiver."</div><div><br></div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>| title |</div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>title := self class name.</div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>aStream</div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">          </span>nextPutAll: (title first isVowel ifTrue: ['an '] ifFalse: ['a ']);</div><div><span class="m_-3517792079758771478gmail-m_4260375310696990592gmail-Apple-tab-span" style="white-space:pre-wrap">               </span>nextPutAll: title</div><div><br></div><div>Without read-only literals there is nothing to stop the programmer from making the mistake of doing something like</div><div>    ((Object>>#printOn:) literalAt: 4) at: 1 put: $A</div><div>which would cause Object new to print as 'An Object', not 'an Object'.  Once literals are read-only then this can't happen; the at:put: will fail.</div></div></div></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​Agreed. Literals should be read-only, they should never be modified.​</div></div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>But one can use becomeForward: or become: in exactly the same way. </div></div></div></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​No you can not. You can only replace the whole literal, but you can not change it. </div></div><div><br></div></div></div></div></blockquote><div><br></div><div>One scenario in st80 was:</div><div><br></div><div>foo</div><div>    ^'bar' writeStream</div><div><br></div><div>baz</div><div>    ^(self foo) nextPutAll: 'baz'; contents</div><div><br></div><div>But WriteStream was using become: to grow the target collection...</div><div>So the method foo was later pointing on a 'barbaz', and next execution of baz not in agreement with source code...</div></div><div class="gmail_quote"><br></div><div class="gmail_quote">We can indeed make the CompiledMethod readOnly, but then, we have to scan the heap at each become: <br></div><div class="gmail_quote">So bye bye fast (lazy) become:...</div><div class="gmail_quote"><br></div><div class="gmail_quote">Also beware, I think that our Squeak Environment rely on become: for shared variable bindings...</div><div class="gmail_quote">CompiledMethod directly points to these...<br></div><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> Unless become is illegal for read-only objects, there is nothing to stop the programmer from making the mistake of doing</div>    ((Object>>#printOn:) literalAt: 4) becomeForward: 'An '<br>    ((Object>>#printOn:) literalAt: 4) become: 'An '</div></div></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​True. But again, unless the CompiledMethod is read-only, I don't see a reason why this sho​uld fail any more than</div><br></div><div><div>    (Object>>#printOn:) literalAt: 4<div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0);display:inline"> put</div>: 'An '</div><div> <br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>And what I expect is failing on another case which surprisingly do not fail:<br></div><div><br></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div>p1 := 10@20.</div></div><div><div>p2 := 40@50.</div></div><div><div>array := {  p1. p2}.</div></div><div><div>array beReadOnlyObject.</div></div><div><div>p1 becomeForward: p2.</div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div>array = {40@50. 40@50} "==true"</div><div><br></div></blockquote>Here become operation modifies state of read only object. But it not fails.</div></blockquote></div></div></div></blockquote><div><br></div><div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​I would expect this to fail, too.​</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>The reason here is to do with instance migration on class definition.  We want becomeForward: to update any and all instances of a class when we shape change a class.  Further, the only way the VM can prevent this is by scanning the entire heap looking for any reference to the receiver of becomeForward: from a read-only object.  And we want becomeForward: to be fast; the last thing we want is to introduce a full heap scan when we introduce read-only objects.  So we're being pragmatic; the definitions here, that two-way become fails if either is a read-only object, and that one-way become fails if the receiver is read-only, work well with the way the system implements instance migration, and allow us to implement become in the presence of read-only objects without a full heap scan.</div><div><br></div><div>This matches the VW implementation which makes the same choices for the same reasons.  It's not ideal, but neither is having the VM catch your last case.  Instead it's a workable compromise.  HTH</div></div></div></div></blockquote><div><br></div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">​Okay. If this is the semantics needed for a fast VM, that's a reason I can accept. It is just surprising that the semantics are both more restrictive (no become of a read-only object) and less restrictive (become can modify parts of a read-only object) than </div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><br></div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">Given this behavior of the VM, wouldn't it make sense to recursively make all sub-objects read-only when making an object read-only? That would ensure that parts cannot become'd either.</div><div></div></div></div></div></blockquote><div><br></div><div>But we have so many cycles in the graph, if we touch a class (then an environment), the whole graph is frozen...</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div></div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"></div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">- Bert -​</div></div></div></div>
<br></blockquote></div><br></div></div>