<br><br><div class="gmail_quote">On Sun, Mar 10, 2013 at 9:53 AM, Nicolas Cellier <span dir="ltr"><<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
I'd like to understand this.<br></blockquote><div><br></div><div>Me too.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
MC mecahnism should invoke primitive 116 (primitiveFlushCacheByMethod,<br>
CompiledMethod>>flushCache) on OLD CompiledMethod when recompiled in<br>
newClass.<br>
This will invoke<br>
<br>
cogit unlinkSendsTo: self stackTop andFreeIf: false<br>
<br>
where stackTop is the old CM.<br></blockquote><div><br></div><div>Can we step back and move to the abstract? What the Cog VM does in response to aMethod primitiveFlushCacheByMethod is remove all cache entries pointing to aMethod. That's both in the first-level method lookup cache, and in any inline caches that point to aMethod. What it won't (and can't do) is alter any existing activations of aMethod.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
But for some reason - ClassBuilder is relatively complex - the<br>
recompilation is invoked with an empty MethodDictionary, so this<br>
primitive is not invoked.<br>
<br>
primitive 119 (primitiveFlushCacheSelective, Symbol>>flushCache) is<br>
invoked then, but will apparently not cogit unlinkAnything.<br></blockquote><div><br></div><div>But in response to aSelector primitiveFlushCacheSelective Cog will remove all cache entries using aSelector That's both in the first-level method lookup cache, and in any inline caches that point to a method whose selector is aSelector. What it won't (and can't do) is alter any existing activations of methods whose selectors are aSelector.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
The super hammer primitive 89 (primitiveFlushCache,<br>
Behavior>>flushCache) would unlink thru flushMethodCache which:<br>
<br>
cogit unlinkAllSends<br>
<br>
But, primitive 89 is not invoked in MC createClass process.<br>
<br>
If I add Object flushCache at the end of ClassBuilder>>mutate:to:, I<br>
can download various versions of Compiler without trouble.<br>
Is my cache analysis correct and could it be the origin of the problem?<br></blockquote><div><br></div><div>We still need to understand what the bug is. What we saw was that an activation of a Parser method that was compiled for Parser before it was shape-changed was still on the stack after Parser had been shape-changed. So the old method ended up reading off the end of the Parser instance. So the first question is</div>
<div><br></div><div>- is the method on the stack there before shape-change or not?</div><div><br></div><div>If it is, then the bug is not with the VM but in the system keeping that old method in use whole it shape-changes Parser.</div>
<div><br></div><div>If it is not, then it would seem to be a VM bug or a cache-flushing bug and the question is how did the old method get activated?</div><div><br></div><div>The second question would be simple to answer if it was the case that the method's selector didn't get flushed. But you're saying the class builder did flush the method's selector.</div>
<div><br></div><div>(sorry I haven't had enough time to focus on this)</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><br>
Nicolas<br>
<br>
2013/3/8 Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>>:<br>
> 2013/3/8 Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>>:<br>
>> To illustrate it, see the attached stack trace when I attempt to load<br>
>> an OrderedCollection(a MCVersion(Compiler-eem.252)) from an up to date<br>
>> trunk image:<br>
>><br>
><br>
> Grrr, sorry, I tried so many combinations...<br>
> This was not an up-to-date Squeak image, I at least reverted my last<br>
> version of Metacello in order to trigger this simple bad behaviour.<br>
> So the recipe would be to load first Monticello-fbs.532 then<br>
> Compiler-eem.252 from an up-to-date trunk image with a COG VM (no<br>
> crash this way back, beacuse we add slots) and attempt the same with<br>
> an Interpreter VM (no problem at all).<br>
><br>
> Nicolas<br>
><br>
>> No obsolete Parser/Compiler compiledMethod sender on the call stack,<br>
>> but an obsolete Parser compiledMethod disagreeing on cue position,<br>
>> sent AFTER the recompilation of Parser, which is not expected.<br>
>><br>
>> No such Behavior with interpreter VM, for me it is clearly a COG VM<br>
>> bug, some cache is not properly flushed or something...<br>
>><br>
>> Nicolas<br>
>><br>
>> 2013/3/8 Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com">nicolas.cellier.aka.nice@gmail.com</a>>:<br>
>>> 2013/3/8 Jeff Gonis <<a href="mailto:jeff.gonis@gmail.com">jeff.gonis@gmail.com</a>>:<br>
>>>><br>
>>>> On Fri, Mar 8, 2013 at 10:49 AM, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>> wrote:<br>
>>>>><br>
>>>>> This is known. It is a bug in the update. not the VM. The update<br>
>>>>> causes the VM to read off the end of a Parser instance. It would<br>
>>>>> crash the Interpreter VM too.<br>
>>>>><br>
>>>>> best,<br>
>>>>> Eliot<br>
>>>><br>
>>><br>
>>> Hmm, looking at it again, I'm not convinced.<br>
>>> First, I tried several times from an Interpreter Vm and that never<br>
>>> triggered any bug.<br>
>>> Then I don't see how the update could fail.<br>
>>><br>
>>> In MCClassDefinition>>createClass we use<br>
>>> class := (ClassBuilder new)<br>
>>> name: name<br>
>>> inEnvironment: superClass environment<br>
>>> subclassOf: superClass<br>
>>> type: type<br>
>>> instanceVariableNames: self instanceVariablesString<br>
>>> classVariableNames: self classVariablesString<br>
>>> poolDictionaries: self sharedPoolsString<br>
>>> category: category.<br>
>>><br>
>>> This is a quite robust process, because it creates a newClass clone<br>
>>> first, compile all the methods from oldClass into newClass, and then<br>
>>> mutate allInstances of oldClass into instances of newClass.<br>
>>><br>
>>> What can fail is having an obsolete CompiledMethod on stack with wrong<br>
>>> inst var slots.<br>
>>><br>
>>> What I observed with COG VM is different.<br>
>>> I change Parser with above ClassBuilder snippet.<br>
>>> Then in previous version of createClass, this snippet fails in<br>
>>> (Compiler evaluate: ...) part :<br>
>>><br>
>>> composition := Compiler evaluate: (self traitComposition ifNil:['{}']).<br>
>>> (composition isCollection and:[composition isEmpty and:[class<br>
>>> traitComposition isEmpty]]) ifFalse:[<br>
>>> class setTraitComposition: composition asTraitComposition.<br>
>>> ].<br>
>>><br>
>>> with an obsolete Parser method...<br>
>>> It's like COG VM is still using an old Parser methodDictionary, while<br>
>>> we just changed it...<br>
>>><br>
>>> Nicolas<br>
>>><br>
>>>> Ok thanks, I wasn't sure if this was the same bug and I figured it was<br>
>>>> safer to send in a report than not. Didn't mean to spam the list.<br>
>>>><br>
>>>> Thanks for your time,<br>
>>>> Jeff<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div>