diff options
author | Tony Cook <tony@develop-help.com> | 2020-06-25 15:26:32 +1000 |
---|---|---|
committer | Karl Williamson <khw@cpan.org> | 2020-07-30 16:08:59 -0600 |
commit | f0cfed98a12d7c2954864f82237387d2b85de5c5 (patch) | |
tree | 8f29bc5b548f86cf1c36c450d79e4ae46e3cc1bd /op.h | |
parent | 95c9b7e93b37d874a0f6f2a3c25fbe1121199124 (diff) | |
download | perl-f0cfed98a12d7c2954864f82237387d2b85de5c5.tar.gz |
re-work opslab handling to avoid non-portable alignment assumptions
Fixes #17871
The op slab allocator code made the assumption that since OP and
hence OPSLOT contain pointers, the base of each of those would be
an integral number of sizeof(pointer) (pointer units) from the
beginning of OPSLAB.
This assumption is non-portable, and broke calculating the location
of the slab based on the address of the op slot and the op slot offset
on m68k platforms.
To avoid that, this change now stores the opslot_offset as the
offset in pointer units from the beginning of opslab_slots rather
than from the beginning of the slab.
If alignment on a pointer boundary for OPs is required, the compiler
will align opslab_opslots and since we work in pointer units from there,
any allocated op slots will also be aligned.
If we assume PADOFFSET is no larger than a pointer and requires no
stricter alignment and structures in themselves have no stricter
alignment requirements then since we work in pointer units all core
OP structures should have sufficient alignment (if this isn't true,
then it's not a new problem, and not the problem I'm trying to solve
here.)
I haven't been able to test this on m68k hardware (the emulator I
tried to use can't maintain a network connection.)
Diffstat (limited to 'op.h')
-rw-r--r-- | op.h | 9 |
1 files changed, 7 insertions, 2 deletions
@@ -718,13 +718,18 @@ struct opslab { }; # define OPSLOT_HEADER STRUCT_OFFSET(OPSLOT, opslot_op) -# define OPSLOT_HEADER_P (OPSLOT_HEADER/sizeof(I32 *)) # define OpSLOT(o) (assert_(o->op_slabbed) \ (OPSLOT *)(((char *)o)-OPSLOT_HEADER)) +/* the slab that owns this op */ +# define OpMySLAB(o) \ + ((OPSLAB*)((char *)((I32**)OpSLOT(o) - OpSLOT(o)->opslot_offset)-STRUCT_OFFSET(struct opslab, opslab_slots))) /* the first (head) opslab of the chain in which this op is allocated */ # define OpSLAB(o) \ - (((OPSLAB*)( (I32**)OpSLOT(o) - OpSLOT(o)->opslot_offset))->opslab_head) + (OpMySLAB(o)->opslab_head) +/* calculate the slot given the owner slab and an offset */ +#define OpSLOToff(slab, offset) \ + ((OPSLOT*)(((I32 **)&(slab)->opslab_slots)+(offset))) # define OpslabREFCNT_dec(slab) \ (((slab)->opslab_refcnt == 1) \ |