From b6f05621f8846ec3e3b279fc32f6bbe9bce20cfb Mon Sep 17 00:00:00 2001 From: David Mitchell Date: Mon, 17 Oct 2011 12:46:51 +0100 Subject: [PATCH] simplify op_dump() / -Dx sequencing Currently, whenever we dump an op tree, we first call sequence(), which walks the tree, creating address => sequence# mappings in PL_op_sequence. Then when individual ops or op-next fields are displayed, the sequence is looked up. Instead, do away with the initial walk, and just map addresses on request. This simplifies the code. As a deliberate side-effect, it no longer assigns a seq# of zero to null ops. This makes it easer to work out what's going on when you call op_dump() during a debugging session with partially constructed op-trees. It also removes the ambiguity in "====> 0" as to whether op_next is NULL or just points to an op_null. --- dump.c | 123 +++++++++----------------------------------------------------- embed.fnc | 2 - embed.h | 2 - proto.h | 2 - 4 files changed, 17 insertions(+), 112 deletions(-) diff --git a/dump.c b/dump.c index ca4e03d..3859da5 100644 --- a/dump.c +++ b/dump.c @@ -87,7 +87,6 @@ S_append_flags(pTHX_ SV *sv, U32 flags, const struct flag_to_name *start, S_append_flags(aTHX_ (sv), (f), (flags), C_ARRAY_END(flags)) -#define Sequence PL_op_sequence void Perl_dump_indent(pTHX_ I32 level, PerlIO *file, const char* pat, ...) @@ -675,104 +674,10 @@ Perl_pmop_dump(pTHX_ PMOP *pm) do_pmop_dump(0, Perl_debug_log, pm); } -/* An op sequencer. We visit the ops in the order they're to execute. */ - -STATIC void -S_sequence(pTHX_ register const OP *o) -{ - dVAR; - const OP *oldop = NULL; - - if (!o) - return; - -#ifdef PERL_MAD - if (o->op_next == 0) - return; -#endif - - if (!Sequence) - Sequence = newHV(); - - for (; o; o = o->op_next) { - STRLEN len; - SV * const op = newSVuv(PTR2UV(o)); - const char * const key = SvPV_const(op, len); - - if (hv_exists(Sequence, key, len)) - break; - - switch (o->op_type) { - case OP_STUB: - if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) { - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - break; - } - goto nothin; - case OP_NULL: -#ifdef PERL_MAD - if (o == o->op_next) - return; -#endif - if (oldop && o->op_next) - continue; - break; - case OP_SCALAR: - case OP_LINESEQ: - case OP_SCOPE: - nothin: - if (oldop && o->op_next) - continue; - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - break; - - case OP_MAPWHILE: - case OP_GREPWHILE: - case OP_AND: - case OP_OR: - case OP_DOR: - case OP_ANDASSIGN: - case OP_ORASSIGN: - case OP_DORASSIGN: - case OP_COND_EXPR: - case OP_RANGE: - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - sequence_tail(cLOGOPo->op_other); - break; - - case OP_ENTERLOOP: - case OP_ENTERITER: - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - sequence_tail(cLOOPo->op_redoop); - sequence_tail(cLOOPo->op_nextop); - sequence_tail(cLOOPo->op_lastop); - break; - - case OP_SUBST: - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - sequence_tail(cPMOPo->op_pmstashstartu.op_pmreplstart); - break; - - case OP_QR: - case OP_MATCH: - case OP_HELEM: - break; - - default: - (void)hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0); - break; - } - oldop = o; - } -} - -static void -S_sequence_tail(pTHX_ const OP *o) -{ - while (o && (o->op_type == OP_NULL)) - o = o->op_next; - sequence(o); -} +/* Return a unique integer to represent the address of op o. + * If it already exists in PL_op_sequence, just return it; + * otherwise add it. + * *** Note that this isn't thread-safe */ STATIC UV S_sequence_num(pTHX_ const OP *o) @@ -782,11 +687,18 @@ S_sequence_num(pTHX_ const OP *o) **seq; const char *key; STRLEN len; - if (!o) return 0; + if (!o) + return 0; op = newSVuv(PTR2UV(o)); + sv_2mortal(op); key = SvPV_const(op, len); - seq = hv_fetch(Sequence, key, len, 0); - return seq ? SvUV(*seq): 0; + if (!PL_op_sequence) + PL_op_sequence = newHV(); + seq = hv_fetch(PL_op_sequence, key, len, 0); + if (seq) + return SvUV(*seq); + (void)hv_store(PL_op_sequence, key, len, newSVuv(++PL_op_seq), 0); + return PL_op_seq; } const struct flag_to_name op_flags_names[] = { @@ -922,19 +834,19 @@ Perl_do_op_dump(pTHX_ I32 level, PerlIO *file, const OP *o) PERL_ARGS_ASSERT_DO_OP_DUMP; - sequence(o); Perl_dump_indent(aTHX_ level, file, "{\n"); level++; seq = sequence_num(o); if (seq) PerlIO_printf(file, "%-4"UVuf, seq); else - PerlIO_printf(file, " "); + PerlIO_printf(file, "????"); PerlIO_printf(file, "%*sTYPE = %s ===> ", (int)(PL_dumpindent*level-4), "", OP_NAME(o)); if (o->op_next) - PerlIO_printf(file, seq ? "%"UVuf"\n" : "(%"UVuf")\n", + PerlIO_printf(file, + o->op_type == OP_NULL ? "(%"UVuf")\n" : "%"UVuf"\n", sequence_num(o->op_next)); else PerlIO_printf(file, "DONE\n"); @@ -2840,7 +2752,6 @@ Perl_do_op_xmldump(pTHX_ I32 level, PerlIO *file, const OP *o) if (!o) return; - sequence(o); seq = sequence_num(o); Perl_xmldump_indent(aTHX_ level, file, " ", diff --git a/embed.fnc b/embed.fnc index b7d4609..43ad88b 100644 --- a/embed.fnc +++ b/embed.fnc @@ -1949,8 +1949,6 @@ Es |void |debug_start_match|NN const REGEXP *prog|const bool do_utf8\ #if defined(PERL_IN_DUMP_C) s |CV* |deb_curcv |const I32 ix s |void |debprof |NN const OP *o -s |void |sequence |NULLOK const OP *o -s |void |sequence_tail |NULLOK const OP *o s |UV |sequence_num |NULLOK const OP *o s |SV* |pm_description |NN const PMOP *pm #endif diff --git a/embed.h b/embed.h index 4c7cbe5..395c791 100644 --- a/embed.h +++ b/embed.h @@ -1307,9 +1307,7 @@ #define deb_curcv(a) S_deb_curcv(aTHX_ a) #define debprof(a) S_debprof(aTHX_ a) #define pm_description(a) S_pm_description(aTHX_ a) -#define sequence(a) S_sequence(aTHX_ a) #define sequence_num(a) S_sequence_num(aTHX_ a) -#define sequence_tail(a) S_sequence_tail(aTHX_ a) # endif # if defined(PERL_IN_GV_C) #define gv_get_super_pkg(a,b,c) S_gv_get_super_pkg(aTHX_ a,b,c) diff --git a/proto.h b/proto.h index 4da34b9..0eb5e7c 100644 --- a/proto.h +++ b/proto.h @@ -5415,9 +5415,7 @@ STATIC SV* S_pm_description(pTHX_ const PMOP *pm) #define PERL_ARGS_ASSERT_PM_DESCRIPTION \ assert(pm) -STATIC void S_sequence(pTHX_ const OP *o); STATIC UV S_sequence_num(pTHX_ const OP *o); -STATIC void S_sequence_tail(pTHX_ const OP *o); # if defined(PERL_MAD) STATIC void S_xmldump_attr(pTHX_ I32 level, PerlIO *file, const char* pat, ...) __attribute__format__(__printf__,pTHX_3,pTHX_4) -- 2.7.4