<div dir="ltr">Hi Chris, Hi All,<div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 2, 2015 at 12:26 PM, Chris Muller <span dir="ltr"><<a href="mailto:ma.chris.m@gmail.com" target="_blank">ma.chris.m@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">We have a release candidate image.<br>
<br>
<a href="http://ftp.squeak.org/4.6/" rel="noreferrer" target="_blank">http://ftp.squeak.org/4.6/</a><br>
<br>
The new sources file is required.<br>
<br>
Please test your apps. This could be the final image unless major<br>
issues are uncovered.<br></blockquote><div><br></div><div>One issue that I'm very tempted to address before the final release is the bug to do with inadvertent editing of a breakpointed method.</div><div><br></div><div>When a breakpointed method is installed, the original is kept in a class var of BreakpointManager, and the new method, while it has full source, has that source stored in the method's trailer, not on the changes file, and so there is no back pointer to the source. If one doesn't realise the method contains a break and one redefines it, then the version history for the method will be broken. The new version fo the method will appear to be the only version.</div><div><br></div><div>There are two things that IMO should be done:</div><div><br></div><div>1. a special warning should be raised when the compiler encounters a self break in method source. The BreakpointManager can catch and squash this warning when it is raised, but the warning can alert the programmer and give them a chance to abort the compilation, revert the method, and resubmit.</div><div><br></div><div>2. when ClassDescription>>logMethodSource:forMethodWithNode:inCategory:withStamp:notifying: looks for the previous version of a method it can query the BreakpointManager to find out if the current version is a breakpointed method and get the real method from the BreakpointManager to preserve the history links.</div><div><br></div><div>#1 is nice to have, and likely reduces the need for #2, but #2 is a must-have because it prevents history links being broken. My issue is how ClassDescription>>logMethodSource:forMethodWithNode:inCategory:withStamp:notifying: queries the BreakpointManager. The issue is the dependency it introduces in a key Kernel method on the SYstem package. Right now there are probably lots of such dependencies and unloading System is impossible anyway, but I don't want to introduce any more dependencies. I can see two approaches that avoid the dependency.</div><div><br></div><div>One is to use CompiledMethod>>#hasBreakpoint:</div><div><br></div><div><div>logMethodSource: aText forMethodWithNode: aCompiledMethodWithNode inCategory: category withStamp: changeStamp notifying: requestor</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| priorMethodOrNil newText |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>priorMethodOrNil := self compiledMethodAt: aCompiledMethodWithNode selector ifAbsent: [].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(priorMethodOrNil notNil and: [priorMethodOrNil hasBreakpoint]) ifTrue:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[priorMethodOrNil := priorMethodOrNil nonBreakpointedOriginal].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>newText := (requestor notNil</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>and: [Preferences confirmFirstUseOfStyle])</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifTrue: [aText askIfAddStyle: priorMethodOrNil req: requestor]</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifFalse: [aText].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>aCompiledMethodWithNode method putSource: newText</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>fromParseNode: aCompiledMethodWithNode node</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>class: self category: category withStamp: changeStamp </div><div><span class="Apple-tab-span" style="white-space:pre">                </span>inFile: 2 priorMethod: priorMethodOrNil.</div></div><div><br></div><div>where CompiledMethod>> nonBreakpointedOriginal is a new method that gets the original from BreakpointManager. But for this to be a good approach CompiledMethod>> hasBreakpoint needs to be an override. Currently hasBreakpoint is a System method:</div><div><br></div><div><div>!CompiledMethod methodsFor: '*System-Tools-debugger support' stamp: 'emm 5/30/2002 09:22'!</div><div>hasBreakpoint</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^BreakpointManager methodHasBreakpoint: self! !</div></div><div><br></div><div>SO the question is how do I introduce an original that read</div><div><br></div><div><div>!CompiledMethod methodsFor: 'debugger support' stamp: 'blah de blah'!</div><div>hasBreakpoint</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>^false! !</div></div><div> </div><div>so that System's version overrides it? Also how do I write an update that accomplishes that?</div><div><br></div><div><br></div><div>The second approach is merely to use Smalltalk classNamed:, but that's ugly:</div><div><br></div><div><div>logMethodSource: aText forMethodWithNode: aCompiledMethodWithNode inCategory: category withStamp: changeStamp notifying: requestor</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>| priorMethodOrNil newText |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>priorMethodOrNil := self compiledMethodAt: aCompiledMethodWithNode selector ifAbsent: [].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>priorMethodOrNil ifNotNil:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>[(Smalltalk classNamed: #BreakpointManager) ifNotNil:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>[priorMethodOrNil := priorMethodOrNil nonBreakpointedOriginalFor: priorMethodOrNil]].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>newText := (requestor notNil</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span>and: [Preferences confirmFirstUseOfStyle])</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifTrue: [aText askIfAddStyle: priorMethodOrNil req: requestor]</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>ifFalse: [aText].</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>aCompiledMethodWithNode method putSource: newText</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>fromParseNode: aCompiledMethodWithNode node</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>class: self category: category withStamp: changeStamp </div><div><span class="Apple-tab-span" style="white-space:pre">                </span>inFile: 2 priorMethod: priorMethodOrNil.</div></div><div><br></div><div>or something similar.</div><div><br></div><div><br></div><div>I wouldn't suggest this except that I've made this error several times in the VMMaker package over the past few weeks. it's very easy to do, and it screws up history horribly. i really think we should fix this. It makes breakpoints dangerous otherwise.</div><div><br></div><div>What d'y'all think?</div></div><div><br></div>-- <br><div class="gmail_signature">best,<div>Eliot</div></div>
</div></div>