Bill Coffman <[EMAIL PROTECTED]> wrote:
> Hello,

> * I have the below failed tests.

> t/library/dumper.t   13  3328    13   13 100.00%  1-13

These are fixed (assignment collisions in pcc.c)

> t/op/gc.t             1   256    18    1   5.56%  13

Is very similar to the case below - gc_14 (you might read that one
first, it's a bit simpler). The variable C<arr2> is assigned to P17. In
gc_13.imc:80 the temp C<$P0> is also getting this register.  Now when
the algorithm backtracks over "y = choose(arr2)" arr2 in P17 is
clobbered and we get "shift_pmc() not implemented in class 'Closure'".
(You can turn on these print statements to see the flow of operations)

There is no sign in the source code, that the control flow from calling
choose() the second time to calling the "fail" closure might be a branch
target. We basically have a loop (due to the continuation usage), which
the register allocator can't be aware of.

Inserting a label e.g.

  lp:
    y = choose(arr2)

and a "branch lp" after the call to the "fail" closure hides the
problem, because with that loop, C<arr2> is preserved. (arr1 is still
clobbered, but the algorithm doesn't bactrack there again).


> t/pmc/sub.t           1   256    78    1   1.28%  78

tb_loop:
        set P17, P16[K16]
                    ^^^^^

Somewhere a SymReg with set 'K' has slipped into the register allocator.
Excluding r->set != 'K' in build_reglist():405 fixes that.


Now failing too is t/op/gc_14 (and an exception test, which is the
same). These 2 are a bit tricky and I don't know, which result is
correct - or better there is probably no answer.

We have this recursive method:

  sub b11 method
    .param int n
    .local int n1
    n1 = n + 1
    newsub $P0, .Exception_Handler, catch
    set_eh $P0
    n = self."b11"(n1)
    clear_eh
  catch:
    .pcc_begin_return
    .return n
    .pcc_end_return
  .end

C<n1> is going into the recursive call, C<n> is the return result. Now
it depends on the register allocator which register C<n1> and C<n> have.
When the allocator isn't really clever then it assigns different
registers. So C<n> is preserved when the exception is fired as the
recursion limit is hit.

The new allocator assigns both C<n1> and C<n> to the same Parrot
register. This is technically correct, as the life-span of C<n> ends on
the line where it's used as a return result of the recursive method call.

Therefore we have a piece of code that in the presence of exceptions may
behave differently depending on some implementation details. This is
AFAIK very the same, as the gcc warning we had until a few days about a
possibly clobbered variable used around setjmp (s. src/inter_run.c:55,
and the variable offset. (It's a volatile now)

This is totally the same variable usage like above's C<n> and the result
depends on register allocation details.

> ~Bill

leo

Reply via email to