petdance/scratch — Issue #15: cmp/bitwise/other mmd vtable functions should not go through proxy pmc
Author: petdance
Created: 2011-11-01 05:26:45+00:00
State: open
Labels: bug, core, Pri-normal, Sev-medium

In rakudo 1 <=> undef was doing the right thing while undef <=> 1 was failing. The first case works because integer.pmc has a multi cmp_num for undef and the VTABLE_get_integer(INTERP, value) call on the Failure value was correctly calling the Failure get_integer vtable method. When I tried to patch undef.pmcI noticed that I was having trouble getting a cmp_num vtable function in that file to call the Failure get_integer vtable method because the value for SELF was an undef pmc rather than a failure pmc. After further digging I concluded that the cmp_num function was being called through a proxy pmc and cmp_num was behaving differently in that regard from add and subtract which did an mmd call through the default pmc. The module lib/Parrot/Pmc2c/PMC/Object.pm generates the vtable forwarding functions and relies on the vtable_method_does_multi subroutine in lib/Parrot/Pmc2c/PMC.pm to decide which vtable methods go through a proxy and which don't.

After dropping by #parrot on Feb 5 I was advised that having bitwise and cmp functions go through a proxy pmc might be an oversight and I was asked to come up with an appropriate test if possible.

The patch included (not attached) below relies on the largely baseless assumption that none of the default pmc vtable mmd functions should go through a proxy from an object when I only seem to have been told that fewer of them should. I thought at least parts of it might be useful if taken fwiw.

The attached patch to t/oo/vtableoverride.t should provide some testing for the desired behavior.

Cheers,
Ron

The fwiw parrot patch:
Index: lib/Parrot/Pmc2c/PMC.pm
===================================================================
--- lib/Parrot/Pmc2c/PMC.pm	(revision 36383)
+++ lib/Parrot/Pmc2c/PMC.pm	(working copy)
@@ -328,14 +328,27 @@
return $self->vtable->attrs($methodname)->{write};
}

+my $multi_cmp = qr/cmp(?:_num|_string|_pmc)?/;
+my $multi_logical = qr/logical_(?:or|and|xor)/;
+my $multi_bitwise = qr/bitwise_(?:or|and|xor|shl|shr|lsr)/;
+my $multi_bitwise_str = qr/bitwise_(?:or|and|xor)/;
+my $multi_arithmetic = qr/add|subtract|multiply|divide|floor_divide|modulus|pow/;
+
+my $multi_bitwise_style = qr/(?:$multi_bitwise|repeat)(?:_int)?/o;
+my $multi_bitwise_str_style = qr/(?:$multi_bitwise|concat)(?:_str)?/o;
+my $multi_arithmetic_style = qr/$multi_arithmetic(?:_int|_float)?/o;
+
+my $multi_bit_or_arith_style = qr/
+ (?:i_)?
+ (?:$multi_bitwise_style|$multi_bitwise_str_style|$multi_arithmetic_style)
+/xo;
+
sub vtable_method_does_multi {
my ( $self, $methodname ) = @_;

return 1 if ($methodname =~ m/^
- (?:i_)?
- (?:add|subtract|multiply|divide|floor_divide|modulus)
- (?:_int|_float)?
- $/x);
+ (?:$multi_cmp|$multi_logical|$multi_bit_or_arith_style)
+ $/xo);
}

sub super_method {