I wanted to write a test (before Stef asked) but I don't know how to clearly copy a CompiledMethod. First I tried
CompiledMethodTest >> testEqualityClassSideMethod
��� | method1 method2 |
��� method1 := self class class >> #returnPlusOne:.
��� method2 := method1 veryDeepCopy.
��� self deny: (method1 literalAt: method1 numLiterals) ==� (method2 literalAt: method2 numLiterals).
��� self assert: method1 = method2.
���
And it doesn't work, the last literal of both CM point are #==.
Then I tried:
testEqualityClassSideMethod
��� | method1 method2 originalAssociation |
��� method1 := self class class >> #returnPlusOne:.
��� method2 := method1 veryDeepCopy.
��� originalAssociation := method2 literalAt: method2 numLiterals.
��� method2 literalAt: method2 numLiterals put: (Association key: originalAssociation key value: originalAssociation value).
��� method1 literalAt: method1 numLiterals put: (Association key: originalAssociation key value: originalAssociation value).
��� self deny: (method1 literalAt: method1 numLiterals) ==� (method2 literalAt: method2 numLiterals).
��� self assert: method1 = method2.
Again, same problem.
So...I don't know how can I copy a CM completly, that means, even use different objects for the last literals. Any ideas?
Thanks!
Or maybe after reading:
� �^ (literal1 == literal2) or: [literal1 key isNil == literal2 key
� �literal1 := self literalAt: numLits.
� �literal2 := method literalAt: numLits.
isNil and: [literal1 value == literal2 value]].
I we are sure that the last literal is always an AssociationIf it's not then one is playing fast and loose with the system. �But if the method doesn't contain a super send then as far as the VM is concerned it doesn't need an association, and that might be the case with, for example, shared inst var accessors in Newspeak. �So instead of assuming its an association write it something like� � ^literal1 class == literal2 class� � �and: [literal1 isVariableBinding� � � � � � � � ifTrue: [literal1 key = literal2 key and: [literal1 value = literal2 value]]� � � � � � � � ifFalse: [literal1 = literal2]]Nicolas
>> On Fri, Sep 16, 2011 at 8:12 PM, St�phane Ducasse
>> <stephane.ducasse@inria.fr> wrote:
>>>
>>> Mariano
>>>
>>> So should we intgerate a fix?
>>>
>>> Stef
>>>
>>> On Sep 15, 2011, at 11:27 PM, Mariano Martinez Peck wrote:
>>>
>>> >
>>> >
>>> >
>>> > BUT, it doesn't mean that Association is always used for globals.
>>> > CompiledMethod equality is failing because of the last literal, the one that
>>> > maps class name (symbol) and point to the real class. So...when I
>>> > materialize, both CMs have non-identical associations for the last literal,
>>> > but equal.
>>> >
>>> > As Henrik says the last literals are ideally #== to each other.
>>> > �However, no Squeak dialect makes any attempt to keep the class0side
>>> > associations equal. Look at a class-side method and you'll see it's last
>>> > literal is nil->SomeClass class. �Now since this association doesn't exist
>>> > in Smalltalk (unlike last literals on the instance side) the compiler merely
>>> > creates distinct ones for each class-side method.
>>> >
>>> >
>>> > Thanks Eliot for that point. In fact, I have just checked and you are
>>> > right. The tests that are failing for me is those where class side methods
>>> > are involded. In this case, the last literal of the original CM and the
>>> > materialized, gives false in #literalEqual: � hence, �originalCM =
>>> > materializedCM is false :(
>>> >
>>> >
>>> >
>>> > Personally I don't think one can defend the position where method
>>> > equality is different for instance-side or class-side methods so there must
>>> > be some solutions:
>>> >
>>> > 1. special case comparison of the last literal (the methodClass
>>> > literal), comparing keys and insisting that the keys be #== and the values
>>> > be #== (can't just define it as keys #== since all similar class-side
>>> > methods will be equal irrespective of their actual class).
>>> >
>>> >
>>> > This one seems the easier and fixes my problem :)
>>> >
>>> > sameLiteralsAs: method
>>> > � � "Compare my literals to those of method. This is needed to compare
>>> > compiled methods."
>>> >
>>> > � � | numLits literal1 literal2 |
>>> > � � (numLits := self numLiterals) ~= method numLiterals
>>> > � � � � ifTrue: [ ^ false ].
>>> > � � "The last literal requires special checking instead of using
>>> > #literalEqual:"
>>> > � � 1 to: numLits - 1 do: [ :index |
>>> > � � � � literal1 := self literalAt: index.
>>> > � � � � literal2 := method literalAt: index.
>>> > � � � � (literal1 == literal2 or: [ literal1 literalEqual: literal2 ])
>>> > � � � � � � ifFalse: [
>>> > � � � � � � � � (index = 1 and: [ #(117 120) includes: self primitive ])
>>> > � � � � � � � � � � ifTrue: [
>>> > � � � � � � � � � � � � literal1 isArray
>>> > � � � � � � � � � � � � � � ifTrue: [
>>> > � � � � � � � � � � � � � � � � (literal2 isArray and: [ literal1
>>> > allButLast = literal2 allButLast ])
>>> > � � � � � � � � � � � � � � � � � � ifFalse: [ self halt. ^ false ] ]
>>> > � � � � � � � � � � � � � � ifFalse: [
>>> > � � � � � � � � � � � � � � � � "ExternalLibraryFunction"
>>> > � � � � � � � � � � � � � � � � (literal1 analogousCodeTo: literal2)
>>> > � � � � � � � � � � � � � � � � � � ifFalse: [ self halt. ^ false ] ] ]
>>> > � � � � � � � � � � ifFalse: [
>>> > � � � � � � � � � � � � index = (numLits - 1)
>>> > � � � � � � � � � � � � � � ifTrue: [
>>> > � � � � � � � � � � � � � � � � "properties"
>>> > � � � � � � � � � � � � � � � � (self properties analogousCodeTo: method
>>> > properties)
>>> > � � � � � � � � � � � � � � � � � � ifFalse: [ self halt. ^ false ] ]
>>> > � � � � � � � � � � � � � � ifFalse: [ self halt. ^ false ] ] ] ].
>>> > � � literal1 := self literalAt: numLits.
>>> > � � literal2 := method literalAt: numLits.
>>> > � � ^ ((literal1 key == literal2 key) and: [literal1 value == literal2
>>> > value]).
>>> >
>>> >
>>> >
>>> > 2. special case comparison of the last literal (the methodClass
>>> > literal), insisting only that the class of the literal be the same if it
>>> > isVariableBinding.
>>> >
>>> > 3. make the compile unique class-side methodClass literals. �i.e. if a
>>> > class already has a class-side method then the compiler or method dictionary
>>> > insertion code must find that existing association and reuse it
>>> >
>>> > Other ideas?
>>> >
>>> > >From my point of view, that literal, the last one does not need to be
>>> > identical to assume 2 CMs are equal. They just need to be equal.
>>> >
>>> >
>>> > --
>>> > Mariano
>>> > http://marianopeck.wordpress.com
>>> >
>>> >
>>> >
>>> >
>>> > --
>>> > best,
>>> > Eliot
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >
>>> > --
>>> > Mariano
>>> > http://marianopeck.wordpress.com
>>> >
>>>
>>>
>>
>>
>>
>> --
>> Mariano
>> http://marianopeck.wordpress.com
>>
>>
>
--
best,Eliot
--