[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 297520852f 2/3: Turn specpdl_ref into a type of its own
From: |
Mattias Engdegård |
Subject: |
master 297520852f 2/3: Turn specpdl_ref into a type of its own |
Date: |
Sat, 12 Feb 2022 12:32:58 -0500 (EST) |
branch: master
commit 297520852f4f0e11a34a8a867c13fdf03d83eafd
Author: Mattias Engdegård <mattiase@acm.org>
Commit: Mattias Engdegård <mattiase@acm.org>
Turn specpdl_ref into a type of its own
Wrap the specpdl_ref contents in a struct, which gives us some very
useful type checking to make sure that all code that assumed integral
specpdl refs has been converted.
We only do this on 64-bit platforms, since those tend to have modern
ABIs where small structs are optimised as scalars. In other words,
this change should not affect the compiled code.
* src/lisp.h (specpdl_ref): Now a struct on 64-bit platforms.
(wrap_specpdl_ref, unwrap_specpdl_ref): New.
(specpdl_count_to_ref, specpdl_ref_to_count)
(specpdl_ref_eq, specpdl_ref_lt)
(specpdl_ref_valid_p, make_invalid_specpdl_ref): Use new wrappers.
---
src/lisp.h | 46 ++++++++++++++++++++++++++++++++++++++++------
1 file changed, 40 insertions(+), 6 deletions(-)
diff --git a/src/lisp.h b/src/lisp.h
index 3ff9dccc4e..9b82307f67 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3350,45 +3350,79 @@ union specbinding
} bt;
};
+/* We use 64-bit platforms as a proxy for ones with ABIs that treat
+ small structs efficiently. */
+#if SIZE_MAX > 0xffffffff
+#define WRAP_SPECPDL_REF 1
+#endif
+
/* Abstract reference to to a specpdl entry. */
+#ifdef WRAP_SPECPDL_REF
+/* Use a proper type for specpdl_ref if it does not make the code slower,
+ since the type checking is quite useful. */
+typedef struct { ptrdiff_t n; } specpdl_ref;
+#else
typedef ptrdiff_t specpdl_ref;
+#endif
+/* Internal use only. */
INLINE specpdl_ref
-specpdl_count_to_ref (ptrdiff_t count)
+wrap_specpdl_ref (ptrdiff_t count)
{
+#ifdef WRAP_SPECPDL_REF
+ return (specpdl_ref) {.n = count};
+#else
return count;
+#endif
}
+/* Internal use only. */
INLINE ptrdiff_t
-specpdl_ref_to_count (specpdl_ref ref)
+unwrap_specpdl_ref (specpdl_ref ref)
{
+#ifdef WRAP_SPECPDL_REF
+ return ref.n;
+#else
return ref;
+#endif
+}
+
+INLINE specpdl_ref
+specpdl_count_to_ref (ptrdiff_t count)
+{
+ return wrap_specpdl_ref (count);
+}
+
+INLINE ptrdiff_t
+specpdl_ref_to_count (specpdl_ref ref)
+{
+ return unwrap_specpdl_ref (ref);
}
/* Whether two `specpdl_ref' refer to the same entry. */
INLINE bool
specpdl_ref_eq (specpdl_ref a, specpdl_ref b)
{
- return a == b;
+ return unwrap_specpdl_ref (a) == unwrap_specpdl_ref (b);
}
/* Whether `a' refers to an earlier entry than `b'. */
INLINE bool
specpdl_ref_lt (specpdl_ref a, specpdl_ref b)
{
- return a < b;
+ return unwrap_specpdl_ref (a) < unwrap_specpdl_ref (b);
}
INLINE bool
specpdl_ref_valid_p (specpdl_ref ref)
{
- return specpdl_ref_to_count (ref) >= 0;
+ return unwrap_specpdl_ref (ref) >= 0;
}
INLINE specpdl_ref
make_invalid_specpdl_ref (void)
{
- return specpdl_count_to_ref (-1);
+ return wrap_specpdl_ref (-1);
}
/* Return a reference that is `delta' steps more recent than `ref'.