]> git.vpit.fr Git - perl/modules/Lexical-Types.git/commitdiff
Stop leaking the op specific info
authorVincent Pit <vince@profvince.com>
Sat, 4 Jul 2009 10:39:19 +0000 (12:39 +0200)
committerVincent Pit <vince@profvince.com>
Sat, 4 Jul 2009 10:39:19 +0000 (12:39 +0200)
This needs extra care under multiplicity perls. We can't actually use a SV because there's no way to free it in the context of the interpreter it was allocated from : it may very well not exist anymore at this point.

MANIFEST
Types.xs
t/40-stress.t [new file with mode: 0644]

index f14794d2cc5a5da674f41d1287c561f9d395eec6..f8c8cf3e21372da624dca6c50ba70859f2e4eabe 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -20,6 +20,7 @@ t/21-tie.t
 t/22-magic.t
 t/23-magic-uvar.t
 t/30-threads.t
+t/40-stress.t
 t/91-pod.t
 t/92-pod-coverage.t
 t/95-portability-files.t
index f3ce903ecbdbc9fc6953312c8cbc465b3b48f957..a01cc1525e7208324f0eb6ab243d6b5118124bf6 100644 (file)
--- a/Types.xs
+++ b/Types.xs
@@ -319,9 +319,14 @@ STATIC perl_mutex lt_op_map_mutex;
 #endif
 
 typedef struct {
+#if LT_MULTIPLICITY
+ STRLEN buf_size, orig_pkg_len, type_pkg_len, type_meth_len;
+ char *buf;
+#else /* LT_MULTIPLICITY */
  SV *orig_pkg;
  SV *type_pkg;
  SV *type_meth;
+#endif /* !LT_MULTIPLICITY */
  OP *(*pp_padsv)(pTHX);
 } lt_op_info;
 
@@ -336,11 +341,45 @@ STATIC void lt_map_store(pPTBLMS_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *t
  if (!(oi = ptable_fetch(lt_op_map, o))) {
   oi = PerlMemShared_malloc(sizeof *oi);
   ptable_map_store(lt_op_map, o, oi);
+#if LT_MULTIPLICITY
+  oi->buf      = NULL;
+  oi->buf_size = 0;
+#else /* LT_MULTIPLICITY */
+ } else {
+  SvREFCNT_dec(oi->orig_pkg);
+  SvREFCNT_dec(oi->type_pkg);
+  SvREFCNT_dec(oi->type_meth);
+#endif /* !LT_MULTIPLICITY */
  }
 
+#if LT_MULTIPLICITY
+ {
+  STRLEN op_len       = SvCUR(orig_pkg);
+  STRLEN tp_len       = SvCUR(type_pkg);
+  STRLEN tm_len       = SvCUR(type_meth);
+  STRLEN new_buf_size = op_len + tp_len + tm_len;
+  char *buf;
+  if (new_buf_size > oi->buf_size) {
+   PerlMemShared_free(oi->buf);
+   oi->buf      = PerlMemShared_malloc(new_buf_size);
+   oi->buf_size = new_buf_size;
+  }
+  buf  = oi->buf;
+  Copy(SvPVX(orig_pkg),  buf, op_len, char);
+  buf += op_len;
+  Copy(SvPVX(type_pkg),  buf, tp_len, char);
+  buf += tp_len;
+  Copy(SvPVX(type_meth), buf, tm_len, char);
+  oi->orig_pkg_len  = op_len;
+  oi->type_pkg_len  = tp_len;
+  oi->type_meth_len = tm_len;
+ }
+#else /* LT_MULTIPLICITY */
  oi->orig_pkg  = orig_pkg;
  oi->type_pkg  = type_pkg;
  oi->type_meth = type_meth;
+#endif /* !LT_MULTIPLICITY */
+
  oi->pp_padsv  = pp_padsv;
 
 #ifdef USE_ITHREADS
@@ -393,20 +432,40 @@ STATIC OP *lt_pp_padsv(pTHX) {
   SV *sv         = PAD_SVl(targ);
 
   if (sv) {
+   SV *orig_pkg, *type_pkg, *type_meth;
    int items;
    dSP;
 
    ENTER;
    SAVETMPS;
 
+#if LT_MULTIPLICITY
+   {
+    STRLEN op_len = oi.orig_pkg_len, tp_len = oi.type_pkg_len;
+    char *buf = oi.buf;
+    orig_pkg  = sv_2mortal(newSVpvn(buf, op_len));
+    SvREADONLY_on(orig_pkg);
+    buf      += op_len;
+    type_pkg  = sv_2mortal(newSVpvn(buf, tp_len));
+    SvREADONLY_on(type_pkg);
+    buf      += tp_len;
+    type_meth = sv_2mortal(newSVpvn(buf, oi.type_meth_len));
+    SvREADONLY_on(type_meth);
+   }
+#else /* LT_MULTIPLICITY */
+   orig_pkg  = oi.orig_pkg;
+   type_pkg  = oi.type_pkg;
+   type_meth = oi.type_meth;
+#endif /* !LT_MULTIPLICITY */
+
    PUSHMARK(SP);
    EXTEND(SP, 3);
-   PUSHs(oi.type_pkg);
+   PUSHs(type_pkg);
    PUSHs(sv);
-   PUSHs(oi.orig_pkg);
+   PUSHs(orig_pkg);
    PUTBACK;
 
-   items = call_sv(oi.type_meth, G_ARRAY | G_METHOD);
+   items = call_sv(type_meth, G_ARRAY | G_METHOD);
 
    SPAGAIN;
    switch (items) {
diff --git a/t/40-stress.t b/t/40-stress.t
new file mode 100644 (file)
index 0000000..16fd887
--- /dev/null
@@ -0,0 +1,19 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+my $count;
+BEGIN { $count = 1_000 }
+
+use Test::More tests => $count;
+
+sub Int::TYPEDSCALAR { join ':', (caller(0))[2], $_ }
+
+for (1 .. $count) {
+ eval q{
+  use Lexical::Types;
+  my Int $x;
+  is $x, "3:$_", "run $_";
+ }
+}