mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-19 14:41:11 -08:00
Avoid some unnecessary copying in Fformat etc.
This patch is just for performance; it should not affect behavior. On my platform, it made the microbenchmark (format "%S" load-path) run about 45% faster. It should also speed up calls like (message "%s" STRING). * src/callint.c (Fcall_interactively): * src/dbusbind.c (XD_OBJECT_TO_STRING): * src/editfns.c (Fmessage, Fmessage_box): * src/xdisp.c (vadd_to_log, Ftrace_to_stderr): Use styled_format instead of Fformat or Fformat_message, to avoid unnecessary copying. * src/editfns.c (styled_format): New arg NEW_RESULT. All uses changed. Reuse an input string if it has the right value and if !NEW_RESULT. * src/lisp.h (style_format): New decl.
This commit is contained in:
parent
98a37e6014
commit
0e82fa3416
5 changed files with 44 additions and 18 deletions
|
|
@ -272,7 +272,7 @@ invoke it. If KEYS is omitted or nil, the return value of
|
|||
{
|
||||
/* `args' will contain the array of arguments to pass to the function.
|
||||
`visargs' will contain the same list but in a nicer form, so that if we
|
||||
pass it to `Fformat_message' it will be understandable to a human. */
|
||||
pass it to styled_format it will be understandable to a human. */
|
||||
Lisp_Object *args, *visargs;
|
||||
Lisp_Object specs;
|
||||
Lisp_Object filter_specs;
|
||||
|
|
@ -502,10 +502,7 @@ invoke it. If KEYS is omitted or nil, the return value of
|
|||
for (i = 2; *tem; i++)
|
||||
{
|
||||
visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n"));
|
||||
if (strchr (SSDATA (visargs[1]), '%'))
|
||||
callint_message = Fformat_message (i - 1, visargs + 1);
|
||||
else
|
||||
callint_message = visargs[1];
|
||||
callint_message = styled_format (i - 1, visargs + 1, true, false);
|
||||
|
||||
switch (*tem)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -237,7 +237,8 @@ static char *
|
|||
XD_OBJECT_TO_STRING (Lisp_Object object)
|
||||
{
|
||||
AUTO_STRING (format, "%s");
|
||||
return SSDATA (CALLN (Fformat, format, object));
|
||||
Lisp_Object args[] = { format, object };
|
||||
return SSDATA (styled_format (ARRAYELTS (args), args, false, false));
|
||||
}
|
||||
|
||||
#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
|
|||
static long int tm_gmtoff (struct tm *);
|
||||
static int tm_diff (struct tm *, struct tm *);
|
||||
static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
|
||||
static Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool);
|
||||
|
||||
#ifndef HAVE_TM_GMTOFF
|
||||
# define HAVE_TM_GMTOFF false
|
||||
|
|
@ -3959,7 +3958,7 @@ usage: (message FORMAT-STRING &rest ARGS) */)
|
|||
}
|
||||
else
|
||||
{
|
||||
Lisp_Object val = Fformat_message (nargs, args);
|
||||
Lisp_Object val = styled_format (nargs, args, true, false);
|
||||
message3 (val);
|
||||
return val;
|
||||
}
|
||||
|
|
@ -3985,7 +3984,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
|
|||
}
|
||||
else
|
||||
{
|
||||
Lisp_Object val = Fformat_message (nargs, args);
|
||||
Lisp_Object val = styled_format (nargs, args, true, false);
|
||||
Lisp_Object pane, menu;
|
||||
|
||||
pane = list1 (Fcons (build_string ("OK"), Qt));
|
||||
|
|
@ -4141,7 +4140,7 @@ produced text.
|
|||
usage: (format STRING &rest OBJECTS) */)
|
||||
(ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
return styled_format (nargs, args, false);
|
||||
return styled_format (nargs, args, false, true);
|
||||
}
|
||||
|
||||
DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0,
|
||||
|
|
@ -4157,13 +4156,16 @@ and right quote replacement characters are specified by
|
|||
usage: (format-message STRING &rest OBJECTS) */)
|
||||
(ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
return styled_format (nargs, args, true);
|
||||
return styled_format (nargs, args, true, true);
|
||||
}
|
||||
|
||||
/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise. */
|
||||
/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise.
|
||||
If NEW_RESULT, the result is a new string; otherwise, the result
|
||||
may be one of the arguments. */
|
||||
|
||||
static Lisp_Object
|
||||
styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
||||
Lisp_Object
|
||||
styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
|
||||
bool new_result)
|
||||
{
|
||||
ptrdiff_t n; /* The number of the next arg to substitute. */
|
||||
char initial_buffer[4000];
|
||||
|
|
@ -4193,6 +4195,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
/* The start and end bytepos in the output string. */
|
||||
ptrdiff_t start, end;
|
||||
|
||||
/* Whether the argument is a newly created string. */
|
||||
bool_bf new_string : 1;
|
||||
|
||||
/* Whether the argument is a string with intervals. */
|
||||
bool_bf intervals : 1;
|
||||
} *info;
|
||||
|
|
@ -4342,7 +4347,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
memset (&discarded[format0 - format_start], 1,
|
||||
format - format0 - (conversion == '%'));
|
||||
if (conversion == '%')
|
||||
goto copy_char;
|
||||
{
|
||||
new_result = true;
|
||||
goto copy_char;
|
||||
}
|
||||
|
||||
++n;
|
||||
if (! (n < nargs))
|
||||
|
|
@ -4352,6 +4360,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
if (nspec < ispec)
|
||||
{
|
||||
spec->argument = args[n];
|
||||
spec->new_string = false;
|
||||
spec->intervals = false;
|
||||
nspec = ispec;
|
||||
}
|
||||
|
|
@ -4369,11 +4378,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
{
|
||||
Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
|
||||
spec->argument = arg = Fprin1_to_string (arg, noescape);
|
||||
spec->new_string = true;
|
||||
if (STRING_MULTIBYTE (arg) && ! multibyte)
|
||||
{
|
||||
multibyte = true;
|
||||
goto retry;
|
||||
}
|
||||
new_result = false;
|
||||
}
|
||||
conversion = 's';
|
||||
}
|
||||
|
|
@ -4387,6 +4398,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
goto retry;
|
||||
}
|
||||
spec->argument = arg = Fchar_to_string (arg);
|
||||
spec->new_string = true;
|
||||
}
|
||||
|
||||
if (!EQ (arg, args[n]))
|
||||
|
|
@ -4409,6 +4421,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
|
||||
if (conversion == 's')
|
||||
{
|
||||
if (format == end && format - format_start == 2
|
||||
&& (!new_result || spec->new_string)
|
||||
&& ! string_intervals (args[0]))
|
||||
return arg;
|
||||
|
||||
/* handle case (precision[n] >= 0) */
|
||||
|
||||
ptrdiff_t prec = -1;
|
||||
|
|
@ -4487,6 +4504,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
if (string_intervals (arg))
|
||||
spec->intervals = arg_intervals = true;
|
||||
|
||||
new_result = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -4754,6 +4772,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
}
|
||||
spec->end = nchars;
|
||||
|
||||
new_result = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -4772,9 +4791,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
}
|
||||
convsrc = format_char == '`' ? uLSQM : uRSQM;
|
||||
convbytes = 3;
|
||||
new_result = true;
|
||||
}
|
||||
else if (format_char == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
|
||||
convsrc = "'";
|
||||
{
|
||||
convsrc = "'";
|
||||
new_result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy a single character from format to buf. */
|
||||
|
|
@ -4798,6 +4821,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
int c = BYTE8_TO_CHAR (format_char);
|
||||
convbytes = CHAR_STRING (c, str);
|
||||
convsrc = (char *) str;
|
||||
new_result = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4844,6 +4868,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
|
|||
if (bufsize < p - buf)
|
||||
emacs_abort ();
|
||||
|
||||
if (! new_result)
|
||||
return args[0];
|
||||
|
||||
if (maybe_combine_byte)
|
||||
nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
|
||||
Lisp_Object val = make_specified_string (buf, nchars, p - buf, multibyte);
|
||||
|
|
|
|||
|
|
@ -3969,6 +3969,7 @@ extern _Noreturn void time_overflow (void);
|
|||
extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
|
||||
extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||
ptrdiff_t, bool);
|
||||
extern Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool, bool);
|
||||
extern void init_editfns (bool);
|
||||
extern void syms_of_editfns (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -10194,7 +10194,7 @@ vadd_to_log (char const *format, va_list ap)
|
|||
for (ptrdiff_t i = 1; i <= nargs; i++)
|
||||
args[i] = va_arg (ap, Lisp_Object);
|
||||
Lisp_Object msg = Qnil;
|
||||
msg = Fformat_message (nargs, args);
|
||||
msg = styled_format (nargs, args, true, false);
|
||||
|
||||
ptrdiff_t len = SBYTES (msg) + 1;
|
||||
USE_SAFE_ALLOCA;
|
||||
|
|
@ -19525,7 +19525,7 @@ DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
|
|||
usage: (trace-to-stderr STRING &rest OBJECTS) */)
|
||||
(ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
Lisp_Object s = Fformat (nargs, args);
|
||||
Lisp_Object s = styled_format (nargs, args, false, false);
|
||||
fwrite (SDATA (s), 1, SBYTES (s), stderr);
|
||||
return Qnil;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue