tim at rowledge.org
Sun Mar 13 18:14:20 UTC 2016
You might find http://wiki.squeak.org/squeak/6202 and http://wiki.squeak.org/squeak/6205 useful even though they are a little out of date right now.
Basically (and I may get this wrong) the CompiledMethod object knows nothing about whether it has been translated or not, let alone whether any PICs are required for the current state of run. When a CM is first translated all the sends within it are as Clement described (and see http://www.mirandabanda.org/cogblog/category/cog/page/5/) whereby the machine code includes some magic word that represents the selector of the message and a then a call to the lookup routine. e.g.
lookUpMessage … looks up the message for the class of the relevant receiver pulled from the stack in the normal way ... duh. Oh, and over-writes those two instructions! Argh, self-modifying code! Oh Noes! It replaces “theRubberPullets” with “boringClassTag” and calls direct to Some Other Thing rather than the look up code.
So what is “Some Other Thing”? When we first do this one of the tasks is to check if the target method - the one looked up - is already translated, which involves the sacrifice of chickens and testing a tag bit hidden somewhere. If it isn’t we take a small side trip and translate it, sacrifice some gerbils and go back to where we were. Which is… ah, yes, finding the actual address in code-space of the translated target method so it can be the “Some Other Thing” above. So now we have
call BoringClass>theRubberPullets machine code address
So that’s kinda-sorta a single inline cache. But what happens when we come around again in our code and this time the class of our receiver is *not* BoringClass but BoringOtherClass? Directly jumping into machine code built for BoringClass could be catastrophic, or worse, annoying. The clever bit is that the first part of the machine code we built for BoringClass>theRubberPullets does a check that the class of the receiver is the same as the boringClassTag we loaded. If it is, no problem, carry on. If it is not then we abort to a routine that builds a PIC - a Polymorphic Inline Cache, see the 2nd URL above - moves things around a bit (not quite randomly) and once more rewrites the call so that now it jumps to the beginning of the PIC. And then we carry on again (isn’t that a neat title for a movie?) with our processing.
After a while we may come again and have a third class of object as our receiver. The PIC is clever and when it decides there is no match with any case in its cache, it aborts to another lookup-and-correct routine that eventually results in a third case being added, or a fourth/fifth/sixth. Six is the number to which one may count, my lord, not five, nor seven. For if seven shall be counted we must abandon all PIC and instead insert an open cachey-thing that diverts to a really big general lookup routine that does pretty much anything.
So there we are children, the Sesame Street guide to Cog caching.
tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim
"!" The strange little noise you make when you can't scream...
More information about the Vm-dev