This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Ensure that the IV in struct pmop (for ithreads) is aligned properly.
authorNicholas Clark <nick@ccl4.org>
Thu, 23 May 2013 11:46:05 +0000 (13:46 +0200)
committerNicholas Clark <nick@ccl4.org>
Fri, 24 May 2013 19:24:38 +0000 (21:24 +0200)
The members of struct pmop vary between ithreads and non-ithreads builds.
For ithreads, an IV is used for op_pmoffset. For 32 bit platforms built
with -Duse64bitint, IVs are 64 bits, but pointers (and all other members of
all OP structures) are 32 bits, hence on 32 bit platforms OP structure sizes
can be an odd multiple of 4 bytes. Since the swap to the slab allocator,
this is causing problems on architectures where 8 byte IVs have to be 8
byte aligned, notably sparcs. The long-term fix is to replace the IV with
an appropriate 32 bit type, as it is being used for an array index. However,
for maint-5.18 we need a work around which doesn't change the public headers
and ideally doesn't impose a large speed or memory penalty.

Hence for now, simply avoid using the slab allocator when allocating a
struct pmop. Only do this for 32 bit platforms build with 8 byte IVs and
ithreads.

This is the interim fix for RT #118055.

op.c
pod/perldelta.pod

diff --git a/op.c b/op.c
index 1501e14..792e8d6 100644 (file)
--- a/op.c
+++ b/op.c
@@ -175,6 +175,19 @@ Perl_Slab_Alloc(pTHX_ size_t sz)
      || (CvSTART(PL_compcv) && !CvSLABBED(PL_compcv)))
        return PerlMemShared_calloc(1, sz);
 
+#if defined(USE_ITHREADS) && IVSIZE > U32SIZE
+    /* Work around a goof with alignment on our part. For sparc32 (and
+       possibly other architectures), if built with -Duse64bitint, the IV
+       op_pmoffset in struct pmop should be 8 byte aligned, but the slab
+       allocator is only providing 4 byte alignment. The real fix is to change
+       the IV to a type the same size as a pointer, such as size_t, but we
+       can't do that without breaking the ABI, which is a no-no in a maint
+       release. So instead, simply allocate struct pmop directly, which will be
+       suitably aligned:  */
+    if (sz == sizeof(struct pmop))
+       return PerlMemShared_calloc(1, sz);
+#endif
+
     /* While the subroutine is under construction, the slabs are accessed via
        CvSTART(), to avoid needing to expand PVCV by one pointer for something
        unneeded at runtime. Once a subroutine is constructed, the slabs are
index 431e811..d8994b4 100644 (file)
@@ -356,7 +356,11 @@ files in F<ext/> and F<lib/> are best summarized in L</Modules and Pragmata>.
 
 =item *
 
-XXX
+The OP allocation code now returns correctly aligned memory in all cases
+for C<struct pmop>. Previously it could return memory only aligned to a
+4-byte boundary, which is not correct for an ithreads build with 64 bit IVs
+on some 32 bit platforms. Notably, this caused the build to fail completely
+on sparc GNU/Linux. [RT #118055]
 
 =back