Anno, that seems to me to be a reasonable guess .... but I'm looking at a '+=' overload XSub that neither increments the refcount nor (afaict) returns anything ... and I'm wondering "how the hell does that work ?". It's from the GMP module - which is not to be found on CPAN. (It ships with the gmp source - in the demos/perl folder.) I don't know if it's going to help the discussion, but here's that XSub:
void
overload_addeq (x, y, o)
mpz_assume x
mpz_coerce y
order_noswap o
ALIAS:
GMP::Mpz::overload_subeq = 1
GMP::Mpz::overload_muleq = 2
GMP::Mpz::overload_diveq = 3
GMP::Mpz::overload_remeq = 4
GMP::Mpz::overload_andeq = 5
GMP::Mpz::overload_ioreq = 6
GMP::Mpz::overload_xoreq = 7
PREINIT:
static_functable const struct {
void (*op) (mpz_ptr, mpz_srcptr, mpz_srcptr);
} table[] = {
{ mpz_add }, /* 0 */
{ mpz_sub }, /* 1 */
{ mpz_mul }, /* 2 */
{ mpz_tdiv_q }, /* 3 */
{ mpz_tdiv_r }, /* 4 */
{ mpz_and }, /* 5 */
{ mpz_ior }, /* 6 */
{ mpz_xor }, /* 7 */
};
PPCODE:
assert_table (ix);
(*table[ix].op) (x->m, x->m, y);
XPUSHs (ST(0));
First up - I don't really understand this XSub at all. I gather it's also handling -=, *=, /=, %=, &=, |= and ^= via some sort of lookup. The XPUSHs() also puzzles me. What does that achieve ?
Anyway, it seems to me that this particular module has overloaded '+=' and friends without any need to return anything, and without any need to increase the refcount. (I've searched the entire XS file and there's not a single SvREFCNT_inc() to be found.)
Cheers, Rob PS: I haven't actually built that GMP module for a while. I assume it works fine with perl-5.8.8, but that's something that's unverified. Last time I built this module, I also benchmarked the overloading and found it to be very efficient - not surprising, given that the author is a smart and talented programmer. | [reply] [d/l] |
I'm looking at a '+=' overload XSub that neither increments the refcount nor (afaict) returns anything
Ah, but it does return a value.
The XPUSHs() also puzzles me. What does that achieve?
It pushes a value on the return stack. See perlapi.
Anno
| [reply] |
It pushes a value on the return stack
Yeaaah ... it pushes a value onto the stack ... but does that mean it returns a value ? (It's also pushing onto the stack something that's already on the stack, isn't it ? .... which doesn't do much to help the intellectually impaired :-) I thought there would have to be an XSRETURN() before anything was returned ... or a RETVAL ....
We see (in INLINE.h):
#define Inline_Stack_Push(x) XPUSHs(x)
Also:
#define Inline_Stack_Return(x) XSRETURN(x)
In Inline::C, we have to Inline_Stack_Return(x) if we wish to return anything from a 'void' function. Since Inline::C and XS are essentially one and the same thing, I expected that we would have to explicitly XSRETURN(x) from an XSub (if we wanted to return anything).
Let's concentrate (for the moment, anyway) on how to rewrite my 'overload_add_eq' in such a way that the refcount increase is not needed. I tried:
void overload_add_eq(SV * obj, SV * addon, SV * third) {
dXSARGS;
Card* c = (Card *)SvIV(SvRV(obj));
c->value += SvIV(addon);
XPUSHs(obj);
}
but still got the same failure with the '+=" operator. (Again, when explicitly calling overload_add_eq($obj, $addon, 0); there's no problem.)
Shit!! ... but hang on ... I also tried:
void overload_add_eq(SV * obj, SV * addon, SV * third) {
dXSARGS;
Card* c = (Card *)SvIV(SvRV(obj));
c->value += SvIV(addon);
XPUSHs(obj);
XSRETURN(1);
}
and that worked fine with the '+=' overloading ... and no increase to the refcount !!! It also worked fine when I explicitly called overload_add_eq($obj, $addon, 0);(This might even constitute "progress".)
So ... I guess one remaining question is "how come I have to call both dXSARGS and XSRETURN (whereas Robert Hyde's GMP code didn't have to do that) ?"
Another question is "Has anything been achieved by rewriting 'overload_add_eq' ?". I guess the answer to that question will be "no" ... the proof will be in the benchmarking.
Thanks for the feedback, Anno. Please don't take my questions/objections/refutations as anything other than the ramblings of one who is both ill-informed and a little dim :-)
Cheers, Rob
| [reply] [d/l] [select] |
And if you don't have the time to dig through perlapi, perl tries not to rely on the C stack for manipulation of variables, returning by pushing onto the return stack is the prefered method, assuming you've first set the stack up correctly. While I haven't played with overloading and C I believe the principle is the same.
| [reply] |