diff options
| author | Mattias EngdegÄrd | 2022-02-02 16:51:43 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2022-02-12 18:18:58 +0100 |
| commit | 297520852f4f0e11a34a8a867c13fdf03d83eafd (patch) | |
| tree | 590f2992b2000c3c4945d8b908a3974848fce636 /src | |
| parent | a8245e122075175df2f124b20e9e5b1b583eff89 (diff) | |
| download | emacs-297520852f4f0e11a34a8a867c13fdf03d83eafd.tar.gz emacs-297520852f4f0e11a34a8a867c13fdf03d83eafd.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lisp.h | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/src/lisp.h b/src/lisp.h index 3ff9dccc4ec..9b82307f675 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -3350,45 +3350,79 @@ union specbinding | |||
| 3350 | } bt; | 3350 | } bt; |
| 3351 | }; | 3351 | }; |
| 3352 | 3352 | ||
| 3353 | /* We use 64-bit platforms as a proxy for ones with ABIs that treat | ||
| 3354 | small structs efficiently. */ | ||
| 3355 | #if SIZE_MAX > 0xffffffff | ||
| 3356 | #define WRAP_SPECPDL_REF 1 | ||
| 3357 | #endif | ||
| 3358 | |||
| 3353 | /* Abstract reference to to a specpdl entry. */ | 3359 | /* Abstract reference to to a specpdl entry. */ |
| 3360 | #ifdef WRAP_SPECPDL_REF | ||
| 3361 | /* Use a proper type for specpdl_ref if it does not make the code slower, | ||
| 3362 | since the type checking is quite useful. */ | ||
| 3363 | typedef struct { ptrdiff_t n; } specpdl_ref; | ||
| 3364 | #else | ||
| 3354 | typedef ptrdiff_t specpdl_ref; | 3365 | typedef ptrdiff_t specpdl_ref; |
| 3366 | #endif | ||
| 3355 | 3367 | ||
| 3368 | /* Internal use only. */ | ||
| 3356 | INLINE specpdl_ref | 3369 | INLINE specpdl_ref |
| 3357 | specpdl_count_to_ref (ptrdiff_t count) | 3370 | wrap_specpdl_ref (ptrdiff_t count) |
| 3358 | { | 3371 | { |
| 3372 | #ifdef WRAP_SPECPDL_REF | ||
| 3373 | return (specpdl_ref) {.n = count}; | ||
| 3374 | #else | ||
| 3359 | return count; | 3375 | return count; |
| 3376 | #endif | ||
| 3360 | } | 3377 | } |
| 3361 | 3378 | ||
| 3379 | /* Internal use only. */ | ||
| 3362 | INLINE ptrdiff_t | 3380 | INLINE ptrdiff_t |
| 3363 | specpdl_ref_to_count (specpdl_ref ref) | 3381 | unwrap_specpdl_ref (specpdl_ref ref) |
| 3364 | { | 3382 | { |
| 3383 | #ifdef WRAP_SPECPDL_REF | ||
| 3384 | return ref.n; | ||
| 3385 | #else | ||
| 3365 | return ref; | 3386 | return ref; |
| 3387 | #endif | ||
| 3388 | } | ||
| 3389 | |||
| 3390 | INLINE specpdl_ref | ||
| 3391 | specpdl_count_to_ref (ptrdiff_t count) | ||
| 3392 | { | ||
| 3393 | return wrap_specpdl_ref (count); | ||
| 3394 | } | ||
| 3395 | |||
| 3396 | INLINE ptrdiff_t | ||
| 3397 | specpdl_ref_to_count (specpdl_ref ref) | ||
| 3398 | { | ||
| 3399 | return unwrap_specpdl_ref (ref); | ||
| 3366 | } | 3400 | } |
| 3367 | 3401 | ||
| 3368 | /* Whether two `specpdl_ref' refer to the same entry. */ | 3402 | /* Whether two `specpdl_ref' refer to the same entry. */ |
| 3369 | INLINE bool | 3403 | INLINE bool |
| 3370 | specpdl_ref_eq (specpdl_ref a, specpdl_ref b) | 3404 | specpdl_ref_eq (specpdl_ref a, specpdl_ref b) |
| 3371 | { | 3405 | { |
| 3372 | return a == b; | 3406 | return unwrap_specpdl_ref (a) == unwrap_specpdl_ref (b); |
| 3373 | } | 3407 | } |
| 3374 | 3408 | ||
| 3375 | /* Whether `a' refers to an earlier entry than `b'. */ | 3409 | /* Whether `a' refers to an earlier entry than `b'. */ |
| 3376 | INLINE bool | 3410 | INLINE bool |
| 3377 | specpdl_ref_lt (specpdl_ref a, specpdl_ref b) | 3411 | specpdl_ref_lt (specpdl_ref a, specpdl_ref b) |
| 3378 | { | 3412 | { |
| 3379 | return a < b; | 3413 | return unwrap_specpdl_ref (a) < unwrap_specpdl_ref (b); |
| 3380 | } | 3414 | } |
| 3381 | 3415 | ||
| 3382 | INLINE bool | 3416 | INLINE bool |
| 3383 | specpdl_ref_valid_p (specpdl_ref ref) | 3417 | specpdl_ref_valid_p (specpdl_ref ref) |
| 3384 | { | 3418 | { |
| 3385 | return specpdl_ref_to_count (ref) >= 0; | 3419 | return unwrap_specpdl_ref (ref) >= 0; |
| 3386 | } | 3420 | } |
| 3387 | 3421 | ||
| 3388 | INLINE specpdl_ref | 3422 | INLINE specpdl_ref |
| 3389 | make_invalid_specpdl_ref (void) | 3423 | make_invalid_specpdl_ref (void) |
| 3390 | { | 3424 | { |
| 3391 | return specpdl_count_to_ref (-1); | 3425 | return wrap_specpdl_ref (-1); |
| 3392 | } | 3426 | } |
| 3393 | 3427 | ||
| 3394 | /* Return a reference that is `delta' steps more recent than `ref'. | 3428 | /* Return a reference that is `delta' steps more recent than `ref'. |