]> git.vpit.fr Git - perl/modules/autovivification.git/commitdiff
Assert that ops reallocated are handled correctly test_realloc
authorVincent Pit <perl@profvince.com>
Fri, 22 Jul 2016 15:50:43 +0000 (12:50 -0300)
committerVincent Pit <perl@profvince.com>
Fri, 22 Jul 2016 15:50:43 +0000 (12:50 -0300)
autovivification.xs
samples/stress_realloc.pl [new file with mode: 0644]

index 5844328eae64768d4a9390e258dc45b102d686c4..23b1f2bf8addcc0c77e12929a9428f2db4959875 100644 (file)
@@ -343,6 +343,22 @@ static int a_undef(pTHX_ SV *sv) {
  * again. That's why we don't remove the op info from our map, so that it can
  * still run correctly if required. */
 
+#ifdef DEBUGGING
+
+static UV a_cop_hint(pTHX_ COP *cop) {
+#define a_cop_hint(C) a_cop_hint(aTHX_ (C))
+ SV *hint;
+
+ if (!cop)
+  return 0;
+
+ hint = cop_hints_fetch_pvn(cop, XSH_HINTS_KEY, XSH_HINTS_KEY_LEN, xsh_hints_key_hash, 0);
+
+ return hint ? xsh_hints_detag(hint) : 0;
+}
+
+#endif
+
 /* ... pp_rv2av ............................................................ */
 
 static OP *a_pp_rv2av(pTHX) {
@@ -352,16 +368,18 @@ static OP *a_pp_rv2av(pTHX) {
 
  oi = a_map_fetch(PL_op);
 
- if (oi->flags & A_HINT_DEREF) {
-  if (a_undef(TOPs)) {
-   /* We always need to push an empty array to fool the pp_aelem() that comes
-    * later. */
-   SV *av;
-   (void) POPs;
-   av = sv_2mortal((SV *) newAV());
-   PUSHs(av);
-   RETURN;
-  }
+ XSH_ASSERT(a_cop_hint(PL_curcop));
+ XSH_ASSERT(oi->flags & A_HINT_DEREF);
+ XSH_ASSERT(oi->flags & A_HINT_DO);
+
+ if (a_undef(TOPs)) {
+  /* We always need to push an empty array to fool the pp_aelem() that comes
+   * later. */
+  SV *av;
+  (void) POPs;
+  av = sv_2mortal((SV *) newAV());
+  PUSHs(av);
+  RETURN;
  }
 
  return oi->old_pp(aTHX);
@@ -376,10 +394,12 @@ static OP *a_pp_rv2hv_simple(pTHX) {
 
  oi = a_map_fetch(PL_op);
 
- if (oi->flags & A_HINT_DEREF) {
-  if (a_undef(TOPs))
-   RETURN;
- }
+ XSH_ASSERT(a_cop_hint(PL_curcop));
+ XSH_ASSERT(oi->flags & A_HINT_DEREF);
+ XSH_ASSERT(oi->flags & A_HINT_DO);
+
+ if (a_undef(TOPs))
+  RETURN;
 
  return oi->old_pp(aTHX);
 }
@@ -391,14 +411,16 @@ static OP *a_pp_rv2hv(pTHX) {
 
  oi = a_map_fetch(PL_op);
 
- if (oi->flags & A_HINT_DEREF) {
-  if (a_undef(TOPs)) {
-   SV *hv;
-   (void) POPs;
-   hv = sv_2mortal((SV *) newHV());
-   PUSHs(hv);
-   RETURN;
-  }
+ XSH_ASSERT(a_cop_hint(PL_curcop));
+ XSH_ASSERT(oi->flags & A_HINT_DEREF);
+ XSH_ASSERT(oi->flags & (A_HINT_FETCH|A_HINT_STORE));
+
+ if (a_undef(TOPs)) {
+  SV *hv;
+  (void) POPs;
+  hv = sv_2mortal((SV *) newHV());
+  PUSHs(hv);
+  RETURN;
  }
 
  return oi->old_pp(aTHX);
@@ -420,26 +442,25 @@ static OP *a_pp_deref(pTHX) {
  dA_MAP_THX;
  const a_op_info *oi;
  UV flags;
+ OP *o;
  dSP;
 
  oi = a_map_fetch(PL_op);
 
+ XSH_ASSERT(a_cop_hint(PL_curcop));
  flags = oi->flags;
- if (flags & A_HINT_DEREF) {
 OP *o;
+ XSH_ASSERT(oi->flags & A_HINT_DEREF);
XSH_ASSERT(oi->flags & A_HINT_DO);
 
 o = oi->old_pp(aTHX);
+ o = oi->old_pp(aTHX);
 
-  if (flags & (A_HINT_NOTIFY|A_HINT_STORE)) {
-   SPAGAIN;
-   if (a_undef(TOPs))
-    a_cannot_vivify(flags);
-  }
-
-  return o;
+ if (flags & (A_HINT_NOTIFY|A_HINT_STORE)) {
+  SPAGAIN;
+  if (a_undef(TOPs))
+   a_cannot_vivify(flags);
  }
 
- return oi->old_pp(aTHX);
+ return o;
 }
 
 /* ... pp_root (exists,delete,keys,values) ................................. */
@@ -599,13 +620,14 @@ static OP *a_pp_multideref(pTHX) {
  SV *sv    = NULL;
  dSP;
 
+ XSH_ASSERT(a_cop_hint(PL_curcop));
+
  {
   dA_MAP_THX;
   const a_op_info *oi = a_map_fetch(PL_op);
   XSH_ASSERT(oi);
   flags = a_do_multideref(PL_op, oi->flags);
-  if (!flags)
-   return oi->old_pp(aTHX);
+  XSH_ASSERT(flags & A_HINT_DO);
  }
 
  items   = cUNOP_AUXx(PL_op)->op_aux;
@@ -1028,6 +1050,10 @@ static OP *a_ck_root(pTHX_ OP *o) {
 /* --- Our peephole optimizer ---------------------------------------------- */
 
 static void xsh_peep_rec(pTHX_ OP *o, ptable *seen) {
+#ifdef DEBUGGING
+ COP *last_cop = NULL;
+#endif
+
  for (; o; o = o->op_next) {
   dA_MAP_THX;
   const a_op_info *oi = NULL;
@@ -1037,11 +1063,20 @@ static void xsh_peep_rec(pTHX_ OP *o, ptable *seen) {
    break;
 
   switch (o->op_type) {
+#ifdef DEBUGGING
+   case OP_NEXTSTATE:
+   case OP_DBSTATE:
+    last_cop = o;
+    break;
+#endif
    case OP_PADSV:
     if (o->op_ppaddr != a_pp_deref) {
      oi = a_map_fetch(o);
      if (oi && (oi->flags & A_HINT_DO)) {
       a_map_store(o, o->op_ppaddr, oi->next, oi->flags);
+#ifdef DEBUGGING
+      XSH_ASSERT(!last_cop || a_cop_hint(last_cop));
+#endif
       o->op_ppaddr = a_pp_deref;
      }
     }
diff --git a/samples/stress_realloc.pl b/samples/stress_realloc.pl
new file mode 100644 (file)
index 0000000..694e9a0
--- /dev/null
@@ -0,0 +1,28 @@
+#!perl
+
+use strict;
+use warnings;
+use blib;
+
+my $n = 1_000;
+my $p = 100;
+
+my $test = <<'TEST';
+ my $e = $x->{foo}[0]{bar};
+ delete $x->{a}[1]{b};
+ exists $x->{x}[2]{y};
+TEST
+
+for (1 .. $n) {
+ my $x;
+ my $r = eval <<" CODE";
+  no autovivification;
+  $test
+ CODE
+ die $@ if $@ or defined $x;
+ for (1 .. $p) {
+  my $x;
+  my $r = eval $test;
+  die $@ if $@;
+ }
+}