What does call_sv() return?

call_sv()の戻り値を正確に把握していないがために、Xslate で厄介なバグを引き起こしてしまった*1。具体的には、call_sv()でG_VOIDを指定すると常に1を返すと思い込んでいた。しかし、それは間違いだった。
検証:
https://github.com/gfx/p5-XS-CallSV

#!perl -w
use strict;
use Test::More;

use B qw(/^G_/);
use XS::SvCallTest;

sub empty_pp { }
sub return_empty_pp { return }
sub return2_pp { return(10, 20) }

sub fatal { die }

note 'G_VOID';
is call_sv(\&empty_pp, G_VOID),          0;
is call_sv(\&return_empty_pp, G_VOID),   0;
is call_sv(\&return2_pp, G_VOID),        0;

is call_sv(\&empty_xs, G_VOID),          0;
is call_sv(\&return2_xs, G_VOID),        2;

note 'G_SCALAR';
is call_sv(\&empty_pp, G_SCALAR),        1;
is call_sv(\&return_empty_pp, G_SCALAR), 1;
is call_sv(\&return2_pp, G_SCALAR),      1;

is call_sv(\&empty_xs, G_SCALAR),        1;
is call_sv(\&return2_xs, G_SCALAR),      1;

note 'G_VOID | G_EVAL';
is call_sv(\&fatal, G_VOID | G_EVAL),    1;

note 'G_SCALAR | G_EVAL';
is call_sv(\&fatal, G_SCALAR | G_EVAL),  1;

done_testing;

このテストはすべてパスする。
興味深いのはG_VOIDで、基本的には0を返すが、1つ以上の値を返すケースではPPサブルーチンとXSUBで結果が変わる。また、G_EVALを指定しているときにサブルーチンが例外を投げると、なぜか1を返す。
G_SCALARについては常に1を返すとみていいようだが、心配なら assert(retval == 1) を仕込んでおくといいかもしれない。

*1:1.0004で修正済み