summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2010-11-03 14:57:11 +0000
committerNicholas Clark <nick@ccl4.org>2010-11-03 15:04:34 +0000
commit25a9ffce153b0e67cfefd260754edeb097da5be7 (patch)
tree6d7e60d1842fa73c3f0fcec7cc9a2e2272baf085 /gv.c
parent7d255dc8b56bf0fe58c3f8a5aa84ba17aade145f (diff)
downloadperl-25a9ffce153b0e67cfefd260754edeb097da5be7.tar.gz
Add Perl_amagic_deref_call() to implement the bulk of tryAMAGICunDEREF_var().
This removes around 300 bytes of object code from each place it was previously inlined. It also provides a better interface - quite a lot of the core currently bodges things by creating a local variable C<SV **sp = &sv> to use the macro. Change the XS::APItest wrapper to amagic_deref_call().
Diffstat (limited to 'gv.c')
-rw-r--r--gv.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/gv.c b/gv.c
index 080db567be..32b5908c99 100644
--- a/gv.c
+++ b/gv.c
@@ -2010,6 +2010,25 @@ Perl_try_amagic_bin(pTHX_ int method, int flags) {
return FALSE;
}
+SV *
+Perl_amagic_deref_call(pTHX_ SV *ref, int method) {
+ SV *tmpsv = NULL;
+
+ PERL_ARGS_ASSERT_AMAGIC_DEREF_CALL;
+
+ while (SvAMAGIC(ref) &&
+ (tmpsv = amagic_call(ref, &PL_sv_undef, method,
+ AMGf_noright | AMGf_unary))) {
+ if (!SvROK(tmpsv))
+ Perl_croak(aTHX_ "Overloaded dereference did not return a reference");
+ if (tmpsv == ref || SvRV(tmpsv) == SvRV(ref)) {
+ /* Bail out if it returns us the same reference. */
+ return tmpsv;
+ }
+ ref = tmpsv;
+ }
+ return tmpsv ? tmpsv : ref;
+}
SV*
Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)