@@ -109,6 +109,24 @@ recursive, but it's recursive on basic blocks, not on tree nodes.
109
109
#define CALL_RPEEP (o ) PL_rpeepp(aTHX_ o)
110
110
#define CALL_OPFREEHOOK (o ) if (PL_opfreehook) PL_opfreehook(aTHX_ o)
111
111
112
+ /* remove any leading "empty" ops from the op_next chain whose first
113
+ * node's address is stored in op_p. Store the updated address of the
114
+ * first node in op_p.
115
+ */
116
+
117
+ STATIC void
118
+ S_prune_chain_head (pTHX_ OP * * op_p )
119
+ {
120
+ while (* op_p
121
+ && ( (* op_p )-> op_type == OP_NULL
122
+ || (* op_p )-> op_type == OP_SCOPE
123
+ || (* op_p )-> op_type == OP_SCALAR
124
+ || (* op_p )-> op_type == OP_LINESEQ )
125
+ )
126
+ * op_p = (* op_p )-> op_next ;
127
+ }
128
+
129
+
112
130
/* See the explanatory comments above struct opslab in op.h. */
113
131
114
132
#ifdef PERL_DEBUG_READONLY_OPS
@@ -3297,6 +3315,7 @@ Perl_newPROG(pTHX_ OP *o)
3297
3315
ENTER ;
3298
3316
CALL_PEEP (PL_eval_start );
3299
3317
finalize_optree (PL_eval_root );
3318
+ S_prune_chain_head (aTHX_ & PL_eval_start );
3300
3319
LEAVE ;
3301
3320
PL_savestack_ix = i ;
3302
3321
}
@@ -3341,6 +3360,7 @@ Perl_newPROG(pTHX_ OP *o)
3341
3360
PL_main_root -> op_next = 0 ;
3342
3361
CALL_PEEP (PL_main_start );
3343
3362
finalize_optree (PL_main_root );
3363
+ S_prune_chain_head (aTHX_ & PL_main_start );
3344
3364
cv_forget_slab (PL_compcv );
3345
3365
PL_compcv = 0 ;
3346
3366
@@ -3647,9 +3667,11 @@ S_gen_constant_list(pTHX_ OP *o)
3647
3667
if (PL_parser && PL_parser -> error_count )
3648
3668
return o ; /* Don't attempt to run with errors */
3649
3669
3650
- PL_op = curop = LINKLIST (o );
3670
+ curop = LINKLIST (o );
3651
3671
o -> op_next = 0 ;
3652
3672
CALL_PEEP (curop );
3673
+ S_prune_chain_head (aTHX_ & curop );
3674
+ PL_op = curop ;
3653
3675
Perl_pp_pushmark (aTHX );
3654
3676
CALLRUNOPS (aTHX );
3655
3677
PL_op = curop ;
@@ -4876,6 +4898,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor)
4876
4898
/* have to peep the DOs individually as we've removed it from
4877
4899
* the op_next chain */
4878
4900
CALL_PEEP (o );
4901
+ S_prune_chain_head (aTHX_ & (o -> op_next ));
4879
4902
if (is_compiletime )
4880
4903
/* runtime finalizes as part of finalizing whole tree */
4881
4904
finalize_optree (o );
@@ -7599,6 +7622,7 @@ Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
7599
7622
CvROOT (cv )-> op_next = 0 ;
7600
7623
CALL_PEEP (CvSTART (cv ));
7601
7624
finalize_optree (CvROOT (cv ));
7625
+ S_prune_chain_head (aTHX_ & CvSTART (cv ));
7602
7626
7603
7627
/* now that optimizer has done its work, adjust pad values */
7604
7628
@@ -7954,6 +7978,7 @@ Perl_newATTRSUB_x(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs,
7954
7978
CvROOT (cv )-> op_next = 0 ;
7955
7979
CALL_PEEP (CvSTART (cv ));
7956
7980
finalize_optree (CvROOT (cv ));
7981
+ S_prune_chain_head (aTHX_ & CvSTART (cv ));
7957
7982
7958
7983
/* now that optimizer has done its work, adjust pad values */
7959
7984
@@ -8351,6 +8376,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
8351
8376
CvROOT (cv )-> op_next = 0 ;
8352
8377
CALL_PEEP (CvSTART (cv ));
8353
8378
finalize_optree (CvROOT (cv ));
8379
+ S_prune_chain_head (aTHX_ & CvSTART (cv ));
8354
8380
cv_forget_slab (cv );
8355
8381
8356
8382
finish :
@@ -9962,9 +9988,12 @@ Perl_ck_sort(pTHX_ OP *o)
9962
9988
if (o -> op_flags & OPf_STACKED )
9963
9989
simplify_sort (o );
9964
9990
firstkid = cLISTOPo -> op_first -> op_sibling ; /* get past pushmark */
9991
+
9965
9992
if ((stacked = o -> op_flags & OPf_STACKED )) { /* may have been cleared */
9966
9993
OP * kid = cUNOPx (firstkid )-> op_first ; /* get past null */
9967
9994
9995
+ /* if the first arg is a code block, process it and mark sort as
9996
+ * OPf_SPECIAL */
9968
9997
if (kid -> op_type == OP_SCOPE || kid -> op_type == OP_LEAVE ) {
9969
9998
LINKLIST (kid );
9970
9999
if (kid -> op_type == OP_LEAVE )
@@ -9991,6 +10020,16 @@ Perl_ck_sort(pTHX_ OP *o)
9991
10020
return o ;
9992
10021
}
9993
10022
10023
+ /* for sort { X } ..., where X is one of
10024
+ * $a <=> $b, $b <= $a, $a cmp $b, $b cmp $a
10025
+ * elide the second child of the sort (the one containing X),
10026
+ * and set these flags as appropriate
10027
+ OPpSORT_NUMERIC;
10028
+ OPpSORT_INTEGER;
10029
+ OPpSORT_DESCEND;
10030
+ * Also, check and warn on lexical $a, $b.
10031
+ */
10032
+
9994
10033
STATIC void
9995
10034
S_simplify_sort (pTHX_ OP * o )
9996
10035
{
@@ -11136,21 +11175,28 @@ S_inplace_aassign(pTHX_ OP *o) {
11136
11175
op_null (oleft );
11137
11176
}
11138
11177
11178
+
11179
+
11180
+ /* mechanism for deferring recursion in rpeep() */
11181
+
11139
11182
#define MAX_DEFERRED 4
11140
11183
11141
11184
#define DEFER (o ) \
11142
11185
STMT_START { \
11143
11186
if (defer_ix == (MAX_DEFERRED-1)) { \
11144
- CALL_RPEEP(defer_queue[defer_base]); \
11187
+ OP **defer = defer_queue[defer_base]; \
11188
+ CALL_RPEEP(*defer); \
11189
+ S_prune_chain_head(aTHX_ defer); \
11145
11190
defer_base = (defer_base + 1) % MAX_DEFERRED; \
11146
11191
defer_ix--; \
11147
11192
} \
11148
- defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = o ; \
11193
+ defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = &(o) ; \
11149
11194
} STMT_END
11150
11195
11151
11196
#define IS_AND_OP (o ) (o->op_type == OP_AND)
11152
11197
#define IS_OR_OP (o ) (o->op_type == OP_OR)
11153
11198
11199
+
11154
11200
STATIC void
11155
11201
S_null_listop_in_list_context (pTHX_ OP * o )
11156
11202
{
@@ -11181,7 +11227,7 @@ Perl_rpeep(pTHX_ OP *o)
11181
11227
dVAR ;
11182
11228
OP * oldop = NULL ;
11183
11229
OP * oldoldop = NULL ;
11184
- OP * defer_queue [MAX_DEFERRED ]; /* small queue of deferred branches */
11230
+ OP * * defer_queue [MAX_DEFERRED ]; /* small queue of deferred branches */
11185
11231
int defer_base = 0 ;
11186
11232
int defer_ix = -1 ;
11187
11233
@@ -11194,8 +11240,12 @@ Perl_rpeep(pTHX_ OP *o)
11194
11240
if (o && o -> op_opt )
11195
11241
o = NULL ;
11196
11242
if (!o ) {
11197
- while (defer_ix >= 0 )
11198
- CALL_RPEEP (defer_queue [(defer_base + defer_ix -- ) % MAX_DEFERRED ]);
11243
+ while (defer_ix >= 0 ) {
11244
+ OP * * defer =
11245
+ defer_queue [(defer_base + defer_ix -- ) % MAX_DEFERRED ];
11246
+ CALL_RPEEP (* defer );
11247
+ S_prune_chain_head (aTHX_ defer );
11248
+ }
11199
11249
break ;
11200
11250
}
11201
11251
@@ -11440,7 +11490,7 @@ Perl_rpeep(pTHX_ OP *o)
11440
11490
case OP_LINESEQ :
11441
11491
case OP_SCOPE :
11442
11492
nothin :
11443
- if (oldop && o -> op_next ) {
11493
+ if (oldop ) {
11444
11494
oldop -> op_next = o -> op_next ;
11445
11495
o -> op_opt = 0 ;
11446
11496
continue ;
@@ -11871,6 +11921,11 @@ Perl_rpeep(pTHX_ OP *o)
11871
11921
DEFER (cLOOP -> op_lastop );
11872
11922
break ;
11873
11923
11924
+ case OP_ENTERTRY :
11925
+ assert (cLOGOPo -> op_other -> op_type == OP_LEAVETRY );
11926
+ DEFER (cLOGOPo -> op_other );
11927
+ break ;
11928
+
11874
11929
case OP_SUBST :
11875
11930
assert (!(cPMOP -> op_pmflags & PMf_ONCE ));
11876
11931
while (cPMOP -> op_pmstashstartu .op_pmreplstart &&
@@ -11883,12 +11938,28 @@ Perl_rpeep(pTHX_ OP *o)
11883
11938
case OP_SORT : {
11884
11939
OP * oright ;
11885
11940
11886
- if (o -> op_flags & OPf_STACKED ) {
11887
- OP * const kid =
11888
- cUNOPx (cLISTOP -> op_first -> op_sibling )-> op_first ;
11889
- if (kid -> op_type == OP_SCOPE
11890
- || (kid -> op_type == OP_NULL && kid -> op_targ == OP_LEAVE ))
11891
- DEFER (kLISTOP -> op_first );
11941
+ if (o -> op_flags & OPf_SPECIAL ) {
11942
+ /* first arg is a code block */
11943
+ OP * const nullop = cLISTOP -> op_first -> op_sibling ;
11944
+ OP * kid = cUNOPx (nullop )-> op_first ;
11945
+
11946
+ assert (nullop -> op_type == OP_NULL );
11947
+ assert (kid -> op_type == OP_SCOPE
11948
+ || (kid -> op_type == OP_NULL && kid -> op_targ == OP_LEAVE ));
11949
+ /* since OP_SORT doesn't have a handy op_other-style
11950
+ * field that can point directly to the start of the code
11951
+ * block, store it in the otherwise-unused op_next field
11952
+ * of the top-level OP_NULL. This will be quicker at
11953
+ * run-time, and it will also allow us to remove leading
11954
+ * OP_NULLs by just messing with op_nexts without
11955
+ * altering the basic op_first/op_sibling layout. */
11956
+ kid = kLISTOP -> op_first ;
11957
+ assert (
11958
+ (kid -> op_type == OP_NULL && kid -> op_targ == OP_NEXTSTATE )
11959
+ || kid -> op_type == OP_STUB
11960
+ || kid -> op_type == OP_ENTER );
11961
+ nullop -> op_next = kLISTOP -> op_next ;
11962
+ DEFER (nullop -> op_next );
11892
11963
}
11893
11964
11894
11965
/* check that RHS of sort is a single plain array */
@@ -12040,6 +12111,23 @@ Perl_rpeep(pTHX_ OP *o)
12040
12111
if (OP_GIMME (o ,0 ) == G_VOID ) {
12041
12112
OP * right = cBINOP -> op_first ;
12042
12113
if (right ) {
12114
+ /* sassign
12115
+ * RIGHT
12116
+ * substr
12117
+ * pushmark
12118
+ * arg1
12119
+ * arg2
12120
+ * ...
12121
+ * becomes
12122
+ *
12123
+ * ex-sassign
12124
+ * substr
12125
+ * pushmark
12126
+ * RIGHT
12127
+ * arg1
12128
+ * arg2
12129
+ * ...
12130
+ */
12043
12131
OP * left = right -> op_sibling ;
12044
12132
if (left -> op_type == OP_SUBSTR
12045
12133
&& (left -> op_private & 7 ) < 4 ) {
@@ -12065,8 +12153,16 @@ Perl_rpeep(pTHX_ OP *o)
12065
12153
}
12066
12154
12067
12155
}
12068
- oldoldop = oldop ;
12069
- oldop = o ;
12156
+ /* did we just null the current op? If so, re-process it to handle
12157
+ * eliding "empty" ops from the chain */
12158
+ if (o -> op_type == OP_NULL && oldop && oldop -> op_next == o ) {
12159
+ o -> op_opt = 0 ;
12160
+ o = oldop ;
12161
+ }
12162
+ else {
12163
+ oldoldop = oldop ;
12164
+ oldop = o ;
12165
+ }
12070
12166
}
12071
12167
LEAVE ;
12072
12168
}
0 commit comments