[Vm-dev] Re: [Pharo-dev] what is exactly flushCache?

Eliot Miranda eliot.miranda at gmail.com
Tue Nov 24 18:10:35 UTC 2015

Hi Stephane,

    the VM caches method lookups in a lookup cache from class,selector
pairs to method,primitive pairs, where primitive may be null.  This is
called the first-level method lookup cache.  The JIT VM caches message
lookups in machine code, so that a particular piece of machine code exists
in a state that invokes a method for a specific class very fast by
embedding the class reference in a register load and the target method in a
call instruction, and having the target method verify this "cache probe"
(this is an "in-line cache).  The JIT also caches the translation of a byte
coded method to machine code, by hiding a reference to a machine code
method in a byte coded method.

These caches can be invalidated in several circumstances:

1a. if one adds or removes a method from a class's method dictionary it may
change the correct results of a lookup not merely of the class whose
dictionary was updated but also subclasses of the class.
1b. if one replaces a method in a method dictionary this changes the target
method for a lookup of the selector for the class and subclasses

2. if one wants to rewrite the byte code or literals of a method, for
example because a Slot definition has changed, then if the method has been
compiled to machine code, the machine code must be discarded before the new
code may be executed

1a & 1b are done via Symbol>>flushCache.  In response the normal VM flushes
its first-level method lookup cache, and the JIT also scans all of machine
code looking for inline caches with that selector, and voiding them,
reverting each send site for that selector to the "unlinked" state.

There used to be confusion in Squeak, which Pharo inherited, that using
CompiledMethod>>flushCache was somehow the right way to void caches when
updating method dictionaries, flushing the old method in the dictionary, if
any, and the new method.  It isn't, precisely because adding or removing
methods affects the visibility of inherited methods with the same
selector.  So MethodDictionary code should use Symbol>>flushCache, and only
once, on each update of a method dictionary.  As a result, the VM will
ensure that the necessary send caches are flushed for that selector.

2. is done via CompiledMethod>>flushCache.  In response the VM searches the
first-level method lookup cache and removes all entries whose target is the
method.  In addition the JIT discards the machine code for the method, and
searches for all send sites with that method's machine code as the target
and voids them, reverting them to the unlinked state.

The VM must be told to flush the cached state for a compiled method via
CompiledMethod>>flushCache and will /try/ and void the state for that
method.  But it can't always deal with existing activations of that method,
because if there are activations running the machine code, that machine
code can't merely be thrown away, and can't be replaced because its length
may change, depending on literals or byte codes.  So this kind of byte
coded method manipulation needs to be done with case and some understanding
of the total system state.


On Tue, Nov 24, 2015 at 9:37 AM, stepharo <stepharo at free.fr> wrote:

> Clement
> do you know what is flushCache and why we need to invoke it?
> Stef

best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20151124/9f8894f7/attachment.htm

More information about the Vm-dev mailing list