Skip to content

Commit

Permalink
Introduce SvCANEXISTDELETE in pp.h, which simplify the logic in pp_he…
Browse files Browse the repository at this point in the history
…lem and pp_hslice
  • Loading branch information
vpit committed Dec 28, 2008
1 parent 3f0c569 commit d30e492
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 28 deletions.
25 changes: 11 additions & 14 deletions pp.c
Expand Up @@ -4143,31 +4143,28 @@ PP(pp_hslice)
register HV * const hv = MUTABLE_HV(POPs);
register const I32 lval = (PL_op->op_flags & OPf_MOD || LVRET);
const bool localizing = PL_op->op_private & OPpLVAL_INTRO;
bool other_magic = FALSE;
bool can_preserve = FALSE;

if (localizing) {
MAGIC *mg;
HV *stash;

other_magic = mg_find((const SV *)hv, PERL_MAGIC_env) ||
((mg = mg_find((const SV *)hv, PERL_MAGIC_tied))
/* Try to preserve the existenceness of a tied hash
* element by using EXISTS and DELETE if possible.
* Fallback to FETCH and STORE otherwise */
&& (stash = SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(hv), mg))))
&& gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
&& gv_fetchmethod_autoload(stash, "DELETE", TRUE));
if (SvCANEXISTDELETE(hv) || mg_find((const SV *)hv, PERL_MAGIC_env))
can_preserve = TRUE;
}

while (++MARK <= SP) {
SV * const keysv = *MARK;
SV **svp;
HE *he;
bool preeminent = FALSE;

if (localizing) {
preeminent = SvRMAGICAL(hv) && !other_magic ? 1 :
hv_exists_ent(hv, keysv, 0);
bool preeminent = TRUE;

if (localizing && can_preserve) {
/* If we can determine whether the element exist,
* try to preserve the existenceness of a tied hash
* element by using EXISTS and DELETE if possible.
* Fallback to FETCH and STORE otherwise. */
preeminent = hv_exists_ent(hv, keysv, 0);
}

he = hv_fetch_ent(hv, keysv, lval, 0);
Expand Down
9 changes: 9 additions & 0 deletions pp.h
Expand Up @@ -500,6 +500,15 @@ True if this op will be the return value of an lvalue subroutine
=cut */
#define LVRET ((PL_op->op_private & OPpMAYBE_LVSUB) && is_lvalue_sub())

#define SvCANEXISTDELETE(sv) \
(!SvRMAGICAL(sv) \
|| ((mg = mg_find((const SV *) sv, PERL_MAGIC_tied)) \
&& (stash = SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(sv), mg)))) \
&& gv_fetchmethod_autoload(stash, "EXISTS", TRUE) \
&& gv_fetchmethod_autoload(stash, "DELETE", TRUE) \
) \
)

/*
* Local variables:
* c-indentation-style: bsd
Expand Down
23 changes: 9 additions & 14 deletions pp_hot.c
Expand Up @@ -1783,28 +1783,23 @@ PP(pp_helem)
const U32 defer = PL_op->op_private & OPpLVAL_DEFER;
SV *sv;
const U32 hash = (SvIsCOW_shared_hash(keysv)) ? SvSHARED_HASH(keysv) : 0;
I32 preeminent = 0;
bool preeminent = TRUE;

if (SvTYPE(hv) != SVt_PVHV)
RETPUSHUNDEF;

if (PL_op->op_private & OPpLVAL_INTRO) {
MAGIC *mg;
HV *stash;
/* does the element we're localizing already exist? */
preeminent = /* can we determine whether it exists? */
( !SvRMAGICAL(hv)
|| mg_find((const SV *)hv, PERL_MAGIC_env)
|| ( (mg = mg_find((const SV *)hv, PERL_MAGIC_tied))
/* Try to preserve the existenceness of a tied hash
* element by using EXISTS and DELETE if possible.
* Fallback to FETCH and STORE otherwise */
&& (stash = SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(hv), mg))))
&& gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
&& gv_fetchmethod_autoload(stash, "DELETE", TRUE)
)
) ? hv_exists_ent(hv, keysv, 0) : 1;

/* If we can determine whether the element exist,
* Try to preserve the existenceness of a tied hash
* element by using EXISTS and DELETE if possible.
* Fallback to FETCH and STORE otherwise. */
if (SvCANEXISTDELETE(hv) || mg_find((const SV *)hv, PERL_MAGIC_env))
preeminent = hv_exists_ent(hv, keysv, 0);
}

he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
svp = he ? &HeVAL(he) : NULL;
if (lval) {
Expand Down

0 comments on commit d30e492

Please sign in to comment.