[Pharo-project] problem with CompiledMethod equality
Hi folks. I was debugging a problem with Moose and I realized that 2 different methods can have the same CompiledMethod. This was weird for me. I don't know if this is correct or not. For example, evaluate: (InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup) -> true If you look at CompiledMethod = aCompiledMethod "Answer whether the receiver implements the same code as aCompiledMethod." | numLits | self == aCompiledMethod ifTrue: [ ^ true ]. self class = aCompiledMethod class ifFalse: [ ^ false ]. self size = aCompiledMethod size ifFalse: [ ^ false ]. self header = aCompiledMethod header ifFalse: [ ^ false ]. self initialPC to: self endPC do: [ :i | (self at: i) = (aCompiledMethod at: i) ifFalse: [ ^ false ] ]. (self sameLiteralsAs: aCompiledMethod) ifFalse: [ ^ false ]. self halt. ^ true It is returning in the last ^ true. What was weird for me is that (self sameLiteralsAs: aCompiledMethod) returns true also. But if I print both literals: self literals -> {#methodReturnTop. (#InstructionClient->InstructionClient)} aCompiledMethod literals -> {#doDup. (#InstructionClient->InstructionClient)} So...for me they are differnt, but sameLiteralsAs: is returning true. Debugging that, it seems that in that method it is returning in the last ^ true. So...any hints? is this the expected behavior ? or it is a bug ? Thanks Mariano
Sorry...I forgot a detail: the problem is that they were storing CompiledMethods in a Dictionary, keys. I guess in Pharo 1.0 it works perfect, but in 1.1 since keys return a Set (that was the changed?), you miss some methods ;) Just do InstructionClient methods size -> 27 InstructionClient methods asSet size -> 21 so...it is not fun :( solution ? ideas? help ? Thanks :) On Tue, May 18, 2010 at 3:35 PM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi folks. I was debugging a problem with Moose and I realized that 2 different methods can have the same CompiledMethod. This was weird for me. I don't know if this is correct or not.
For example, evaluate:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup) -> true
If you look at
CompiledMethod = aCompiledMethod "Answer whether the receiver implements the same code as aCompiledMethod."
| numLits | self == aCompiledMethod ifTrue: [ ^ true ]. self class = aCompiledMethod class ifFalse: [ ^ false ]. self size = aCompiledMethod size ifFalse: [ ^ false ]. self header = aCompiledMethod header ifFalse: [ ^ false ]. self initialPC to: self endPC do: [ :i | (self at: i) = (aCompiledMethod at: i) ifFalse: [ ^ false ] ]. (self sameLiteralsAs: aCompiledMethod) ifFalse: [ ^ false ]. self halt. ^ true
It is returning in the last ^ true.
What was weird for me is that (self sameLiteralsAs: aCompiledMethod) returns true also. But if I print both literals:
self literals -> {#methodReturnTop. (#InstructionClient->InstructionClient)}
aCompiledMethod literals -> {#doDup. (#InstructionClient->InstructionClient)}
So...for me they are differnt, but sameLiteralsAs: is returning true. Debugging that, it seems that in that method it is returning in the last ^ true.
So...any hints? is this the expected behavior ? or it is a bug ?
Thanks
Mariano
On May 18, 2010, at 3:39 33PM, Mariano Martinez Peck wrote:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12. I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding. Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits -1 = index is checked? At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 contains properties.... Cheers, Henry
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12.
I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding.
That's fine, the method has no bytecode. It is a quick-return self.
Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits  -1 = index is checked?
Check the VM source/compiler on the different special literal slots and how different kind of primitives are encoded.
At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 Â contains properties....
The two literals are the selector and the class-binding, as the method comment says these literals are not considered for equality. Lukas -- Lukas Renggli www.lukas-renggli.ch
On May 18, 2010, at 4:41 41PM, Lukas Renggli wrote:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12.
I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding.
That's fine, the method has no bytecode. It is a quick-return self.
Ah yes, inspecting it I saw bytes 13 -16 which were diferent, didn't realize those were the trailer itself :) Doh! Cheers, Henry
On May 18, 2010, at 4:41 41PM, Lukas Renggli wrote:
Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits -1 = index is checked?
Check the VM source/compiler on the different special literal slots and how different kind of primitives are encoded.
Wouldn't it be nice to document this in the method as well, so
At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 contains properties....
The two literals are the selector and the class-binding, as the method comment says these literals are not considered for equality.
Hmmm, which method comment? In my image, at the top of sameLiteralsAs: it says: "Compare my literals to those of method. This is needed to compare compiled methods." And in = "Answer whether the receiver implements the same code as aCompiledMethod." Nothing about which literals are or aren't considered for equality :(
On May 18, 2010, at 4:15 33PM, Henrik Johansen wrote:
On May 18, 2010, at 3:39 33PM, Mariano Martinez Peck wrote:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12.
I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding.
Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits -1 = index is checked?
At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 contains properties....
Oh, ok, numLit -1 contains the selector. So that would be the "except selector" Lukas mentioned. Same method in different classes do not equal eachother though, if I've not made a mistake in: |mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [ REALLY deserve some comments... Cheers, Henry
Please send me that and I will integrate it. Stef On May 18, 2010, at 4:46 PM, Henrik Johansen wrote:
On May 18, 2010, at 4:15 33PM, Henrik Johansen wrote:
On May 18, 2010, at 3:39 33PM, Mariano Martinez Peck wrote:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12.
I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding.
Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits -1 = index is checked?
At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 contains properties....
Oh, ok, numLit -1 contains the selector.
So that would be the "except selector" Lukas mentioned. Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On May 18, 2010, at 4:58 18PM, Stéphane Ducasse wrote:
Please send me that and I will integrate it.
Stef
If I had any idea what a helpful comments would be, I would :) Clearly, I just don't understand it at all atm though, and I really don't have time to read the Compiler and/or VM sources to figure it out. Cheers, Henry
On May 18, 2010, at 4:46 PM, Henrik Johansen wrote:
On May 18, 2010, at 4:15 33PM, Henrik Johansen wrote:
On May 18, 2010, at 3:39 33PM, Mariano Martinez Peck wrote:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup)
methodReturnTop startPC -> 13 methodReturnTop endPC -> 12.
I have a slight feeling that is one of the reasons :) Seems to be related to method trailers size assumptions not holding.
Also, sameLiteralsAs: is a mess. There are no comments really revealing the intention of the 8 ifTrue/False branches, no refactoring to use revealing method names... Can anyone explain to me why numLits -1 = index is checked?
At least for methodReturnTop, which has 2 literals, it certainly does not seem like numLits -1 contains properties....
Oh, ok, numLit -1 contains the selector.
So that would be the "except selector" Lukas mentioned. Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Same method in different classes do not  equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=. In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class. Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
Hi Lukas, On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches). The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it. (pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good). best Eliot
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
2010/5/19 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Lukas,
On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not  equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. Â The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. Â This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Â Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches). The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. Â While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it. (pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good). best Eliot
Well, we could have a cake and eat it too. - rename #= to #isEqualToMethod: Then, the parts which intentionally require a comparisons, like you described above, will use this message. While for the rest of smalltalk code , sending #= will end up being #==.
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
Elliot I think that we already took into changes made by nicolas. Stef On May 19, 2010, at 2:35 AM, Eliot Miranda wrote:
Hi Lukas,
On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches).
The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it.
(pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good).
best Eliot
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Hi Eliot, What about super sends ? Object>>beNasty ^self Collection>>beNasty self addLast; 1. super beNasty. OrderedCollection>>beNasty self addLast; 1. super beNasty. Do you think you can remove OrderedCollection>>beNasty ? Nicolas 2010/5/19 Stéphane Ducasse <stephane.ducasse@inria.fr>:
Elliot I think that we already took into changes made by nicolas.
Stef
On May 19, 2010, at 2:35 AM, Eliot Miranda wrote:
Hi Lukas,
On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not  equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. Â The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. Â This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Â Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches).
The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. Â While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it.
(pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good).
best Eliot
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On Wed, May 19, 2010 at 4:58 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Eliot, What about super sends ?
Object>>beNasty ^self
Collection>>beNasty self addLast; 1. super beNasty.
OrderedCollection>>beNasty self addLast; 1. super beNasty.
Good point. I still find the existing #= definition very useful for compiler verification.
Do you think you can remove OrderedCollection>>beNasty ?
Nicolas
2010/5/19 Stéphane Ducasse <stephane.ducasse@inria.fr>:
Elliot I think that we already took into changes made by nicolas.
Stef
On May 19, 2010, at 2:35 AM, Eliot Miranda wrote:
Hi Lukas,
On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches).
The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it.
(pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good).
best Eliot
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
Wow.....the conversation went far away from my understanding and knowledge. I will try to read it slowly and carefully, several times and try to understand what you said. For the moment (just my needs) the solution from Lukas worked: use IdentitityDictionary instead of Dictionary. Now I let you to you to decide if it is a bug or not, if it deserves comment, etc. Thank you very much. Mariano 2010/5/19 Eliot Miranda <eliot.miranda@gmail.com>
On Wed, May 19, 2010 at 4:58 AM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Hi Eliot, What about super sends ?
Object>>beNasty ^self
Collection>>beNasty self addLast; 1. super beNasty.
OrderedCollection>>beNasty self addLast; 1. super beNasty.
Good point. I still find the existing #= definition very useful for compiler verification.
Do you think you can remove OrderedCollection>>beNasty ?
Nicolas
2010/5/19 Stéphane Ducasse <stephane.ducasse@inria.fr>:
Elliot I think that we already took into changes made by nicolas.
Stef
On May 19, 2010, at 2:35 AM, Eliot Miranda wrote:
Hi Lukas,
On Tue, May 18, 2010 at 8:17 AM, Lukas Renggli <renggli@gmail.com> wrote:
Same method in different classes do not equal eachother though, if I've not made a mistake in:
|mrtCp| mrtCp := (InstructionClient>>#methodReturnTop) copy. mrtCp literalAt: 2 put: #ContextPart->ContextPart. (InstructionClient>>#methodReturnTop) = mrtCp
For methods that send super the behavior changes if you change the class binding. That's probably why it is not ignored for #=.
In fact I would suggest to #= from compiled method altogether, in most cases it doesn't do what one would expect in a given context anyway. There are too many and possibility completely different interpretations of #= for CompiledMethod. #== is the only decent implementation for this class.
I sympathise but I think there is a reasonable default interpretation of #= for CompiledMethod that is what most people want. The intent is to answer whether two methods have the same execution semantics and same method tags & properties, e.g. if one were to compile the same source code in two different classes that had the same inst var offsets for the inst vars in the methods, then one would want those methods to be #=. This allows tests such as - checking whether a subclass has a method that is #= to a superclass, and is hence redundant. - checking whether a set of sourceless methods are equivalent so that they may be shared under different selectors (e.g. think auto-generated accessor methods which can be cached and shared) So for this informal definition the selector and the class are irrelevant, but bytecodes and literals (apart from the selector and method class literals) are relevant. Its almost a short-cut comparison of error-free decompilation, although there are differences in the bytecode that wouldn't show in decompilation (e.g. using long branches for short branches).
The current definition serves for compiler hackers as it tells you accurately whether a compiler change has an effect on the bytecode, can be used to test whether compilation followed by decompilation followed by recompilation has an effect, etc. While it may not be a universal code comparison method it has met my needs throughout the closure compiler so at least I'm pretty happy with it.
(pleading for CompiledMethod>>#= to stay the same as the current Squeak 4.1 definition, which ever since Nichoas Celier's float compilation changes, is pretty darned good).
best Eliot
Lukas
At the very least, the branches of index = 1 and: [ #(117 120) includes: self primitive ]) ifTrue: [
REALLY deserve some comments...
Cheers, Henry
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
On May 18, 2010, at 3:35 PM, Mariano Martinez Peck wrote:
Hi folks. I was debugging a problem with Moose and I realized that 2 different methods can have the same CompiledMethod. This was weird for me. I don't know if this is correct or not.
For example, evaluate:
(InstructionClient>>#methodReturnTop) = (InstructionClient>>#doDup) -> true
If you look at
CompiledMethod = aCompiledMethod "Answer whether the receiver implements the same code as aCompiledMethod."
| numLits | self == aCompiledMethod ifTrue: [ ^ true ]. self class = aCompiledMethod class ifFalse: [ ^ false ]. self size = aCompiledMethod size ifFalse: [ ^ false ]. self header = aCompiledMethod header ifFalse: [ ^ false ]. self initialPC to: self endPC do: [ :i | (self at: i) = (aCompiledMethod at: i) ifFalse: [ ^ false ] ]. (self sameLiteralsAs: aCompiledMethod) ifFalse: [ ^ false ]. self halt. ^ true
It is returning in the last ^ true.
What was weird for me is that (self sameLiteralsAs: aCompiledMethod) returns true also. But if I print both literals:
self literals -> {#methodReturnTop. (#InstructionClient->InstructionClient)}
aCompiledMethod literals -> {#doDup. (#InstructionClient->InstructionClient)}
So...for me they are differnt, but sameLiteralsAs: is returning true. Debugging that, it seems that in that method it is returning in the last ^ true.
So...any hints? is this the expected behavior ? or it is a bug ?
certainly a bug
Thanks
Mariano
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
So...any hints? is this the expected behavior ? Â or it is a bug ?
certainly a bug
I would not say that this is a bug, it depends of course what you consider equal. The current definition of #= in compiled method is has same bytecode, same literals (except the class and selector) and same annotations. In your case you probably should use an IdentitySet or IdentityDictionary. Lukas -- Lukas Renggli www.lukas-renggli.ch
I was planning to have a look just after a couple of integrations... but you save my time :) On May 18, 2010, at 4:00 PM, Lukas Renggli wrote:
So...any hints? is this the expected behavior ? or it is a bug ?
certainly a bug
I would not say that this is a bug, it depends of course what you consider equal.
The current definition of #= in compiled method is has same bytecode, same literals (except the class and selector) and same annotations.
In your case you probably should use an IdentitySet or IdentityDictionary.
Lukas
-- Lukas Renggli www.lukas-renggli.ch
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
participants (7)
-
Eliot Miranda -
Henrik Johansen -
Igor Stasenko -
Lukas Renggli -
Mariano Martinez Peck -
Nicolas Cellier -
Stéphane Ducasse