On Sat, Sep 17, 2011 at 8:39 AM, Mariano Martinez Peck < [email protected]> wrote:
> 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? > Compile them from source using the same and different source. Generate source with subtle differences etc. e.g. use Behavior>compile:classified:notifying:trailer:ifFail: which answers a compiled method. > 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 > > -- best, Eliot
