On my platform this made ‘make compile-always’ 1.3% faster.
Suggested by Alex Gramiak in:
https://lists.gnu.org/r/emacs-devel/2019-04/msg00684.html
* configure.ac (nw): Don’t use -Wsuggest-attribute=cold.
* lib-src/make-docfile.c (write_globals):
Mark noreturn functions as cold.
* src/callproc.c (exec_failed):
* src/data.c (wrong_length_argument, wrong_type_argument):
* src/emacs-module.c (module_abort):
* src/emacs.c (terminate_due_to_signal):
* src/eval.c (unwind_to_catch):
* src/image.c (my_png_error, my_error_exit):
* src/json.c (json_out_of_memory, json_parse_error):
* src/keyboard.c (quit_throw_to_read_char, user_error):
* src/lisp.h (die, wrong_type_argument, wrong_choice)
(args_out_of_range, args_out_of_range_3, circular_list)
(buffer_overflow, memory_full, buffer_memory_full)
(string_overflow, xsignal, xsignal0, xsignal1, xsignal2)
(xsignal3, signal_error, overflow_error, error, verror)
(nsberror, report_file_errno, report_file_error)
(report_file_notify_error, terminate_due_to_signal)
(emacs_abort, fatal):
* src/lread.c (load_error_old_style_backquotes)
(end_of_file_error, invalid_syntax):
* src/pdumper.c (error_unsupported_dump_object):
* src/puresize.h (pure_write_error):
* src/search.c (matcher_overflow):
* src/sound.c (sound_perror, alsa_sound_perror):
* src/sysdep.c (handle_arith_signal):
* src/systime.h (time_overflow):
* src/term.c (maybe_fatal, vfatal):
* src/textprop.c (text_read_only):
* src/timefns.c (invalid_time_zone_specification)
(time_error, invalid_hz):
* src/xterm.c (x_connection_closed):
Use AVOID instead of _Noreturn void, so that it’s marked cold.
* src/conf_post.h (__has_attribute_cold) [!__has_attribute]:
New macro.
(ATTRIBUTE_COLD): New macro.
* src/frame.h (WINDOW_SYSTEM_RETURN): Add ATTRIBUTE_COLD.
* src/lisp.h (AVOID): New macro.
* src/xterm.c: Omit unnecessary static decls, so that we needn’t
worry about which functions should be marked cold.
(x_io_error_quitter): Mark as cold.
# Emacs's use of alloca inhibits protecting the stack.
nw="$nw -Wstack-protector"
+ # Emacs's use of __attribute__ ((cold)) causes false alarms with this option.
+ nw="$nw -Wsuggest-attribute=cold"
+
# Emacs's use of partly-const functions such as Fgnutls_available_p
# make this option problematic.
nw="$nw -Wsuggest-attribute=const"
printf ("%d", globals[i].v.value);
putchar (')');
+ if (globals[i].flags & DEFUN_noreturn)
+ fputs (" ATTRIBUTE_COLD", stdout);
if (globals[i].flags & DEFUN_const)
fputs (" ATTRIBUTE_CONST", stdout);
mess up the allocator's data structures in the parent.
Report the error and exit the child. */
-static _Noreturn void
+static AVOID
exec_failed (char const *name, int err)
{
/* Avoid deadlock if the child's perror writes to a full pipe; the
# define __has_attribute(a) __has_attribute_##a
# define __has_attribute_alloc_size GNUC_PREREQ (4, 3, 0)
# define __has_attribute_cleanup GNUC_PREREQ (3, 4, 0)
+# define __has_attribute_cold GNUC_PREREQ (4, 3, 0)
# define __has_attribute_externally_visible GNUC_PREREQ (4, 1, 0)
# define __has_attribute_no_address_safety_analysis false
# define __has_attribute_no_sanitize_address GNUC_PREREQ (4, 8, 0)
extern char *emacs_getenv_TZ (void);
extern int emacs_setenv_TZ (char const *);
+#if __has_attribute (cold)
+# define ATTRIBUTE_COLD __attribute__ ((cold))
+#else
+# define ATTRIBUTE_COLD
+#endif
+
#if __GNUC__ >= 3 /* On GCC 3.0 we might get a warning. */
#define NO_INLINE __attribute__((noinline))
#else
blv->valcell = val;
}
-static _Noreturn void
+static AVOID
wrong_length_argument (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3)
{
Lisp_Object size1 = make_fixnum (bool_vector_size (a1));
make_fixnum (bool_vector_size (a3)));
}
-_Noreturn void
+AVOID
wrong_type_argument (register Lisp_Object predicate, register Lisp_Object value)
{
/* If VALUE is not even a valid Lisp object, we'd want to abort here
static void module_assert_thread (void);
static void module_assert_runtime (struct emacs_runtime *);
static void module_assert_env (emacs_env *);
-static _Noreturn void module_abort (const char *format, ...)
- ATTRIBUTE_FORMAT_PRINTF(1, 2);
+static AVOID module_abort (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
static emacs_env *initialize_environment (emacs_env *,
struct emacs_env_private *);
static void finalize_environment (emacs_env *);
initialize_storage (&global_storage);
}
-static _Noreturn void
-ATTRIBUTE_FORMAT_PRINTF(1, 2)
+static AVOID ATTRIBUTE_FORMAT_PRINTF (1, 2)
module_abort (const char *format, ...)
{
fputs ("Emacs module assertion: ", stderr);
/* Report a fatal error due to signal SIG, output a backtrace of at
most BACKTRACE_LIMIT lines, and exit. */
-_Noreturn void
+AVOID
terminate_due_to_signal (int sig, int backtrace_limit)
{
signal (sig, SIG_DFL);
This is used for correct unwinding in Fthrow and Fsignal. */
-static _Noreturn void
+static AVOID
unwind_to_catch (struct handler *catch, Lisp_Object value)
{
bool last_time;
#ifdef HAVE_WINDOW_SYSTEM
# define WINDOW_SYSTEM_RETURN
#else
-# define WINDOW_SYSTEM_RETURN _Noreturn
+# define WINDOW_SYSTEM_RETURN _Noreturn ATTRIBUTE_COLD
#endif
extern WINDOW_SYSTEM_RETURN struct frame *
/* Error and warning handlers installed when the PNG library
is initialized. */
-static _Noreturn void
+static AVOID
my_png_error (png_struct *png_ptr, const char *msg)
{
eassert (png_ptr != NULL);
};
-static _Noreturn void
+static AVOID
my_error_exit (j_common_ptr cinfo)
{
struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
return code_convert_string (string, Qutf_8_unix, Qt, true, true, true);
}
-static _Noreturn void
+static AVOID
json_out_of_memory (void)
{
xsignal0 (Qjson_out_of_memory);
/* Signal a Lisp error corresponding to the JSON ERROR. */
-static _Noreturn void
+static AVOID
json_parse_error (const json_error_t *error)
{
Lisp_Object symbol;
static Lisp_Object apply_modifiers (int, Lisp_Object);
static void restore_kboard_configuration (int);
static void handle_interrupt (bool);
-static _Noreturn void quit_throw_to_read_char (bool);
+static AVOID quit_throw_to_read_char (bool);
static void timer_start_idle (void);
static void timer_stop_idle (void);
static void timer_resume_idle (void);
Fthrow (Qtop_level, Qnil);
}
-static _Noreturn void
+static AVOID
user_error (const char *msg)
{
xsignal1 (Quser_error, build_string (msg));
}
-/* _Noreturn will be added to prototype by make-docfile. */
DEFUN ("exit-recursive-edit", Fexit_recursive_edit, Sexit_recursive_edit, 0, 0, "",
doc: /* Exit from the innermost recursive edit or minibuffer. */
attributes: noreturn)
user_error ("No recursive edit is in progress");
}
-/* _Noreturn will be added to prototype by make-docfile. */
DEFUN ("abort-recursive-edit", Fabort_recursive_edit, Sabort_recursive_edit, 0, 0, "",
doc: /* Abort the command that requested this recursive edit or minibuffer input. */
attributes: noreturn)
# define pD "t"
#endif
+/* Convenience macro for rarely-used functions that do not return. */
+#define AVOID _Noreturn ATTRIBUTE_COLD void
+
/* Extra internal type checking? */
/* Define Emacs versions of <assert.h>'s 'assert (COND)' and <verify.h>'s
# define eassume(cond) assume (cond)
#else /* ENABLE_CHECKING */
-extern _Noreturn void die (const char *, const char *, int);
+extern AVOID die (const char *, const char *, int);
extern bool suppress_checking EXTERNALLY_VISIBLE;
extern void char_table_set (Lisp_Object, int, Lisp_Object);
/* Defined in data.c. */
-extern _Noreturn void wrong_type_argument (Lisp_Object, Lisp_Object);
+extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
/* Defined in emacs.c. */
}
/* Defined in data.c. */
-extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object);
+extern AVOID wrong_choice (Lisp_Object, Lisp_Object);
extern void notify_variable_watchers (Lisp_Object, Lisp_Object,
Lisp_Object, Lisp_Object);
extern Lisp_Object indirect_function (Lisp_Object);
extern uintmax_t cons_to_unsigned (Lisp_Object, uintmax_t);
extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
-extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object);
-extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object,
- Lisp_Object);
-extern _Noreturn void circular_list (Lisp_Object);
+extern AVOID args_out_of_range (Lisp_Object, Lisp_Object);
+extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern AVOID circular_list (Lisp_Object);
extern Lisp_Object do_symval_forwarding (lispfwd);
enum Set_Internal_Bind {
SET_INTERNAL_SET,
/* Defined in insdel.c. */
extern void move_gap_both (ptrdiff_t, ptrdiff_t);
-extern _Noreturn void buffer_overflow (void);
+extern AVOID buffer_overflow (void);
extern void make_gap (ptrdiff_t);
extern void make_gap_1 (struct buffer *, ptrdiff_t);
extern ptrdiff_t copy_text (const unsigned char *, unsigned char *,
extern void check_pure_size (void);
extern void allocate_string_data (struct Lisp_String *, EMACS_INT, EMACS_INT);
extern void malloc_warning (const char *);
-extern _Noreturn void memory_full (size_t);
-extern _Noreturn void buffer_memory_full (ptrdiff_t);
+extern AVOID memory_full (size_t);
+extern AVOID buffer_memory_full (ptrdiff_t);
extern bool survives_gc_p (Lisp_Object);
extern void mark_object (Lisp_Object);
#if defined REL_ALLOC && !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
extern Lisp_Object make_uninit_bool_vector (EMACS_INT);
extern Lisp_Object bool_vector_fill (Lisp_Object, Lisp_Object);
-extern _Noreturn void string_overflow (void);
+extern AVOID string_overflow (void);
extern Lisp_Object make_string (const char *, ptrdiff_t);
extern Lisp_Object make_formatted_string (char *, const char *, ...)
ATTRIBUTE_FORMAT_PRINTF (2, 3);
Lisp_Object (*funcall)
(ptrdiff_t nargs, Lisp_Object *args));
extern Lisp_Object quit (void);
-INLINE _Noreturn void
+INLINE AVOID
xsignal (Lisp_Object error_symbol, Lisp_Object data)
{
Fsignal (error_symbol, data);
}
-extern _Noreturn void xsignal0 (Lisp_Object);
-extern _Noreturn void xsignal1 (Lisp_Object, Lisp_Object);
-extern _Noreturn void xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object);
-extern _Noreturn void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object);
-extern _Noreturn void signal_error (const char *, Lisp_Object);
-extern _Noreturn void overflow_error (void);
+extern AVOID xsignal0 (Lisp_Object);
+extern AVOID xsignal1 (Lisp_Object, Lisp_Object);
+extern AVOID xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern AVOID xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
+extern AVOID signal_error (const char *, Lisp_Object);
+extern AVOID overflow_error (void);
extern bool FUNCTIONP (Lisp_Object);
extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector);
extern Lisp_Object eval_sub (Lisp_Object form);
extern Lisp_Object unbind_to (ptrdiff_t, Lisp_Object);
extern void rebind_for_thread_switch (void);
extern void unbind_for_thread_switch (struct thread_state *);
-extern _Noreturn void error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
-extern _Noreturn void verror (const char *, va_list)
+extern AVOID error (const char *, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
+extern AVOID verror (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
extern Lisp_Object vformat_string (const char *, va_list)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
/* Defined in buffer.c. */
extern bool mouse_face_overlay_overlaps (Lisp_Object);
extern Lisp_Object disable_line_numbers_overlay_at_eob (void);
-extern _Noreturn void nsberror (Lisp_Object);
+extern AVOID nsberror (Lisp_Object);
extern void adjust_overlays_for_insert (ptrdiff_t, ptrdiff_t);
extern void adjust_overlays_for_delete (ptrdiff_t, ptrdiff_t);
extern void fix_start_end_in_overlays (ptrdiff_t, ptrdiff_t);
extern void fclose_unwind (void *);
extern void restore_point_unwind (Lisp_Object);
extern Lisp_Object get_file_errno_data (const char *, Lisp_Object, int);
-extern _Noreturn void report_file_errno (const char *, Lisp_Object, int);
-extern _Noreturn void report_file_error (const char *, Lisp_Object);
-extern _Noreturn void report_file_notify_error (const char *, Lisp_Object);
+extern AVOID report_file_errno (const char *, Lisp_Object, int);
+extern AVOID report_file_error (const char *, Lisp_Object);
+extern AVOID report_file_notify_error (const char *, Lisp_Object);
extern bool internal_delete_file (Lisp_Object);
extern Lisp_Object emacs_readlinkat (int, const char *);
extern bool file_directory_p (Lisp_Object);
#endif
extern Lisp_Object decode_env_path (const char *, const char *, bool);
extern Lisp_Object empty_unibyte_string, empty_multibyte_string;
-extern _Noreturn void terminate_due_to_signal (int, int);
+extern AVOID terminate_due_to_signal (int, int);
#ifdef WINDOWSNT
extern Lisp_Object Vlibrary_cache;
#endif
extern void seed_random (void *, ptrdiff_t);
extern void init_random (void);
extern void emacs_backtrace (int);
-extern _Noreturn void emacs_abort (void) NO_INLINE;
+extern AVOID emacs_abort (void) NO_INLINE;
extern int emacs_open (const char *, int, int);
extern int emacs_pipe (int[2]);
extern int emacs_close (int);
/* Defined in term.c. */
extern int *char_ins_del_vector;
extern void syms_of_term (void);
-extern _Noreturn void fatal (const char *msgid, ...)
- ATTRIBUTE_FORMAT_PRINTF (1, 2);
+extern AVOID fatal (const char *msgid, ...) ATTRIBUTE_FORMAT_PRINTF (1, 2);
/* Defined in terminal.c. */
extern void syms_of_terminal (void);
return Qnil;
}
-static _Noreturn void
+static AVOID
load_error_old_style_backquotes (void)
{
if (NILP (Vload_file_name))
/* Signal an `end-of-file' error, if possible with file name
information. */
-static _Noreturn void
+static AVOID
end_of_file_error (void)
{
if (STRINGP (Vload_file_name))
/* Signal Qinvalid_read_syntax error.
S is error string of length N (if > 0) */
-static _Noreturn void
+static AVOID
invalid_syntax (const char *s)
{
xsignal1 (Qinvalid_read_syntax, build_string (s));
enum cold_op op,
Lisp_Object arg);
-_Noreturn
-static void
+static AVOID
error_unsupported_dump_object (struct dump_context *ctx,
Lisp_Object object,
const char *msg)
#define PURESIZE (BASE_PURESIZE * PURESIZE_RATIO * PURESIZE_CHECKING_RATIO)
#endif
-extern _Noreturn void pure_write_error (Lisp_Object);
+extern AVOID pure_write_error (Lisp_Object);
extern EMACS_INT pure[];
Lisp_Object re_match_object;
-static _Noreturn void
+static AVOID
matcher_overflow (void)
{
error ("Stack overflow in regexp matcher");
#ifndef WINDOWSNT
/* Like perror, but signals an error. */
-static _Noreturn void
+static AVOID
sound_perror (const char *msg)
{
int saved_errno = errno;
#define DEFAULT_ALSA_SOUND_DEVICE "default"
#endif
-static _Noreturn void
+static AVOID
alsa_sound_perror (const char *msg, int err)
{
error ("%s: %s", msg, snd_strerror (err));
deliver_thread_signal (sig, handle_fatal_signal);
}
-static _Noreturn void
+static AVOID
handle_arith_signal (int sig)
{
pthread_sigmask (SIG_SETMASK, &empty_mask, 0);
extern bool list4_to_timespec (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, struct timespec *);
extern struct timespec lisp_time_argument (Lisp_Object);
-extern _Noreturn void time_overflow (void);
+extern AVOID time_overflow (void);
extern void init_timefns (void);
extern void syms_of_timefns (void);
static void set_tty_hooks (struct terminal *terminal);
static void dissociate_if_controlling_tty (int fd);
static void delete_tty (struct terminal *);
-static _Noreturn void maybe_fatal (bool, struct terminal *,
- const char *, const char *, ...)
+static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *,
+ ...)
ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
-static _Noreturn void vfatal (const char *str, va_list ap)
- ATTRIBUTE_FORMAT_PRINTF (1, 0);
+static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
#define OUTPUT(tty, a) \
/* Signal a `text-read-only' error. This function makes it easier
to capture that error in GDB by putting a breakpoint on it. */
-static _Noreturn void
+static AVOID
text_read_only (Lisp_Object propval)
{
if (STRINGP (propval))
return tm;
}
-static _Noreturn void
+static AVOID
invalid_time_zone_specification (Lisp_Object zone)
{
xsignal2 (Qerror, build_string ("Invalid time zone specification"), zone);
error ("Specified time is not representable");
}
-static _Noreturn void
+static AVOID
time_error (int err)
{
switch (err)
}
}
-static _Noreturn void
+static AVOID
invalid_hz (Lisp_Object hz)
{
xsignal2 (Qerror, build_string ("Invalid time frequency"), hz);
Glyph display
***********************************************************************/
-
-
-static void x_set_glyph_string_clipping (struct glyph_string *);
-static void x_set_glyph_string_gc (struct glyph_string *);
-static void x_draw_glyph_string_foreground (struct glyph_string *);
-static void x_draw_composite_glyph_string_foreground (struct glyph_string *);
-static void x_draw_glyph_string_box (struct glyph_string *);
-static void x_draw_glyph_string (struct glyph_string *);
-static _Noreturn void x_delete_glyphs (struct frame *, int);
-static void x_compute_glyph_string_overhangs (struct glyph_string *);
-static void x_set_cursor_gc (struct glyph_string *);
-static void x_set_mode_line_face_gc (struct glyph_string *);
-static void x_set_mouse_face_gc (struct glyph_string *);
static bool x_alloc_lighter_color (struct frame *, Display *, Colormap,
unsigned long *, double, int);
-static void x_setup_relief_color (struct frame *, struct relief *,
- double, int, unsigned long);
-static void x_setup_relief_colors (struct glyph_string *);
-static void x_draw_image_glyph_string (struct glyph_string *);
-static void x_draw_image_relief (struct glyph_string *);
-static void x_draw_image_foreground (struct glyph_string *);
-#ifndef USE_CAIRO
-static void x_draw_image_foreground_1 (struct glyph_string *, Pixmap);
-#endif
-static void x_clear_glyph_string_rect (struct glyph_string *, int,
- int, int, int);
-static void x_draw_relief_rect (struct frame *, int, int, int, int,
- int, bool, bool, bool, bool, bool,
- XRectangle *);
-static void x_draw_box_rect (struct glyph_string *, int, int, int, int,
- int, bool, bool, XRectangle *);
static void x_scroll_bar_clear (struct frame *);
#ifdef GLYPH_DEBUG
for X frames. */
static void
-x_delete_glyphs (struct frame *f, register int n)
+x_delete_glyphs (struct frame *f, int n)
{
emacs_abort ();
}
/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
the text of an error message that lead to the connection loss. */
-static _Noreturn void
+static AVOID
x_connection_closed (Display *dpy, const char *error_message, bool ioerror)
{
struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
It kills all frames on the display that we lost touch with.
If that was the only one, it prints an error message and kills Emacs. */
-static _Noreturn int
+static _Noreturn ATTRIBUTE_COLD int
x_io_error_quitter (Display *display)
{
char buf[256];