Hi Eliot. I am implementing some kind of MethodWrappes/ObjectsAsMethod, whihc basically use the #run:with:in trick. My question is that I am not sure how to implement #flushCache in my wrappers. This method is called by MethodDictionary>>#at:put: when I want to put back the original CompiledMethod.
MyClass methodDict at: #foo put: MyWrapper withMethod: (MyClass>>#foo). ... MyClass methodDict at: #foo put: wrapper wrappedMethod -> here it sends #flushCache to my wrapper instance.
In the StandardVM, I realised that at that moment, there is an entry in the cache that has selector: #foo, method: my wrapped instance, class: MyClass, etc...
So, to flush this, I have to options:
MyWrappers>>flushCache self wrappedMethod selector flushCache
or....
MyWrappers>>flushCache <primitive: 116>
this is because "self" will be found in the entry as "method" in the cache table...
So, first, are my assumptions correct?
Now, in cog I am not sure if both solutions are still valid. If I see CoInterpreterPrimitives>> primitiveFlushCacheByMethod
you do at the end:
(self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]
and
methodHasCogMethod: aMethodOop <api> self assert: (objectMemory isNonIntegerObject: aMethodOop). ^self isCogMethodReference: (self rawHeaderOf: aMethodOop)
So, it is not safe if the method is something different than a compiled method.
Is that correct? should I flush the cache entering by selector instead? which is the safe way to clean the cache in this case?
thanks
Mariano
Anyone? I am having Cog crashed and I think it is related to this...
On Wed, Mar 16, 2011 at 11:20 AM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi Eliot. I am implementing some kind of MethodWrappes/ObjectsAsMethod, whihc basically use the #run:with:in trick. My question is that I am not sure how to implement #flushCache in my wrappers. This method is called by MethodDictionary>>#at:put: when I want to put back the original CompiledMethod.
MyClass methodDict at: #foo put: MyWrapper withMethod: (MyClass>>#foo). ... MyClass methodDict at: #foo put: wrapper wrappedMethod -> here it sends #flushCache to my wrapper instance.
In the StandardVM, I realised that at that moment, there is an entry in the cache that has selector: #foo, method: my wrapped instance, class: MyClass, etc...
So, to flush this, I have to options:
MyWrappers>>flushCache self wrappedMethod selector flushCache
or....
MyWrappers>>flushCache <primitive: 116>
this is because "self" will be found in the entry as "method" in the cache table...
So, first, are my assumptions correct?
Now, in cog I am not sure if both solutions are still valid. If I see CoInterpreterPrimitives>> primitiveFlushCacheByMethod
you do at the end:
(self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]
and
methodHasCogMethod: aMethodOop <api> self assert: (objectMemory isNonIntegerObject: aMethodOop). ^self isCogMethodReference: (self rawHeaderOf: aMethodOop)
So, it is not safe if the method is something different than a compiled method.
Is that correct? should I flush the cache entering by selector instead? which is the safe way to clean the cache in this case?
thanks
Mariano
Hi Mariano,
VMMaker-oscog.52 is uploading:
primitiveFlushCacheByMethod "The receiver is a compiledMethod. Clear all entries in the method lookup cache that refer to this method, presumably because it has been redefined, overridden or removed. Override to flush appropriate machine code caches also." | probe oldMethod primIdx | oldMethod := self stackTop. probe := 0. 1 to: MethodCacheEntries do: [:i | (methodCache at: probe + MethodCacheMethod) = oldMethod ifTrue: [methodCache at: probe + MethodCacheSelector put: 0]. probe := probe + MethodCacheEntrySize]. (objectMemory isOopCompiledMethod: oldMethod) ifTrue: [primIdx := self primitiveIndexOf: oldMethod. primIdx = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oldMethod]. (self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]]
On Wed, Mar 16, 2011 at 3:20 AM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi Eliot. I am implementing some kind of MethodWrappes/ObjectsAsMethod, whihc basically use the #run:with:in trick. My question is that I am not sure how to implement #flushCache in my wrappers. This method is called by MethodDictionary>>#at:put: when I want to put back the original CompiledMethod.
MyClass methodDict at: #foo put: MyWrapper withMethod: (MyClass>>#foo). ... MyClass methodDict at: #foo put: wrapper wrappedMethod -> here it sends #flushCache to my wrapper instance.
In the StandardVM, I realised that at that moment, there is an entry in the cache that has selector: #foo, method: my wrapped instance, class: MyClass, etc...
So, to flush this, I have to options:
MyWrappers>>flushCache self wrappedMethod selector flushCache
or....
MyWrappers>>flushCache <primitive: 116>
this is because "self" will be found in the entry as "method" in the cache table...
So, first, are my assumptions correct?
Now, in cog I am not sure if both solutions are still valid. If I see CoInterpreterPrimitives>> primitiveFlushCacheByMethod
you do at the end:
(self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]
and
methodHasCogMethod: aMethodOop <api> self assert: (objectMemory isNonIntegerObject: aMethodOop). ^self isCogMethodReference: (self rawHeaderOf: aMethodOop)
So, it is not safe if the method is something different than a compiled method.
Is that correct? should I flush the cache entering by selector instead? which is the safe way to clean the cache in this case?
thanks
Mariano
Thanks Eliot. So I assume that the correcet way to implement #flushCache in my object as method is this:
MyObjectAsMethod>>flushCache <primitive: 116>
thanks Eliot
Mariano
On Sun, Mar 20, 2011 at 5:32 PM, Eliot Miranda eliot.miranda@gmail.comwrote:
Hi Mariano,
VMMaker-oscog.52 is uploading:
primitiveFlushCacheByMethod "The receiver is a compiledMethod. Clear all entries in the method lookup cache that refer to this method, presumably because it has been redefined, overridden or removed. Override to flush appropriate machine code caches also." | probe oldMethod primIdx | oldMethod := self stackTop. probe := 0. 1 to: MethodCacheEntries do: [:i | (methodCache at: probe + MethodCacheMethod) = oldMethod ifTrue: [methodCache at: probe + MethodCacheSelector put: 0]. probe := probe + MethodCacheEntrySize]. (objectMemory isOopCompiledMethod: oldMethod) ifTrue: [primIdx := self primitiveIndexOf: oldMethod. primIdx = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oldMethod]. (self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]]
On Wed, Mar 16, 2011 at 3:20 AM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi Eliot. I am implementing some kind of MethodWrappes/ObjectsAsMethod, whihc basically use the #run:with:in trick. My question is that I am not sure how to implement #flushCache in my wrappers. This method is called by MethodDictionary>>#at:put: when I want to put back the original CompiledMethod.
MyClass methodDict at: #foo put: MyWrapper withMethod: (MyClass>>#foo). ... MyClass methodDict at: #foo put: wrapper wrappedMethod -> here it sends #flushCache to my wrapper instance.
In the StandardVM, I realised that at that moment, there is an entry in the cache that has selector: #foo, method: my wrapped instance, class: MyClass, etc...
So, to flush this, I have to options:
MyWrappers>>flushCache self wrappedMethod selector flushCache
or....
MyWrappers>>flushCache <primitive: 116>
this is because "self" will be found in the entry as "method" in the cache table...
So, first, are my assumptions correct?
Now, in cog I am not sure if both solutions are still valid. If I see CoInterpreterPrimitives>> primitiveFlushCacheByMethod
you do at the end:
(self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]
and
methodHasCogMethod: aMethodOop <api> self assert: (objectMemory isNonIntegerObject: aMethodOop). ^self isCogMethodReference: (self rawHeaderOf: aMethodOop)
So, it is not safe if the method is something different than a compiled method.
Is that correct? should I flush the cache entering by selector instead? which is the safe way to clean the cache in this case?
thanks
Mariano
On Sun, Mar 20, 2011 at 9:52 AM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Thanks Eliot. So I assume that the correcet way to implement #flushCache in my object as method is this:
MyObjectAsMethod>>flushCache <primitive: 116>
Sure. ANother way would be something like
Object methods flushCache self primFlushCacheIfSelector. self primFlushCacheIfMethod
primFlushCacheIfSelector <primitive: 119> ^nil
primFlushCacheIfMethod <primitive: 116>
But I would be tempted to define a new prim, primFlushIfSelectorAndMethod if I were going to go that route long-term, e.g.
Object methods flushCache "Flush method lookup caches for the receiver whether it functions as a selector or a method." <primitive: 215> "OIf the primitive fails it probably isn't supported; fall back on the older slower prims" self primFlushCacheIfSelector. self primFlushCacheIfMethod
thanks Eliot
Mariano
On Sun, Mar 20, 2011 at 5:32 PM, Eliot Miranda eliot.miranda@gmail.comwrote:
Hi Mariano,
VMMaker-oscog.52 is uploading:
primitiveFlushCacheByMethod "The receiver is a compiledMethod. Clear all entries in the method lookup cache that refer to this method, presumably because it has been redefined, overridden or removed. Override to flush appropriate machine code caches also." | probe oldMethod primIdx | oldMethod := self stackTop. probe := 0. 1 to: MethodCacheEntries do: [:i | (methodCache at: probe + MethodCacheMethod) = oldMethod ifTrue: [methodCache at: probe + MethodCacheSelector put: 0]. probe := probe + MethodCacheEntrySize]. (objectMemory isOopCompiledMethod: oldMethod) ifTrue: [primIdx := self primitiveIndexOf: oldMethod. primIdx = PrimitiveExternalCallIndex ifTrue: ["It's primitiveExternalCall" self flushExternalPrimitiveOf: oldMethod]. (self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]]
On Wed, Mar 16, 2011 at 3:20 AM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi Eliot. I am implementing some kind of MethodWrappes/ObjectsAsMethod, whihc basically use the #run:with:in trick. My question is that I am not sure how to implement #flushCache in my wrappers. This method is called by MethodDictionary>>#at:put: when I want to put back the original CompiledMethod.
MyClass methodDict at: #foo put: MyWrapper withMethod: (MyClass>>#foo). ... MyClass methodDict at: #foo put: wrapper wrappedMethod -> here it sends #flushCache to my wrapper instance.
In the StandardVM, I realised that at that moment, there is an entry in the cache that has selector: #foo, method: my wrapped instance, class: MyClass, etc...
So, to flush this, I have to options:
MyWrappers>>flushCache self wrappedMethod selector flushCache
or....
MyWrappers>>flushCache <primitive: 116>
this is because "self" will be found in the entry as "method" in the cache table...
So, first, are my assumptions correct?
Now, in cog I am not sure if both solutions are still valid. If I see CoInterpreterPrimitives>> primitiveFlushCacheByMethod
you do at the end:
(self methodHasCogMethod: oldMethod) ifTrue: [cogit unlinkSendsTo: (self cogMethodOf: oldMethod)]
and
methodHasCogMethod: aMethodOop <api> self assert: (objectMemory isNonIntegerObject: aMethodOop). ^self isCogMethodReference: (self rawHeaderOf: aMethodOop)
So, it is not safe if the method is something different than a compiled method.
Is that correct? should I flush the cache entering by selector instead? which is the safe way to clean the cache in this case?
thanks
Mariano
vm-dev@lists.squeakfoundation.org