The register coloring algorithm's not dirtying registers right, and
looks to be assuming that things are in registers across method calls
when they really aren't. The following test program shows the
problem. While it should print "In method 1\nIn method 2\n" a few
dozen times, instead it dies partway through. From a trace it looks
like the coloring algorithm assumes that an object is in a register
that gets clobbered (correctly) by the method calls.
.namespace ["Foo"]
.sub __biginit prototyped, @MAIN
newclass $P0, "Foo"
$I1 = find_type "Foo"
$P1 = new $I1
$P1.method1()
$P1.method2()
$P2 = new $I1
$P2.method1()
$P2.method2()
$P3 = new $I1
$P3.method1()
$P3.method2()
$P4 = new $I1
$P4.method1()
$P4.method2()
$P5 = new $I1
$P5.method1()
$P5.method2()
$P6 = new $I1
$P6.method1()
$P6.method2()
$P7 = new $I1
$P7.method1()
$P7.method2()
$P8 = new $I1
$P8.method1()
$P8.method2()
$P9 = new $I1
$P9.method1()
$P9.method2()
$P10 = new $I1
$P10.method1()
$P10.method2()
$P11 = new $I1
$P11.method1()
$P11.method2()
$P12 = new $I1
$P12.method1()
$P12.method2()
$P13 = new $I1
$P13.method1()
$P13.method2()
$P14 = new $I1
$P14.method1()
$P14.method2()
$P15 = new $I1
$P15.method1()
$P15.method2()
$P1.method1()
$P1.method2()
$P2.method1()
$P2.method2()
$P3.method1()
$P3.method2()
$P4.method1()
$P4.method2()
$P5.method1()
$P5.method2()
$P6.method1()
$P6.method2()
$P7.method1()
$P7.method2()
$P8.method1()
$P8.method2()
$P9.method1()
$P9.method2()
$P10.method1()
$P10.method2()
$P11.method1()
$P11.method2()
$P12.method1()
$P12.method2()
$P13.method1()
$P13.method2()
$P14.method1()
$P14.method2()
$P15.method1()
$P15.method2()
end
.end
.sub method1 prototyped, method
print "In method 1\n"
.pcc_begin_return
.pcc_end_return
.end
.sub method2 prototyped, method
print "In method 2\n"
.pcc_begin_return
.pcc_end_return
.end
--
Dan
--------------------------------------it's like this-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
> The register coloring algorithm's not dirtying registers right,
There are still some compatibility hooks inside parrot that set P1 on
the caller's end (or on both sides). I'll remove this remenants RSN.
leo
Looking a bit deeper into this bug reveals that above sentence doesn't
describe fully what happens, and it additionally depends on the register
allocator (CVS or new).
1) current CVS allocator
* P28 .. P30 are used to allocate temps and not allocated else
* P31 is reserved for spilling
* the old allocator doesn't have the code WRT preserved registers, which
was written for the new one (it could be backported)
* the register allocator needs 3 more registers and allocates P0, P1, P3
(P2 is visible in "set P2, Px" that moves the object in place)
Now implicit register usage strikes back. The register allocator isn't
aware of the side effect that C<callmethodcc> clobbers P0, P1, and S0.
2) new allocator
* has a list of allocatables usable for temps and has a clear notion
of preserved vs non-preserved registers
static const char assignable[4][5] = {
/* 0 1 2 3 4 */
{ 0, 0, 0, 0, 0, }, /* I */
{ 0, 1, 1, 1, 1, }, /* S */
{ 0, 0, 0, 1, 1, }, /* P */
{ 1, 1, 1, 1, 1, }, /* N */
};
* code would execute correctly, one more used register would cause
spilling
leo
> The register coloring algorithm's not dirtying registers right, and
> looks to be assuming that things are in registers across method calls
> when they really aren't.
Fixed and thanks for the test case,
leo