]> git.eshelyaron.com Git - emacs.git/commitdiff
Count bytes, not records, in specpdl_ref
authorMattias Engdegård <mattiase@acm.org>
Wed, 2 Feb 2022 16:42:07 +0000 (17:42 +0100)
committerMattias Engdegård <mattiase@acm.org>
Sat, 12 Feb 2022 17:21:34 +0000 (18:21 +0100)
SPECPDL_INDEX becomes much faster because the pointer subtraction,
expensive because of the inconveniently sized specpdl records, is now
gone.  This translates to a useful speedup on a wide variety of code.

* src/lisp.h (specpdl_ref, wrap_specpdl_ref, unwrap_specpdl_ref):
Rename member.
(specpdl_count_to_ref, specpdl_ref_to_count)
(specpdl_ref_add, specpdl_ref_to_ptr, SPECPDL_INDEX):
Count offset in bytes rather than in records.

src/lisp.h

index 9b82307f67593b790147fe86fd8c6a8d82c8d97d..f27c2ad2dd5fd70aa585a4321a0bba89ff6a68b8 100644 (file)
@@ -3356,23 +3356,24 @@ union specbinding
 #define WRAP_SPECPDL_REF 1
 #endif
 
-/* Abstract reference to to a specpdl entry.  */
+/* Abstract reference to to a specpdl entry.
+   The number is always a multiple of sizeof (union specbinding).  */
 #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;
+typedef struct { ptrdiff_t bytes; } specpdl_ref;
 #else
 typedef ptrdiff_t specpdl_ref;
 #endif
 
 /* Internal use only.  */
 INLINE specpdl_ref
-wrap_specpdl_ref (ptrdiff_t count)
+wrap_specpdl_ref (ptrdiff_t bytes)
 {
 #ifdef WRAP_SPECPDL_REF
-  return (specpdl_ref) {.n = count};
+  return (specpdl_ref){.bytes = bytes};
 #else
-  return count;
+  return bytes;
 #endif
 }
 
@@ -3381,7 +3382,7 @@ INLINE ptrdiff_t
 unwrap_specpdl_ref (specpdl_ref ref)
 {
 #ifdef WRAP_SPECPDL_REF
-  return ref.n;
+  return ref.bytes;
 #else
   return ref;
 #endif
@@ -3390,13 +3391,13 @@ unwrap_specpdl_ref (specpdl_ref ref)
 INLINE specpdl_ref
 specpdl_count_to_ref (ptrdiff_t count)
 {
-  return wrap_specpdl_ref (count);
+  return wrap_specpdl_ref (count * sizeof (union specbinding));
 }
 
 INLINE ptrdiff_t
 specpdl_ref_to_count (specpdl_ref ref)
 {
-  return unwrap_specpdl_ref (ref);
+  return unwrap_specpdl_ref (ref) / sizeof (union specbinding);
 }
 
 /* Whether two `specpdl_ref' refer to the same entry.  */
@@ -3430,20 +3431,21 @@ make_invalid_specpdl_ref (void)
 INLINE specpdl_ref
 specpdl_ref_add (specpdl_ref ref, ptrdiff_t delta)
 {
-  return specpdl_count_to_ref (specpdl_ref_to_count (ref) + delta);
+  return wrap_specpdl_ref (unwrap_specpdl_ref (ref)
+                          + delta * sizeof (union specbinding));
 }
 
 INLINE union specbinding *
 specpdl_ref_to_ptr (specpdl_ref ref)
 {
-  return specpdl + specpdl_ref_to_count (ref);
+  return (union specbinding *)((char *)specpdl + unwrap_specpdl_ref (ref));
 }
 
 /* Return a reference to the most recent specpdl entry.  */
 INLINE specpdl_ref
 SPECPDL_INDEX (void)
 {
-  return specpdl_count_to_ref (specpdl_ptr - specpdl);
+  return wrap_specpdl_ref ((char *)specpdl_ptr - (char *)specpdl);
 }
 
 INLINE bool