OK, I fixed this (a pleasant Monday afternoon distraction) (at least I *think* I've fixed it; I still have to check the decompiler). �But... in doing so I realised I had to fix CompiledMethod>>#= since I needed to see exactly which methods the compiler change affected (just committed as Kernel-eem.669). �In doing this I noticed that recent compiler changes have not been applied by recompiling affected methods in the system. �If you look at Behavior>>#sourceMatchesBytecodeAt: it uses CompiledMethod>>#= to check that the compiler's output remains unchanged. �In the 4.3 trunk image with CompiledMethod>>#= fixed,�sourceMatchesBytecodeAt: reports that some�19654 methods need recompiling:
Hi All,� � (whitewash alert) �I just had occasion to look at the bytecode generated by the standard compiler for HashedCollection class>>#goodPrimeAtLeast:. �Here's the source, with the issue in bold:goodPrimeAtLeast: lowerLimit"Answer the next good prime >= lowerlimit.If lowerLimit is larger than the largest known good prime,just make it odd."| primes low mid high prime |primes := self goodPrimes.low := 1.high := primes size.lowerLimit > (primes at: high) ifTrue: [^lowerLimit bitOr: 1 ].[ high - low <= 1 ] whileFalse: [mid := high + low // 2.prime := primes at: mid.prime = lowerLimit ifTrue: [ ^prime ].prime < lowerLimitifTrue: [ low := mid ]ifFalse: [ high := mid ] ].(primes at: low) >= lowerLimit ifTrue: [ ^primes at: low ].^primes at: highThe code for this sequence is58 <15> pushTemp: 559 <10> pushTemp: 060 <B2> send: <61 <9B> jumpFalse: 6662 <13> pushTemp: 363 <81 42> storeIntoTemp: 265 <92> jumpTo: 6966 <13> pushTemp: 367 <81 44> storeIntoTemp: 469 <87> pop
where-as the following would be better:58 <15> pushTemp: 559 <10> pushTemp: 060 <B2> send: <61 <9B> jumpFalse: 6662 <13> pushTemp: 363 <82 42> popIntoTemp: 265 <92> jumpTo: 6966 <13> pushTemp: 367 <82 44> popIntoTemp: 4The reason is that the code generator favours using a single pop for both arms of the if:MessageNode>>sizeCodeForIf: encoder value: forValue| thenExpr elseExpr branchSize thenSize elseSize |thenExpr := arguments at: 1.elseExpr := arguments at: 2.(forValueor: [(thenExpr isJust: NodeNil)or: [elseExpr isJust: NodeNil]]) not"(...not ifTrue: avoids using ifFalse: alone during this compile)"ifTrue: �"Two-armed IFs forEffect share a single pop"[^super sizeCodeForEffect: encoder]....MessageNode>>emitCodeForIf: stack encoder: encoder value: forValue| thenExpr thenSize elseExpr elseSize |thenSize := sizes at: 1.elseSize := sizes at: 2.(forValue not and: [elseSize * thenSize > 0]) ifTrue:"Two-armed IFs forEffect share a single pop"[^super emitCodeForEffect: stack encoder: encoder].It would be nice if this only happened if doing so actually reduced the size of the generated code.--
best,Eliot