2015-10-08 23:45 GMT+02:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Nicolai,
On Thu, Oct 8, 2015 at 2:27 PM, Nicolai Hess <nicolaihess@web.de> wrote:
Hello Eliot, and thanks for your time.
In our (pharo) implementation for sourceNodeForPC, we start at the AST-Node of the compiled method, get the IR (IntermediateRepresentation) and scan this sequence of IRNodes until we finally find that one, that maps to the bytecode of the closure creation code (this should be a IRPushClosureCopy). The problem is now, we don't find (always) the right IRNode, and it depens on the number of local temps, if this is > 3 we don't hit the right one.
That's very strange. Can you construct a synthetic example of two simple blocks, one with three temps and and one with four temps and show me the difference in the byte code?
[ :x | | a b c | a:=b:=c:=x ] "calling #sourceNode gives a RBBlockNode - ok" Bytecode 13 <8F 01 00 0B> closureNumCopied: 0 numArgs: 1 bytes 17 to 27 17 <73> pushConstant: nil 18 <73> pushConstant: nil 19 <73> pushConstant: nil 20 <10> pushTemp: 0 21 <81 43> storeIntoTemp: 3 23 <81 42> storeIntoTemp: 2 25 <81 41> storeIntoTemp: 1 27 <7D> blockReturn 28 <7C> returnTop [ :x | | a b c d | a:=b:=c:=d:=x ] "calling #sourceNode gives a RBMethodNode - not ok" Bytecode 13 <8F 01 00 0E> closureNumCopied: 0 numArgs: 1 bytes 17 to 30 17 <73> pushConstant: nil 18 <73> pushConstant: nil 19 <73> pushConstant: nil 20 <73> pushConstant: nil 21 <10> pushTemp: 0 22 <81 44> storeIntoTemp: 4 24 <81 43> storeIntoTemp: 3 26 <81 42> storeIntoTemp: 2 28 <81 41> storeIntoTemp: 1 30 <7D> blockReturn 31 <7C> returnTop As I wrote above, in Pharo, to get the sourceNode we try to find the push closure bytecode from "startpc - 1" by traversing the IR and try to get the IRNode with matching "bytecodeOffset". The bytecodeOffsets for the above blocks: [ :x | | a b c | a:=b:=c:=x ] "bytecodeOffset -> IR" 19->pushClosureCopyCopiedValues: #() args: #(#x) 28->returnTop 20->pushTemp: #x 22->storeTemp: #c 24->storeTemp: #b 26->storeTemp: #a 27->blockReturnTop [ :x | | a b c d | a:=b:=c:=d:=x ] "bytecodeOffset -> IR" 20->pushClosureCopyCopiedValues: #() args: #(#x) 31->returnTop 21->pushTemp: #x 23->storeTemp: #d 25->storeTemp: #c 27->storeTemp: #b 29->storeTemp: #a 30->blockReturnTop Both blocks don't have a bytecodeOffset matching the bytecode of the pushclosure (13), but we start the search from "startpc - 1" (= 16) and do a loop from 0 to -3 (because bytecodes can have a length of 1,2 or 4) For the first block, this works bytecodeOffset 19 = 16 - (-3) For the second block this does not work, somehow the bytecodeoffset value depends on the number of local temps. And for the second block this is one greater.
And my interpretation was, the IRPushClosureCopy node has the wrong
"bytecode offset" (whatever this is). The bytecodeOffset value (somehow) depends on the number of local temps, but maybe this is right (for whatever this is used) and we are just using it wrong for in this situation.
So you need to ask Marcus how to interpret bytecodeOffset. The thing is, it should be simple. One has:
BlockCreationBytecode any number of pushConstant: nil's (0 to N) first byte code in block last bytecode in block (always a blockReturnTop)
and a block's startup is always that of the byte immediately following the BlockCreationBytecode. So if the byte code offset is somehow the span of the "any number of pushConstant: nil's (0 to N)" then there's a bug in the IR somewhere when the number of temps is > 3. But if that's not what it means then, well, I don't know what the problem is.