summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>1999-01-13 17:24:59 +0000
committerJarkko Hietaniemi <jhi@iki.fi>1999-01-13 17:24:59 +0000
commit9c007264caa0e1aed57010dc2950fe35f9d8347e (patch)
tree16b435433f6ef5875c593a2549690a2ec78ea3e9 /op.c
parent61ae2fbf8676dafa05a9a9a710fde421f30a2071 (diff)
downloadperl-9c007264caa0e1aed57010dc2950fe35f9d8347e.tar.gz
From: Hans Mulder <hansm@icgroup.nl>
Optimize common sort routines. Thread started by the message From: Hans Mulder <hansm@icgroup.nl> Sender: owner-perl5-porters@perl.org To: perl5-porters@perl.org Subject: [Patch for 5.00554] From the Todo list: Optimize sort by { $a <=> $b Message-Id: <9901092156.AA03831@icgned.icgroup.nl> and the patch from the message From: Hans Mulder <hans@icgroup.nl> To: jhi@iki.fi Cc: perl5-porters@perl.org Subject: Re: [Patch for 5.00554] From the Todo list: Optimize sort by { $a <=> $b } Date: Wed, 13 Jan 1999 17:39:35 +0100 Message-Id: <9901131639.AA17419@icgned.icgroup.nl> p4raw-id: //depot/cfgperl@2595
Diffstat (limited to 'op.c')
-rw-r--r--op.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/op.c b/op.c
index 58f26e160c..901995aa39 100644
--- a/op.c
+++ b/op.c
@@ -51,6 +51,7 @@ static PADOFFSET pad_findlex _((char* name, PADOFFSET newoff, U32 seq,
CV* startcv, I32 cx_ix, I32 saweval));
static OP *newDEFSVOP _((void));
static OP *new_logop _((I32 type, I32 flags, OP **firstp, OP **otherp));
+static void simplify_sort(OP *o);
#endif
STATIC char*
@@ -5048,7 +5049,9 @@ ck_sort(OP *o)
o->op_private |= OPpLOCALE;
#endif
- if (o->op_flags & OPf_STACKED) {
+ if (o->op_flags & OPf_STACKED)
+ simplify_sort(o);
+ if (o->op_flags & OPf_STACKED) { /* may have been cleared */
OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
OP *k;
kid = kUNOP->op_first; /* get past rv2gv */
@@ -5089,6 +5092,64 @@ ck_sort(OP *o)
return o;
}
+static void
+simplify_sort(OP *o)
+{
+ register OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */
+ OP *k;
+ int reversed;
+ if (!(o->op_flags & OPf_STACKED))
+ return;
+ kid = kUNOP->op_first; /* get past rv2gv */
+ if (kid->op_type != OP_SCOPE)
+ return;
+ kid = kLISTOP->op_last; /* get past scope */
+ switch(kid->op_type) {
+ case OP_NCMP:
+ case OP_I_NCMP:
+ case OP_SCMP:
+ break;
+ default:
+ return;
+ }
+ k = kid; /* remember this node*/
+ if (kBINOP->op_first->op_type != OP_RV2SV)
+ return;
+ kid = kBINOP->op_first; /* get past cmp */
+ if (kUNOP->op_first->op_type != OP_GV)
+ return;
+ kid = kUNOP->op_first; /* get past rv2sv */
+ if (GvSTASH(kGVOP->op_gv) != PL_curstash)
+ return;
+ if (strEQ(GvNAME(kGVOP->op_gv), "a"))
+ reversed = 0;
+ else if(strEQ(GvNAME(kGVOP->op_gv), "b"))
+ reversed = 1;
+ else
+ return;
+ kid = k; /* back to cmp */
+ if (kBINOP->op_last->op_type != OP_RV2SV)
+ return;
+ kid = kBINOP->op_last; /* down to 2nd arg */
+ if (kUNOP->op_first->op_type != OP_GV)
+ return;
+ kid = kUNOP->op_first; /* get past rv2sv */
+ if (GvSTASH(kGVOP->op_gv) != PL_curstash
+ || ( reversed
+ ? strNE(GvNAME(kGVOP->op_gv), "a")
+ : strNE(GvNAME(kGVOP->op_gv), "b")))
+ return;
+ o->op_flags &= ~(OPf_STACKED | OPf_SPECIAL);
+ if (reversed)
+ o->op_private |= OPpSORT_REVERSE;
+ if (k->op_type == OP_NCMP)
+ o->op_private |= OPpSORT_NUMERIC;
+ if (k->op_type == OP_I_NCMP)
+ o->op_private |= OPpSORT_NUMERIC | OPpSORT_INTEGER;
+ op_free(cLISTOPo->op_first->op_sibling); /* delete comparison block */
+ cLISTOPo->op_first->op_sibling = cLISTOPo->op_last;
+ cLISTOPo->op_children = 1;
+}
OP *
ck_split(OP *o)