2014-10-22 0:45 GMT+02:00 Eliot Miranda <[email protected]>: > > > On Tue, Oct 21, 2014 at 1:02 PM, Nicolai Hess <[email protected]> wrote: > >> >> The more I tried to change/fix the compiler and checking the failing >> testcases, >> the more I learn about it. >> Finally I think the compiler and testcases are mostly right and my >> understanding was wrong. >> >> My (wrong) assumptions were: >> - the "numTemps" in the method header is always the number of declared >> temps, regardless whether they end up in an indirection vector >> > > Ah, no. It is the sum of the arguments and the local temporaries. So it > is the position to set the stack pointer to on activating a method. > > >> - the inlined ifTrue: and the inlined whileTrue: blocks are handled the >> same way, >> >> both assumptions are wrong: >> A method that starts with >> foo >> | a b c| >> >> and all temps end up in an indirect vector has only 1 tempvar, the >> "indirection vector" and even "numTemps" in the method header is 1. >> >> ifTrue and whileTrue are handled differently for example in this case >> >> |a| >> a:=1. >> (...) ifTrue:[ >> ... assign to "a" >> ... create a block which uses "a" >> ] >> >> the block only needs a copy of "a", as it is not changed after the >> creation of the block >> > > Right. > > >> >> |a| >> a:=1. >> [...] whileTrue:[ >> ... assign to "a" >> ... create a block which uses "a" >> ] >> >> here we need a indirection vector, because the while-block *can* loop >> repeatedly and change the value of "a" after >> an block was created. >> > > Right. In general the compiler cannot tell whether the whileTrue: will be > executed 0, 1 or many times. In cases where it can tell it would take lots > of machinery to do so and only be able to tell in relatively few cases. So > the compiler always assumes the whileTrue: is evaluated more than once, and > hence that it is possible for a block to be created and a modified in a > subsequent iteration of the loop. Hence it must put a in an indirection > vector. > > >> If this is all correct, there is only one problem in this special case >> (my example above): >> If there is no assignment within the loop at all, there is no need to >> create a indirection vector and >> all used vars (a b c) can just be copied. >> >> >> Or am I still confused ?! >> > > No you're not. You get it now :-). One question is whether you can > explain it all better than I did on my blog, because people seem to find > this area of teh system hard and take a while to "get it". >
@eliot Your blog contains all the information needed. But if someone don't have already a deep knowledge of the compiler and VM-internals, it can be a bit overwhelming. And I must admit I have overread or skipped some parts, because I thought they are not important or because I didn't understand :) And now I found the place in the (old) compiler, where the blocks in optimized loops are handled. You search for assignments in a loop and if one is found, restart the "analyseClosure" as if the write had happened after the close over. Now I need to find a way to do the same with opal compiler. It is (and looks a lot) different than the old compiler. It tags the variables with a usage marker #write, #read and an "escaping" flag. And it does only one pass over the tree. But this way, it can not distinguish between a write that happens before entering the loop from a write happening within the loop. @marcus I propese an extra usage tag #writeInLoop, that is only set on assignments within a loop. And then, mark an "escaping" var in an optimized loop only as "escapingWrite", if it is marked as "writeInLoop". > > nicolai >> > -- > best, > Eliot >
