2014-10-22 0:45 GMT+02:00 Eliot Miranda <eliot.miranda@gmail.com>:


On Tue, Oct 21, 2014 at 1:02 PM, Nicolai Hess <nicolaihess@web.de> 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