summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2021-12-03 22:42:26 +0000
committerPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2021-12-08 00:05:15 +0000
commit1dd1944b9e9757d121aa50a03029666ee4a07440 (patch)
tree1e9081530da05cb117aca1104907409d137b80ea /pp.c
parentd2817bd771b5f4a948f1a5395803b7d795453c07 (diff)
downloadperl-1dd1944b9e9757d121aa50a03029666ee4a07440.tar.gz
Give blessed() the same TRUEBOOL optimisation that ref() has in boolean contexts
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/pp.c b/pp.c
index 79b73e45a1..8376168354 100644
--- a/pp.c
+++ b/pp.c
@@ -7256,20 +7256,36 @@ PP(pp_unweaken)
PP(pp_blessed)
{
dSP;
- dTARGET;
- SV *arg = POPs;
+ SV *arg = TOPs;
SV *rv;
SvGETMAGIC(arg);
- if(SvROK(arg) && SvOBJECT((rv = SvRV(arg)))) {
- sv_ref(TARG, rv, TRUE);
- SvSETMAGIC(TARG);
+ if(!SvROK(arg) || !SvOBJECT((rv = SvRV(arg)))) {
+ SETs(&PL_sv_undef);
+ RETURN;
+ }
+
+ if((PL_op->op_private & OPpTRUEBOOL) ||
+ ((PL_op->op_private & OPpMAYBE_TRUEBOOL) && (block_gimme() == G_VOID))) {
+ /* We only care about the boolean truth, not the specific string value.
+ * We just have to check for the annoying cornercase of the package
+ * named "0" */
+ HV *stash = SvSTASH(rv);
+ HEK *hek = HvNAME_HEK(stash);
+ if(!hek)
+ goto fallback;
+ I32 len = HEK_LEN(hek);
+ if(UNLIKELY(len == HEf_SVKEY || (len == 1 && HEK_KEY(hek)[0] == '0')))
+ goto fallback;
+
+ SETs(&PL_sv_yes);
+ }
+ else {
+fallback:
+ SETs(sv_ref(NULL, rv, TRUE));
}
- else
- sv_setsv(TARG, &PL_sv_undef);
- PUSHs(TARG);
RETURN;
}