Hi Mariano,

On Fri, Dec 31, 2010 at 7:48 AM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Eliot. I am very newbie in all this stuff, so I would directly ask you if you could explain me my doubt ;)

StackInterpreter >>  flushMethodCacheFrom: memStart to: memEnd
    "Flush entries in the method cache only if the oop address is within the given memory range.
    This reduces overagressive cache clearing. Note the AtCache is fully flushed, 70% of the time
    cache entries live in newspace, new objects die young"
    | probe |
    probe := 0.
    1 to: MethodCacheEntries do: [:i |
            (methodCache at: probe + MethodCacheSelector) = 0
                ifFalse: [((((self oop: (methodCache at: probe + MethodCacheSelector) isGreaterThanOrEqualTo: memStart)
                                        and: [self oop: (methodCache at: probe + MethodCacheSelector) isLessThan: memEnd])
                                    or: [(self oop: (methodCache at: probe + MethodCacheClass) isGreaterThanOrEqualTo: memStart)
                                            and: [self oop: (methodCache at: probe + MethodCacheClass) isLessThan: memEnd]])
                                or: [(self oop: (methodCache at: probe + MethodCacheMethod) isGreaterThanOrEqualTo: memStart)
                                        and: [self oop: (methodCache at: probe + MethodCacheMethod) isLessThan: memEnd]])
                        ifTrue: [methodCache at: probe + MethodCacheSelector put: 0]].
            probe := probe + MethodCacheEntrySize].
    1 to: AtCacheTotalSize do: [:i | atCache at: i put: 0]

But if I see

CoInterpreter >> flushMethodCache
    "Flush the method cache. The method cache is flushed on every programming change and garbage collect."

    1 to: MethodCacheSize do: [ :i | methodCache at: i put: 0 ].
    lastMethodCacheProbeWrite := 0. "this for primitiveExternalMethod"
    cogit unlinkAllSends

So....my newbie question is just why the "cogit unlinkAllSends" is not need in Cog?   I mean, why cog doesn't need to do:

CoInterpreter >>  flushMethodCacheFrom: memStart to: memEnd
   super flushMethodCacheFrom: memStart to: memEnd .
   self unlinkAllSends.

Good question.  The answer is that  flushMethodCacheFrom:to: is being used to cheaply avoid having to remap entries in the method cache.  It gets called from mapPointersInObjectsFrom:to: during GC (which moves objects) and which could  actually remap the entries in the method cache instead of just throwing them away.  The issue for remapping is that there is no ordering of the objects in the method cache so one has to scan all of its entries, but since its small that's not likely to be an issue.  In any case, throwing away or unlinking sends in Cog is much more expensive, so I don't do it.

Instead, Cog object references are updated in mapInterpreterOops (also called from mapPointersInObjectsFrom:to:) and high cost is avoided by maintaining a flag, inFullGC, that tells Cog whether it has to remap all object references or just young object references, and a list of Cog methods containing young references (see selectors matching youngReferrers).  So during a young space scavenge when doing mapMachineCode Cog only looks at the methods containing young referrers, and typically there aren't any.


Thanks for the explanation in advance,