diff options
author | Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> | 2021-12-03 22:42:26 +0000 |
---|---|---|
committer | Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> | 2021-12-08 00:05:15 +0000 |
commit | 1dd1944b9e9757d121aa50a03029666ee4a07440 (patch) | |
tree | 1e9081530da05cb117aca1104907409d137b80ea /pp.c | |
parent | d2817bd771b5f4a948f1a5395803b7d795453c07 (diff) | |
download | perl-1dd1944b9e9757d121aa50a03029666ee4a07440.tar.gz |
Give blessed() the same TRUEBOOL optimisation that ref() has in boolean contexts
Diffstat (limited to 'pp.c')
-rw-r--r-- | pp.c | 32 |
1 files changed, 24 insertions, 8 deletions
@@ -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; } |