develooper Front page | perl.perl5.porters | Postings from November 2000

av.c patch (having slight problems)

Thread Next
From:
Jeff Pinyan
Date:
November 20, 2000 09:46
Subject:
av.c patch (having slight problems)
Message ID:
Pine.GSO.4.21.0011201227360.714-100000@crusoe.crusoe.net
Failed Test         Status Wstat Total Fail  Failed  List of Failed
------------------------------------------------------------------------
lib/b.t                             15    1   6.67%  13
lib/bigfloat.t           0   139   355   55  15.49%  301-355
lib/bigfltpm.t           0   139   362   55  15.19%  308-362
lib/ftmp-tempfile.       0   139    16    0   0.00%  ??
6 tests and 78 subtests skipped.
Failed 4/268 test scripts, 98.51% okay. 111/15631 subtests failed, 99.29%
okay.


That's from ./perl harness in the t/ directory.

The patch is intended to build up space before the beginning of an array
when unshift() is called.  This is so that multiple calls to
unshift() aren't so slow.  However, it appears to cause segfaults after "a
while" (where "a while" is some condition I've not been able to pinpoint
yet).

Here is a problem case:

  open 0;
  print <0>;
  my @a;
  for (1..15) { unshift @a, 1; print "$_: $#a (@a)\n"; }
  __END__
  1: 0 (1)
  2: 1 (1 1)
  3: 2 (1 1 1)
  4: 3 (1 1 1 1)
  5: 4 (1 1 1 1 1)
  6: 5 (1 1 1 1 1 1)
  Segmentation fault (core dumped)

This is using the 7734 snapshot.  Here is the information on the system
it's being tested on:

  jefpin@towers [12:43pm] ~/perl #521> ./miniperl -v

  This is perl, v5.7.0 built for i586-linux
  (with 1 registered patch, see perl -V for more detail)

-V isn't working (it says it can't find Config.pm).

I'd appreciate any help on the matter.  My attempted patch is below my
sig.

-- 
Jeff "japhy" Pinyan     japhy@pobox.com     http://www.pobox.com/~japhy/
PerlMonth - An Online Perl Magazine            http://www.perlmonth.com/
The Perl Archive - Articles, Forums, etc.    http://www.perlarchive.com/
CPAN - #1 Perl Resource  (my id:  PINYAN)        http://search.cpan.org/



First, an explanation of what it's doing:

given an array that looks like
  @a = qw( a b c d );
we want to unshift ('x','y','z') to @a

let's assume i = 1 (amt. of free room before beginning of the array)

after the if (i) block, we have num being 3 - 1 = 2.
in the if (num) block, i gets set to 4 (the highest index)
slide is the min of (num,i) which is 2

  i = 4
  num = 2
  slide = 2

now the array is extended from an index of 4 to an index of 8

  X is PL_sv_undef
  / is some void value

  0  1  2  3  4  5  6  7  8
  X  a  b  c  d  /  /  /  /

if (i + 1 > num + slide), we need to do TWO Moves() since Move() will mess
up on overlapping sequences.  First we move from (num+slide) to
2*(num+slide), and we do this for (i+1)-(num+slide) elements:

  num+slide = 4
  2*(num+slide) = 8
  (i+1) - (num+slide) = 5 - 4 = 1

  0  1  2  3  4  5  6  7  8
  X  a  b  c  d  /  /  /  /

  becomes

  0  1  2  3  4  5  6  7  8
  X  a  b  c  /  /  /  /  d

Now we move the FIRST num+slide elements up num+slide spaces:

  0  1  2  3  4  5  6  7  8
  X  a  b  c  /  /  /  /  d

  becomes

  0  1  2  3  4  5  6  7  8
  /  /  /  /  X  a  b  c  d

Now we fill in from --num + slide to 0 with PL_sv_undef:

  0  1  2  3  4  5  6  7  8
  X  X  X  X  X  a  b  c  d

And we set where the array's start point is (AvARRAY(av) + slide):

  0  1 |2  3  4  5  6  7  8
  X  X |X  X  X  a  b  c  d

And then the 'x', 'y', and 'z' can be filled in.




--- av.c.old    Mon Nov 20 10:02:20 2000
+++ av.c        Mon Nov 20 12:25:37 2000
@@ -552,6 +552,7 @@
 Perl_av_unshift(pTHX_ register AV *av, register I32 num)
 {   
     register I32 i;
+    register I32 slide;
     register SV **ary;
     MAGIC* mg;

@@ -591,13 +592,23 @@
     }
     if (num) {
        i = AvFILLp(av);
-       av_extend(av, i + num);
+        slide = (i < num) ? (i <= 0 ? 1 : i) : num;
+       av_extend(av, i + num + slide);
        AvFILLp(av) += num;
        ary = AvARRAY(av);
-       Move(ary, ary + num, i + 1, SV*);
+
+        if (i + 1 >= slide + num) {
+            Move(ary + num+slide, ary + 2*(num+slide), i+1 - (num+slide),
SV*);
+            Move(ary, ary + num+slide, num+slide, SV*);
+        }
+        else
+            Move(ary, ary + num+slide, i + 1, SV*);
+
        do {
-           ary[--num] = &PL_sv_undef;
-       } while (num);
+           ary[--num+slide] = &PL_sv_undef;
+       } while (num+slide);
+
+        SvPVX(av) = (char *)(AvARRAY(av) + slide);
     }
 }


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About