- up = myorigmark + 1;
- while (MARK < SP) { /* This may or may not shift down one here. */
- /*SUPPRESS 560*/
- if ((*up = *++MARK)) { /* Weed out nulls. */
- SvTEMP_off(*up);
- if (!PL_sortcop && !SvPOK(*up)) {
- STRLEN n_a;
- if (SvAMAGIC(*up))
- overloading = 1;
- else
- (void)sv_2pv(*up, &n_a);
+ /* optimiser converts "@a = sort @a" to "sort \@a";
+ * in case of tied @a, pessimise: push (@a) onto stack, then assign
+ * result back to @a at the end of this function */
+ if (priv & OPpSORT_INPLACE) {
+ assert( MARK+1 == SP && *SP && SvTYPE(*SP) == SVt_PVAV);
+ (void)POPMARK; /* remove mark associated with ex-OP_AASSIGN */
+ av = (AV*)(*SP);
+ max = AvFILL(av) + 1;
+ if (SvMAGICAL(av)) {
+ MEXTEND(SP, max);
+ p2 = SP;
+ for (i=0; i < max; i++) {
+ SV **svp = av_fetch(av, i, FALSE);
+ *SP++ = (svp) ? *svp : NULL;
+ }
+ }
+ else {
+ if (SvREADONLY(av))
+ Perl_croak(aTHX_ PL_no_modify);
+ else
+ SvREADONLY_on(av);
+ p1 = p2 = AvARRAY(av);
+ sorting_av = 1;
+ }
+ }
+ else {
+ p2 = MARK+1;
+ max = SP - MARK;
+ }
+
+ /* shuffle stack down, removing optional initial cv (p1!=p2), plus
+ * any nulls; also stringify or converting to integer or number as
+ * required any args */
+ for (i=max; i > 0 ; i--) {
+ if ((*p1 = *p2++)) { /* Weed out nulls. */
+ SvTEMP_off(*p1);
+ if (!PL_sortcop) {
+ if (priv & OPpSORT_NUMERIC) {
+ if (priv & OPpSORT_INTEGER) {
+ if (!SvIOK(*p1)) {
+ if (SvAMAGIC(*p1))
+ overloading = 1;
+ else
+ (void)sv_2iv(*p1);
+ }
+ }
+ else {
+ if (!SvNSIOK(*p1)) {
+ if (SvAMAGIC(*p1))
+ overloading = 1;
+ else
+ (void)sv_2nv(*p1);
+ }
+ if (all_SIVs && !SvSIOK(*p1))
+ all_SIVs = 0;
+ }
+ }
+ else {
+ if (!SvPOK(*p1)) {
+ if (SvAMAGIC(*p1))
+ overloading = 1;
+ else
+ (void)sv_2pv_flags(*p1, 0,
+ SV_GMAGIC|SV_CONST_RETURN);
+ }
+ }