Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1146.mcz ==================== Summary ==================== Name: Kernel-eem.1146 Author: eem Time: 13 January 2018, 7:16:52.936871 pm UUID: 3ff238e6-dc26-491f-96de-a9b1520c4608 Ancestors: Kernel-eem.1145 Follow Clément's lead and redefine CompiledCode>>#= in terms of the subclass responsibility hasSameLiteralsAs: which avoids comparing the last literal in COmpiledBlock (the outerCode pointer) which neatly eliminates infinite recursion and considers iotherwise identical blocks embedded in different methiods as being equal. =============== Diff against Kernel-eem.1145 =============== Item was added: + ----- Method: CompiledBlock>>hasSameLiteralsAs: (in category 'comparing') ----- + hasSameLiteralsAs: aMethod + "Answer whether the receiver has the same sequence of literals as the argument. + Do not fully compare the last literal as this is the outerCode back pointer to the + containing method or block, and following it would cause infinite recursion. In any + case this is a useful definition because it considers identical block methods in other- + wise different containing blocks or methods to be the same, which makes sense." + | numLits | + numLits := self numLiterals. + numLits = aMethod numLiterals ifFalse: [^false]. + 1 to: numLits - 1 do: + [:i| | lit1 lit2 | + lit1 := self literalAt: i. + lit2 := aMethod literalAt: i. + (lit1 == lit2 or: [lit1 literalEqual: lit2]) ifFalse: + [^false]]. + ^(self literalAt: numLits) isCompiledCode = (aMethod literalAt: numLits) isCompiledCode! Item was changed: ----- Method: CompiledCode>>= (in category 'comparing') ----- + = aMethod + "Answer whether the receiver implements the same code as the argument, aMethod. - = method - "Answer whether the receiver implements the same code as the argument, method. Here ``same code'' means that if the receiver's source is compiled with the same compiler it should produce the same sequence of bytecodes and literals, same trailer and same properties. Hence this definition of #= (only one of many plausible definitions) can be used to quickly identify changes in the compiler's output." + self == aMethod ifTrue: - | numLits | - self == method ifTrue: [^true]. + (aMethod isCompiledCode + and: [self size = aMethod size + and: [self header = aMethod header]]) ifFalse:"N.B. includes numLiterals comparison." + [^false]. - method isCompiledCode ifFalse: [^false]. - self size = method size ifFalse: [^false]. - self header = method header ifFalse: [^false]. "N.B. includes numLiterals comparison." self initialPC to: self endPC do: + [:i | (self at: i) = (aMethod at: i) ifFalse: [^false]]. + ^self hasSameLiteralsAs: aMethod! - [:i | (self at: i) = (method at: i) ifFalse: [^false]]. - numLits := self numLiterals. - 1 to: numLits do: - [:i| | lit1 lit2 | - lit1 := self literalAt: i. - lit2 := method literalAt: i. - (lit1 == lit2 or: [lit1 literalEqual: lit2]) ifFalse: - [(i = 1 and: [#(117 120) includes: self primitive]) - ifTrue: - [lit1 isArray - ifTrue: - [(lit2 isArray and: [(lit1 first: 2) = (lit2 first: 2)]) ifFalse: - [^false]] - ifFalse: "ExternalLibraryFunction" - [(lit1 analogousCodeTo: lit2) ifFalse: - [^false]]] - ifFalse: - [i = (numLits - 1) - ifTrue: "properties" - [(self properties analogousCodeTo: method properties) - ifFalse: [^false]] - ifFalse: "last literal (methodClassAssociation) of class-side methods is not unique" - "last literal of CompiledBlock is outerMethod and may not be unique." - [(self isCompiledBlock - and: [lit1 isCompiledCode - and: [lit2 isCompiledCode]]) ifTrue: - [^true]. - (i = numLits - and: [lit1 isVariableBinding - and: [lit2 isVariableBinding - and: [lit1 key == lit2 key - and: [lit1 value == lit2 value]]]]) ifFalse: - [^false]]]]]. - ^true! Item was added: + ----- Method: CompiledCode>>hasSameLiteralsAs: (in category 'comparing') ----- + hasSameLiteralsAs: aMethod + "Answer whether the receiver has the same sequence of literals as the argument." + self subclassResponsibility! Item was added: + ----- Method: CompiledMethod>>hasSameLiteralsAs: (in category 'comparing') ----- + hasSameLiteralsAs: aMethod + "Answer whether the receiver has the same sequence of literals as the argument. + Compare the last literal, which is the class association, specially so as not to + differentiate between otherwise identical methods installed in different classes. + Compare the first literal carefully if it is the binding informaiton for an FFI or + external primitive call. Don't compare all of the state so that linked and unlinked + methods are still considered equal." + | numLits | + numLits := self numLiterals. + numLits = aMethod numLiterals ifFalse: [^false]. + 1 to: numLits do: + [:i| | lit1 lit2 | + lit1 := self literalAt: i. + lit2 := aMethod literalAt: i. + (lit1 == lit2 or: [lit1 literalEqual: lit2]) ifFalse: + [(i = 1 and: [#(117 120) includes: self primitive]) + ifTrue: + [lit1 isArray + ifTrue: + [(lit2 isArray and: [(lit1 first: 2) = (lit2 first: 2)]) ifFalse: + [^false]] + ifFalse: "ExternalLibraryFunction" + [(lit1 analogousCodeTo: lit2) ifFalse: + [^false]]] + ifFalse: + [i = (numLits - 1) + ifTrue: "properties" + [(self properties analogousCodeTo: aMethod properties) + ifFalse: [^false]] + ifFalse: "last literal (methodClassAssociation) of class-side methods is not unique" + "last literal of CompiledBlock is outerMethod and may not be unique." + [(self isCompiledBlock + and: [lit1 isCompiledCode + and: [lit2 isCompiledCode]]) ifTrue: + [^true]. + (i = numLits + and: [lit1 isVariableBinding + and: [lit2 isVariableBinding + and: [lit1 key == lit2 key + and: [lit1 value == lit2 value]]]]) ifFalse: + [^false]]]]]. + ^true! |
Free forum by Nabble | Edit this page |