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!
On Sat, Sep 17, 2011 at 11:30 AM, Mariano Martinez Peck <
[email protected]> wrote:
>
> Or maybe after reading:
>>>
>>> literal1 := self literalAt: numLits.
>>> literal2 := method literalAt: numLits.
>>> ^ (literal1 == literal2) or: [literal1 key isNil == literal2 key
>>> isNil and: [literal1 value == literal2 value]].
>>>
>>> I we are sure that the last literal is always an Association
>>>
>>
>> If 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]]
>>
>>
>>>
> Thanks. Issue and slice in
> http://code.google.com/p/pharo/issues/detail?id=4814
>
>
>
>
>> Nicolas
>>>
>>> >> On Fri, Sep 16, 2011 at 8:12 PM, Stéphane Ducasse
>>> >> <[email protected]> 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
>>
>>
>>
>>
>>
>
>
> --
> Mariano
> http://marianopeck.wordpress.com
>
>
--
Mariano
http://marianopeck.wordpress.com