emacs-diffs
[Top][All Lists]
Advanced

[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'.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]