aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-10-04 14:29:58 -0700
committerPaul Eggert2017-10-04 14:45:08 -0700
commit3db388b0bf83d3138562f09ce25fab8ba89bcc81 (patch)
treeff86fa2e529cdd9187a12e88d193b4416d60c26e /src
parent4e0b67ed27114fa2cbebca32567089fd8fa78425 (diff)
downloademacs-3db388b0bf83d3138562f09ce25fab8ba89bcc81.tar.gz
emacs-3db388b0bf83d3138562f09ce25fab8ba89bcc81.zip
Speed up (format "%s" STRING) and the like
Although the Lisp manual said that ‘format’ returns a newly-allocated string, this was not true for a few cases like (format "%s" ""), and fixing the documentation to allow reuse of arguments lets us improve performance in common cases like (format "foo") and (format "%s" "foo") (Bug#28625). * doc/lispref/strings.texi (Formatting Strings): * etc/NEWS: Say that the result of ‘format’ might not be newly allocated. * 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): Just use Fformat or Fformat_message, as that’s simpler and no longer makes unnecessary copies. * src/editfns.c (styled_format): Remove last argument, as it is no longer needed: all callers now want it to behave as if it were true. All remaining callers changed. Make this function static again. Simplify the function now that we no longer need to worry about whether the optimization is allowed.
Diffstat (limited to 'src')
-rw-r--r--src/callint.c4
-rw-r--r--src/dbusbind.c3
-rw-r--r--src/editfns.c28
-rw-r--r--src/lisp.h1
-rw-r--r--src/xdisp.c4
5 files changed, 16 insertions, 24 deletions
diff --git a/src/callint.c b/src/callint.c
index 469205cc380..5d88082e38d 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -272,7 +272,7 @@ invoke it. If KEYS is omitted or nil, the return value of
272{ 272{
273 /* `args' will contain the array of arguments to pass to the function. 273 /* `args' will contain the array of arguments to pass to the function.
274 `visargs' will contain the same list but in a nicer form, so that if we 274 `visargs' will contain the same list but in a nicer form, so that if we
275 pass it to styled_format it will be understandable to a human. */ 275 pass it to Fformat_message it will be understandable to a human. */
276 Lisp_Object *args, *visargs; 276 Lisp_Object *args, *visargs;
277 Lisp_Object specs; 277 Lisp_Object specs;
278 Lisp_Object filter_specs; 278 Lisp_Object filter_specs;
@@ -502,7 +502,7 @@ invoke it. If KEYS is omitted or nil, the return value of
502 for (i = 2; *tem; i++) 502 for (i = 2; *tem; i++)
503 { 503 {
504 visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n")); 504 visargs[1] = make_string (tem + 1, strcspn (tem + 1, "\n"));
505 callint_message = styled_format (i - 1, visargs + 1, true, false); 505 callint_message = Fformat_message (i - 1, visargs + 1);
506 506
507 switch (*tem) 507 switch (*tem)
508 { 508 {
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 789aa008611..4a7068416fe 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -237,8 +237,7 @@ static char *
237XD_OBJECT_TO_STRING (Lisp_Object object) 237XD_OBJECT_TO_STRING (Lisp_Object object)
238{ 238{
239 AUTO_STRING (format, "%s"); 239 AUTO_STRING (format, "%s");
240 Lisp_Object args[] = { format, object }; 240 return SSDATA (CALLN (Fformat, format, object));
241 return SSDATA (styled_format (ARRAYELTS (args), args, false, false));
242} 241}
243 242
244#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \ 243#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
diff --git a/src/editfns.c b/src/editfns.c
index e326604467c..d88a913c667 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -74,6 +74,7 @@ static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
74static long int tm_gmtoff (struct tm *); 74static long int tm_gmtoff (struct tm *);
75static int tm_diff (struct tm *, struct tm *); 75static int tm_diff (struct tm *, struct tm *);
76static void update_buffer_properties (ptrdiff_t, ptrdiff_t); 76static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
77static Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool);
77 78
78#ifndef HAVE_TM_GMTOFF 79#ifndef HAVE_TM_GMTOFF
79# define HAVE_TM_GMTOFF false 80# define HAVE_TM_GMTOFF false
@@ -3958,7 +3959,7 @@ usage: (message FORMAT-STRING &rest ARGS) */)
3958 } 3959 }
3959 else 3960 else
3960 { 3961 {
3961 Lisp_Object val = styled_format (nargs, args, true, false); 3962 Lisp_Object val = Fformat_message (nargs, args);
3962 message3 (val); 3963 message3 (val);
3963 return val; 3964 return val;
3964 } 3965 }
@@ -3984,7 +3985,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
3984 } 3985 }
3985 else 3986 else
3986 { 3987 {
3987 Lisp_Object val = styled_format (nargs, args, true, false); 3988 Lisp_Object val = Fformat_message (nargs, args);
3988 Lisp_Object pane, menu; 3989 Lisp_Object pane, menu;
3989 3990
3990 pane = list1 (Fcons (build_string ("OK"), Qt)); 3991 pane = list1 (Fcons (build_string ("OK"), Qt));
@@ -4140,7 +4141,7 @@ produced text.
4140usage: (format STRING &rest OBJECTS) */) 4141usage: (format STRING &rest OBJECTS) */)
4141 (ptrdiff_t nargs, Lisp_Object *args) 4142 (ptrdiff_t nargs, Lisp_Object *args)
4142{ 4143{
4143 return styled_format (nargs, args, false, true); 4144 return styled_format (nargs, args, false);
4144} 4145}
4145 4146
4146DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0, 4147DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0,
@@ -4156,16 +4157,13 @@ and right quote replacement characters are specified by
4156usage: (format-message STRING &rest OBJECTS) */) 4157usage: (format-message STRING &rest OBJECTS) */)
4157 (ptrdiff_t nargs, Lisp_Object *args) 4158 (ptrdiff_t nargs, Lisp_Object *args)
4158{ 4159{
4159 return styled_format (nargs, args, true, true); 4160 return styled_format (nargs, args, true);
4160} 4161}
4161 4162
4162/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise. 4163/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise. */
4163 If NEW_RESULT, the result is a new string; otherwise, the result
4164 may be one of the arguments. */
4165 4164
4166Lisp_Object 4165static Lisp_Object
4167styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message, 4166styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4168 bool new_result)
4169{ 4167{
4170 ptrdiff_t n; /* The number of the next arg to substitute. */ 4168 ptrdiff_t n; /* The number of the next arg to substitute. */
4171 char initial_buffer[4000]; 4169 char initial_buffer[4000];
@@ -4195,9 +4193,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4195 /* The start and end bytepos in the output string. */ 4193 /* The start and end bytepos in the output string. */
4196 ptrdiff_t start, end; 4194 ptrdiff_t start, end;
4197 4195
4198 /* Whether the argument is a newly created string. */
4199 bool_bf new_string : 1;
4200
4201 /* Whether the argument is a string with intervals. */ 4196 /* Whether the argument is a string with intervals. */
4202 bool_bf intervals : 1; 4197 bool_bf intervals : 1;
4203 } *info; 4198 } *info;
@@ -4241,6 +4236,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4241 ptrdiff_t ispec; 4236 ptrdiff_t ispec;
4242 ptrdiff_t nspec = 0; 4237 ptrdiff_t nspec = 0;
4243 4238
4239 /* True if a string needs to be allocated to hold the result. */
4240 bool new_result = false;
4241
4244 /* If we start out planning a unibyte result, 4242 /* If we start out planning a unibyte result,
4245 then discover it has to be multibyte, we jump back to retry. */ 4243 then discover it has to be multibyte, we jump back to retry. */
4246 retry: 4244 retry:
@@ -4360,7 +4358,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4360 if (nspec < ispec) 4358 if (nspec < ispec)
4361 { 4359 {
4362 spec->argument = args[n]; 4360 spec->argument = args[n];
4363 spec->new_string = false;
4364 spec->intervals = false; 4361 spec->intervals = false;
4365 nspec = ispec; 4362 nspec = ispec;
4366 } 4363 }
@@ -4378,7 +4375,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4378 { 4375 {
4379 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; 4376 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
4380 spec->argument = arg = Fprin1_to_string (arg, noescape); 4377 spec->argument = arg = Fprin1_to_string (arg, noescape);
4381 spec->new_string = true;
4382 if (STRING_MULTIBYTE (arg) && ! multibyte) 4378 if (STRING_MULTIBYTE (arg) && ! multibyte)
4383 { 4379 {
4384 multibyte = true; 4380 multibyte = true;
@@ -4397,7 +4393,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4397 goto retry; 4393 goto retry;
4398 } 4394 }
4399 spec->argument = arg = Fchar_to_string (arg); 4395 spec->argument = arg = Fchar_to_string (arg);
4400 spec->new_string = true;
4401 } 4396 }
4402 4397
4403 if (!EQ (arg, args[n])) 4398 if (!EQ (arg, args[n]))
@@ -4421,7 +4416,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4421 if (conversion == 's') 4416 if (conversion == 's')
4422 { 4417 {
4423 if (format == end && format - format_start == 2 4418 if (format == end && format - format_start == 2
4424 && (!new_result || spec->new_string)
4425 && ! string_intervals (args[0])) 4419 && ! string_intervals (args[0]))
4426 return arg; 4420 return arg;
4427 4421
diff --git a/src/lisp.h b/src/lisp.h
index bdb162aea4c..266370333f5 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3970,7 +3970,6 @@ extern _Noreturn void time_overflow (void);
3970extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); 3970extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
3971extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, 3971extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
3972 ptrdiff_t, bool); 3972 ptrdiff_t, bool);
3973extern Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool, bool);
3974extern void init_editfns (bool); 3973extern void init_editfns (bool);
3975extern void syms_of_editfns (void); 3974extern void syms_of_editfns (void);
3976 3975
diff --git a/src/xdisp.c b/src/xdisp.c
index 86164eb9f6f..141275f15a0 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -10194,7 +10194,7 @@ vadd_to_log (char const *format, va_list ap)
10194 for (ptrdiff_t i = 1; i <= nargs; i++) 10194 for (ptrdiff_t i = 1; i <= nargs; i++)
10195 args[i] = va_arg (ap, Lisp_Object); 10195 args[i] = va_arg (ap, Lisp_Object);
10196 Lisp_Object msg = Qnil; 10196 Lisp_Object msg = Qnil;
10197 msg = styled_format (nargs, args, true, false); 10197 msg = Fformat_message (nargs, args);
10198 10198
10199 ptrdiff_t len = SBYTES (msg) + 1; 10199 ptrdiff_t len = SBYTES (msg) + 1;
10200 USE_SAFE_ALLOCA; 10200 USE_SAFE_ALLOCA;
@@ -19525,7 +19525,7 @@ DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
19525usage: (trace-to-stderr STRING &rest OBJECTS) */) 19525usage: (trace-to-stderr STRING &rest OBJECTS) */)
19526 (ptrdiff_t nargs, Lisp_Object *args) 19526 (ptrdiff_t nargs, Lisp_Object *args)
19527{ 19527{
19528 Lisp_Object s = styled_format (nargs, args, false, false); 19528 Lisp_Object s = Fformat (nargs, args);
19529 fwrite (SDATA (s), 1, SBYTES (s), stderr); 19529 fwrite (SDATA (s), 1, SBYTES (s), stderr);
19530 return Qnil; 19530 return Qnil;
19531} 19531}