summaryrefslogtreecommitdiff
path: root/op.h
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2020-06-25 15:26:32 +1000
committerKarl Williamson <khw@cpan.org>2020-07-30 16:08:59 -0600
commitf0cfed98a12d7c2954864f82237387d2b85de5c5 (patch)
tree8f29bc5b548f86cf1c36c450d79e4ae46e3cc1bd /op.h
parent95c9b7e93b37d874a0f6f2a3c25fbe1121199124 (diff)
downloadperl-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.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/op.h b/op.h
index fc21f03cda..6e7dc3120f 100644
--- a/op.h
+++ b/op.h
@@ -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) \