xref: /openbsd/gnu/usr.bin/perl/t/bigmem/stack.t (revision 5486feef)
1*5486feefSafresh1#!perl
2*5486feefSafresh1BEGIN {
3*5486feefSafresh1    chdir 't' if -d 't';
4*5486feefSafresh1    @INC = "../lib";
5*5486feefSafresh1    require './test.pl';
6*5486feefSafresh1}
7*5486feefSafresh1
8*5486feefSafresh1use strict;
9*5486feefSafresh1use Config qw(%Config);
10*5486feefSafresh1use XS::APItest;
11*5486feefSafresh1
12*5486feefSafresh1# memory usage checked with top
13*5486feefSafresh1$ENV{PERL_TEST_MEMORY} >= 60
14*5486feefSafresh1    or skip_all("Need ~60GB for this test");
15*5486feefSafresh1$Config{ptrsize} >= 8
16*5486feefSafresh1    or skip_all("Need 64-bit pointers for this test");
17*5486feefSafresh1XS::APItest::wide_marks()
18*5486feefSafresh1    or skip_all("Not configured for SSize_t marks");
19*5486feefSafresh1
20*5486feefSafresh1my @x;
21*5486feefSafresh1$x[0x8000_0000] = "Hello";
22*5486feefSafresh1
23*5486feefSafresh1my $arg_count;
24*5486feefSafresh1
25*5486feefSafresh1my @tests =
26*5486feefSafresh1  (
27*5486feefSafresh1      [ mark => sub
28*5486feefSafresh1        {
29*5486feefSafresh1            # unlike the grep example this avoids the mark manipulation done by grep
30*5486feefSafresh1            # so it's more of a pure mark type test
31*5486feefSafresh1            # it also fails/succeeds a lot faster
32*5486feefSafresh1            my $count = () =  (x(), z());
33*5486feefSafresh1            is($count, 0x8000_0002, "got expected (large) list size");
34*5486feefSafresh1        },
35*5486feefSafresh1      ],
36*5486feefSafresh1      [ xssize => sub
37*5486feefSafresh1        {
38*5486feefSafresh1            # check XS gets the right numbers in our predefined variables
39*5486feefSafresh1            # returned ~ -2G before fix
40*5486feefSafresh1            my $count = XS::APItest::xs_items(x(), z());
41*5486feefSafresh1            is($count, 0x8000_0002, "got expected XS list size");
42*5486feefSafresh1        }
43*5486feefSafresh1      ],
44*5486feefSafresh1      [ listsub => sub
45*5486feefSafresh1        {
46*5486feefSafresh1            my $last = ( x() )[-1];
47*5486feefSafresh1            is($last, "Hello", "list subscripting");
48*5486feefSafresh1
49*5486feefSafresh1            my ($first, $last2, $last1) = ( "first", x(), "Goodbye" )[0, -2, -1];
50*5486feefSafresh1            is($first, "first", "list subscripting in list context (0)");
51*5486feefSafresh1            is($last2, "Hello", "list subscripting in list context (-2)");
52*5486feefSafresh1            is($last1, "Goodbye", "list subscripting in list context (-1)");
53*5486feefSafresh1        }
54*5486feefSafresh1      ],
55*5486feefSafresh1      [ iterctx => sub
56*5486feefSafresh1        {
57*5486feefSafresh1            # the iter context had an I32 stack offset
58*5486feefSafresh1            my $last = ( x(), iter() )[-1];
59*5486feefSafresh1            is($last, "abc", "check iteration not confused");
60*5486feefSafresh1        }
61*5486feefSafresh1      ],
62*5486feefSafresh1      [ split => sub
63*5486feefSafresh1        {
64*5486feefSafresh1            # split had an I32 base offset
65*5486feefSafresh1            # this paniced with "Split loop"
66*5486feefSafresh1            my $count = () = ( x(), do_split("ABC") );
67*5486feefSafresh1            is($count, 0x8000_0004, "split base index");
68*5486feefSafresh1            # it would be nice to test split returning >2G (or >4G) items, but
69*5486feefSafresh1            # I don't have the memory needed
70*5486feefSafresh1        }
71*5486feefSafresh1      ],
72*5486feefSafresh1      [ xsload => sub
73*5486feefSafresh1        {
74*5486feefSafresh1            # I expect this to crash if buggy
75*5486feefSafresh1            my $count = () = (x(), loader());
76*5486feefSafresh1            is($count, 0x8000_0001, "check loading XS with large stack");
77*5486feefSafresh1        }
78*5486feefSafresh1      ],
79*5486feefSafresh1      [ pp_list => sub
80*5486feefSafresh1        {
81*5486feefSafresh1            my $l = ( x(), list2() )[-1];
82*5486feefSafresh1            is($l, 2, "pp_list mark handling");
83*5486feefSafresh1        }
84*5486feefSafresh1       ],
85*5486feefSafresh1      [
86*5486feefSafresh1          chomp_av => sub {
87*5486feefSafresh1              # not really stack related, but is 32-bit related
88*5486feefSafresh1              local $x[-1] = "Hello\n";
89*5486feefSafresh1              chomp(@x);
90*5486feefSafresh1              is($x[-1], "Hello", "chomp on a large array");
91*5486feefSafresh1          }
92*5486feefSafresh1         ],
93*5486feefSafresh1      [
94*5486feefSafresh1          grepwhile => sub {
95*5486feefSafresh1            SKIP: {
96*5486feefSafresh1                  skip "This test is even slower - define PERL_RUN_SLOW_TESTS to run me", 1
97*5486feefSafresh1                    unless $ENV{PERL_RUN_SLOW_TESTS};
98*5486feefSafresh1                  # grep ..., @x used too much memory
99*5486feefSafresh1                  my $count = grep 1, ( (undef) x 0x7FFF_FFFF, 1, 1 );
100*5486feefSafresh1                  is($count, 0x8000_0001, "grepwhile item count");
101*5486feefSafresh1              }
102*5486feefSafresh1          }
103*5486feefSafresh1      ],
104*5486feefSafresh1      [
105*5486feefSafresh1          repeat => sub {
106*5486feefSafresh1            SKIP:
107*5486feefSafresh1              {
108*5486feefSafresh1                  $ENV{PERL_TEST_MEMORY} >= 70
109*5486feefSafresh1                       or skip "repeat test needs 70GB", 2;
110*5486feefSafresh1                  # pp_repeat would throw an unable to allocate error
111*5486feefSafresh1                  my ($lastm1, $middle) = ( ( x() ) x 2 )[-1, @x-1];
112*5486feefSafresh1                  is($lastm1, "Hello", "repeat lastm1");
113*5486feefSafresh1                  is($middle, "Hello", "repeat middle");
114*5486feefSafresh1              }
115*5486feefSafresh1          },
116*5486feefSafresh1      ],
117*5486feefSafresh1      [
118*5486feefSafresh1          tiescalar => sub {
119*5486feefSafresh1            SKIP:
120*5486feefSafresh1              {
121*5486feefSafresh1                  # this swaps unless you have actually 80GB RAM, since
122*5486feefSafresh1                  # most of the memory is touched
123*5486feefSafresh1                  $ENV{PERL_TEST_MEMORY} >= 80
124*5486feefSafresh1                    or skip "tiescalar second test needs 80GB", 2;
125*5486feefSafresh1                  my $x;
126*5486feefSafresh1                  ok(ref( ( x(), tie($x, "ScalarTie", 1..5))[-1]),
127*5486feefSafresh1                     "tied with deep stack");
128*5486feefSafresh1                  is($x, 6, "check arguments received");
129*5486feefSafresh1                  untie $x;
130*5486feefSafresh1                  ok(tie($x, "ScalarTie", x()), "tie scalar with long argument list");
131*5486feefSafresh1                  is($x, 1+scalar(@x), "check arguments received");
132*5486feefSafresh1                  untie $x;
133*5486feefSafresh1                SKIP:
134*5486feefSafresh1                  {
135*5486feefSafresh1                      skip "This test is even slower - define PERL_RUN_SLOW_TESTS to run me", 1
136*5486feefSafresh1                        unless $ENV{PERL_RUN_SLOW_TESTS};
137*5486feefSafresh1                      my $o = bless {}, "ScalarTie";
138*5486feefSafresh1                      # this was news to me
139*5486feefSafresh1                      ok(tie($x, $o, x(), 1), "tie scalar via object with long argument list");
140*5486feefSafresh1                      is($x, 2+scalar(@x), "check arguments received");
141*5486feefSafresh1                      untie $x;
142*5486feefSafresh1                  }
143*5486feefSafresh1              }
144*5486feefSafresh1          }
145*5486feefSafresh1      ],
146*5486feefSafresh1      [
147*5486feefSafresh1          apply => sub {
148*5486feefSafresh1            SKIP:
149*5486feefSafresh1              {
150*5486feefSafresh1                  skip "2**31 system calls take a very long time - define PERL_RUN_SLOW_TESTS to run me", 1
151*5486feefSafresh1                    unless $ENV{PERL_RUN_SLOW_TESTS};
152*5486feefSafresh1                  my $mode = (stat $0)[2];
153*5486feefSafresh1                  my $tries = 0x8000_0001;
154*5486feefSafresh1                  my $count = chmod $mode, ( $0 ) x $tries;
155*5486feefSafresh1                  is($count, $tries, "chmod with 2G files");
156*5486feefSafresh1              }
157*5486feefSafresh1          }
158*5486feefSafresh1      ],
159*5486feefSafresh1      [
160*5486feefSafresh1          join => sub {
161*5486feefSafresh1              no warnings 'uninitialized';
162*5486feefSafresh1              my $joined = join "", @x, "!";
163*5486feefSafresh1              is($joined, "Hello!", "join");
164*5486feefSafresh1          },
165*5486feefSafresh1      ],
166*5486feefSafresh1      [
167*5486feefSafresh1          class_construct => sub {
168*5486feefSafresh1              use experimental 'class';
169*5486feefSafresh1              class Foo {
170*5486feefSafresh1                  field $x :param;
171*5486feefSafresh1              };
172*5486feefSafresh1              my $y = Foo->new((x => 1) x 0x4000_0001);
173*5486feefSafresh1              ok($y, "construct class based object with 2G parameters");
174*5486feefSafresh1          },
175*5486feefSafresh1      ],
176*5486feefSafresh1      [
177*5486feefSafresh1          eval_sv_count => sub {
178*5486feefSafresh1            SKIP:
179*5486feefSafresh1              {
180*5486feefSafresh1                  $ENV{PERL_TEST_MEMORY} >= 70
181*5486feefSafresh1                    or skip "eval_sv_count test needs 70GB", 2;
182*5486feefSafresh1
183*5486feefSafresh1                  my $count = ( @x, XS::APItest::eval_sv('@x', G_LIST) )[-1];
184*5486feefSafresh1                  is($count, scalar @x, "check eval_sv result/mark handling");
185*5486feefSafresh1              }
186*5486feefSafresh1          }
187*5486feefSafresh1      ],
188*5486feefSafresh1      [
189*5486feefSafresh1          call_sv_args => sub {
190*5486feefSafresh1              undef $arg_count;
191*5486feefSafresh1              my $ret_count = XS::APItest::call_sv(\&arg_count, G_LIST, x());
192*5486feefSafresh1              is($ret_count, 0, "call_sv with 2G args - arg_count() returns nothing");
193*5486feefSafresh1              is($arg_count, scalar @x, "check call_sv argument handling - argument count");
194*5486feefSafresh1          },
195*5486feefSafresh1      ],
196*5486feefSafresh1      [
197*5486feefSafresh1          call_sv_mark => sub {
198*5486feefSafresh1              my $ret_count = ( x(), XS::APItest::call_sv(\&list, G_LIST) )[-1];
199*5486feefSafresh1              is($ret_count, 2, "call_sv with deep stack - returned value count");
200*5486feefSafresh1          },
201*5486feefSafresh1      ],
202*5486feefSafresh1     );
203*5486feefSafresh1
204*5486feefSafresh1# these tests are slow, let someone debug them one at a time
205*5486feefSafresh1my %enabled = map { $_ => 1 } @ARGV;
206*5486feefSafresh1for my $test (@tests) {
207*5486feefSafresh1    my ($id, $code) = @$test;
208*5486feefSafresh1    if (!@ARGV || $enabled{$id}) {
209*5486feefSafresh1        note($id);
210*5486feefSafresh1        $code->();
211*5486feefSafresh1    }
212*5486feefSafresh1}
213*5486feefSafresh1
214*5486feefSafresh1done_testing();
215*5486feefSafresh1
216*5486feefSafresh1sub x { @x }
217*5486feefSafresh1
218*5486feefSafresh1sub z { 1 }
219*5486feefSafresh1
220*5486feefSafresh1sub iter {
221*5486feefSafresh1    my $result = '';
222*5486feefSafresh1    my $count = 0;
223*5486feefSafresh1    for my $item (qw(a b c)) {
224*5486feefSafresh1        $result .= $item;
225*5486feefSafresh1        die "iteration bug" if ++$count > 5;
226*5486feefSafresh1    }
227*5486feefSafresh1    $result;
228*5486feefSafresh1}
229*5486feefSafresh1
230*5486feefSafresh1sub do_split {
231*5486feefSafresh1    return split //, $_[0];
232*5486feefSafresh1}
233*5486feefSafresh1
234*5486feefSafresh1sub loader {
235*5486feefSafresh1    require Cwd;
236*5486feefSafresh1    ();
237*5486feefSafresh1}
238*5486feefSafresh1
239*5486feefSafresh1sub list2 {
240*5486feefSafresh1    scalar list(1);
241*5486feefSafresh1}
242*5486feefSafresh1
243*5486feefSafresh1sub list {
244*5486feefSafresh1    # ensure this continues to use a pp_list op
245*5486feefSafresh1    # if you change it.
246*5486feefSafresh1    return shift() ? (1, 2) : (2, 1);
247*5486feefSafresh1}
248*5486feefSafresh1
249*5486feefSafresh1sub arg_count {
250*5486feefSafresh1    $arg_count = @_;
251*5486feefSafresh1    ();
252*5486feefSafresh1}
253*5486feefSafresh1
254*5486feefSafresh1package ScalarTie;
255*5486feefSafresh1
256*5486feefSafresh1sub TIESCALAR {
257*5486feefSafresh1    ::note("TIESCALAR $_[0]");
258*5486feefSafresh1    bless { count => scalar @_ }, __PACKAGE__;
259*5486feefSafresh1}
260*5486feefSafresh1
261*5486feefSafresh1sub FETCH {
262*5486feefSafresh1    $_[0]{count};
263*5486feefSafresh1}
264