diff options
| author | Paul Eggert | 2017-10-04 14:29:58 -0700 |
|---|---|---|
| committer | Paul Eggert | 2017-10-04 14:45:08 -0700 |
| commit | 3db388b0bf83d3138562f09ce25fab8ba89bcc81 (patch) | |
| tree | ff86fa2e529cdd9187a12e88d193b4416d60c26e /src | |
| parent | 4e0b67ed27114fa2cbebca32567089fd8fa78425 (diff) | |
| download | emacs-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.c | 4 | ||||
| -rw-r--r-- | src/dbusbind.c | 3 | ||||
| -rw-r--r-- | src/editfns.c | 28 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/xdisp.c | 4 |
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 * | |||
| 237 | XD_OBJECT_TO_STRING (Lisp_Object object) | 237 | XD_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, | |||
| 74 | static long int tm_gmtoff (struct tm *); | 74 | static long int tm_gmtoff (struct tm *); |
| 75 | static int tm_diff (struct tm *, struct tm *); | 75 | static int tm_diff (struct tm *, struct tm *); |
| 76 | static void update_buffer_properties (ptrdiff_t, ptrdiff_t); | 76 | static void update_buffer_properties (ptrdiff_t, ptrdiff_t); |
| 77 | static 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. | |||
| 4140 | usage: (format STRING &rest OBJECTS) */) | 4141 | usage: (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 | ||
| 4146 | DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0, | 4147 | DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0, |
| @@ -4156,16 +4157,13 @@ and right quote replacement characters are specified by | |||
| 4156 | usage: (format-message STRING &rest OBJECTS) */) | 4157 | usage: (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 | ||
| 4166 | Lisp_Object | 4165 | static Lisp_Object |
| 4167 | styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message, | 4166 | styled_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); | |||
| 3970 | extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); | 3970 | extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); |
| 3971 | extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, | 3971 | extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, |
| 3972 | ptrdiff_t, bool); | 3972 | ptrdiff_t, bool); |
| 3973 | extern Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool, bool); | ||
| 3974 | extern void init_editfns (bool); | 3973 | extern void init_editfns (bool); |
| 3975 | extern void syms_of_editfns (void); | 3974 | extern 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, "", | |||
| 19525 | usage: (trace-to-stderr STRING &rest OBJECTS) */) | 19525 | usage: (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 | } |