�� �� just stumbled across a bytecode compiler bug that's in both the Squeak compiler and the Opal compiler.�� I'm told by Cl��ment that Opal mimics the bug to avoid crashing legacy code.�� So there may be places that depend on this bug.�� It would be good to eliminate the dependencies and the bug.
For illustration look at the to:do: loop in the ifNil: arm in Context>>privRefresh:
"Reinitialize the receiver so that it is in the state it was at its creation."
closureOrNil
ifNotNil:
[pc := closureOrNil startpc.
self stackp: closureOrNil numArgs + closureOrNil numCopiedValues.
1 to: closureOrNil numCopiedValues do:
[:i | self tempAt: closureOrNil numArgs + i put: (closureOrNil at: i)]]
ifNil:
[pc := method initialPC.
self stackp: method numTemps.
method numArgs+1 to: method numTemps do:
[:i | self tempAt: i put: nil]]
This should evaluate method numArgs + 1 then method numTemps.�� If it were written as a non-in-lined (method numArgs+1 to: method numTemps) do: [:i| self tempAt: i put: nil] then the [self tempAt: i put: nil] block would be created next.�� But the bytecode for the inlined version is
self stackp: method numTemps.
63 <70> self
64 <84 40 03> pushRcvr: 3
67 <D6> send: numTemps
68 <E1> send: stackp:
69 <87> pop
iLimit := method numTemps
70 <84 40 03> pushRcvr: 3
73 <D6> send: numTemps
74 <69> popIntoTemp: 1
i := method numArgs + 1
75 <84 40 03> pushRcvr: 3
78 <D2> send: numArgs
79 <76> pushConstant: 1
80 <B0> send: +
81 <81 40> storeIntoTemp: 0 (squeak)��<69> popIntoTemp: 1 (pharo)
83 <10> pushTemp: 0
84 <11> pushTemp: 1
85 <B4> send: <=
86 <AC 0B> jumpFalse: 99
There is a second bug in the Squeak bytecode; storeIntoTemp: is used to load i whereas it should be popIntoTemp:.�� It was this second bug that alerted me to the order-of-evaluation bug.