aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-09-26 16:31:57 -0700
committerPaul Eggert2017-09-26 16:36:43 -0700
commit0e82fa34163dba21121e3a9cffa7f896c81c4d93 (patch)
tree16c728aa616dae256d429060e257313dcfe4dbde /src
parent98a37e60142340b9c2b4e6b17c373f4ae6a2d8b4 (diff)
downloademacs-0e82fa34163dba21121e3a9cffa7f896c81c4d93.tar.gz
emacs-0e82fa34163dba21121e3a9cffa7f896c81c4d93.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/callint.c7
-rw-r--r--src/dbusbind.c3
-rw-r--r--src/editfns.c47
-rw-r--r--src/lisp.h1
-rw-r--r--src/xdisp.c4
5 files changed, 44 insertions, 18 deletions
diff --git a/src/callint.c b/src/callint.c
index 105ec071d07..469205cc380 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 `Fformat_message' it will be understandable to a human. */ 275 pass it to styled_format 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,10 +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 if (strchr (SSDATA (visargs[1]), '%')) 505 callint_message = styled_format (i - 1, visargs + 1, true, false);
506 callint_message = Fformat_message (i - 1, visargs + 1);
507 else
508 callint_message = visargs[1];
509 506
510 switch (*tem) 507 switch (*tem)
511 { 508 {
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 4a7068416fe..789aa008611 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -237,7 +237,8 @@ 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 return SSDATA (CALLN (Fformat, format, object)); 240 Lisp_Object args[] = { format, object };
241 return SSDATA (styled_format (ARRAYELTS (args), args, false, false));
241} 242}
242 243
243#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \ 244#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
diff --git a/src/editfns.c b/src/editfns.c
index 2f8b075817a..ef0374199cc 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -74,7 +74,6 @@ 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);
78 77
79#ifndef HAVE_TM_GMTOFF 78#ifndef HAVE_TM_GMTOFF
80# define HAVE_TM_GMTOFF false 79# define HAVE_TM_GMTOFF false
@@ -3959,7 +3958,7 @@ usage: (message FORMAT-STRING &rest ARGS) */)
3959 } 3958 }
3960 else 3959 else
3961 { 3960 {
3962 Lisp_Object val = Fformat_message (nargs, args); 3961 Lisp_Object val = styled_format (nargs, args, true, false);
3963 message3 (val); 3962 message3 (val);
3964 return val; 3963 return val;
3965 } 3964 }
@@ -3985,7 +3984,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */)
3985 } 3984 }
3986 else 3985 else
3987 { 3986 {
3988 Lisp_Object val = Fformat_message (nargs, args); 3987 Lisp_Object val = styled_format (nargs, args, true, false);
3989 Lisp_Object pane, menu; 3988 Lisp_Object pane, menu;
3990 3989
3991 pane = list1 (Fcons (build_string ("OK"), Qt)); 3990 pane = list1 (Fcons (build_string ("OK"), Qt));
@@ -4141,7 +4140,7 @@ produced text.
4141usage: (format STRING &rest OBJECTS) */) 4140usage: (format STRING &rest OBJECTS) */)
4142 (ptrdiff_t nargs, Lisp_Object *args) 4141 (ptrdiff_t nargs, Lisp_Object *args)
4143{ 4142{
4144 return styled_format (nargs, args, false); 4143 return styled_format (nargs, args, false, true);
4145} 4144}
4146 4145
4147DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0, 4146DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0,
@@ -4157,13 +4156,16 @@ and right quote replacement characters are specified by
4157usage: (format-message STRING &rest OBJECTS) */) 4156usage: (format-message STRING &rest OBJECTS) */)
4158 (ptrdiff_t nargs, Lisp_Object *args) 4157 (ptrdiff_t nargs, Lisp_Object *args)
4159{ 4158{
4160 return styled_format (nargs, args, true); 4159 return styled_format (nargs, args, true, true);
4161} 4160}
4162 4161
4163/* Implement ‘format-message’ if MESSAGE is true, ‘format’ otherwise. */ 4162/* 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. */
4164 4165
4165static Lisp_Object 4166Lisp_Object
4166styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) 4167styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message,
4168 bool new_result)
4167{ 4169{
4168 ptrdiff_t n; /* The number of the next arg to substitute. */ 4170 ptrdiff_t n; /* The number of the next arg to substitute. */
4169 char initial_buffer[4000]; 4171 char initial_buffer[4000];
@@ -4193,6 +4195,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4193 /* The start and end bytepos in the output string. */ 4195 /* The start and end bytepos in the output string. */
4194 ptrdiff_t start, end; 4196 ptrdiff_t start, end;
4195 4197
4198 /* Whether the argument is a newly created string. */
4199 bool_bf new_string : 1;
4200
4196 /* Whether the argument is a string with intervals. */ 4201 /* Whether the argument is a string with intervals. */
4197 bool_bf intervals : 1; 4202 bool_bf intervals : 1;
4198 } *info; 4203 } *info;
@@ -4342,7 +4347,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4342 memset (&discarded[format0 - format_start], 1, 4347 memset (&discarded[format0 - format_start], 1,
4343 format - format0 - (conversion == '%')); 4348 format - format0 - (conversion == '%'));
4344 if (conversion == '%') 4349 if (conversion == '%')
4345 goto copy_char; 4350 {
4351 new_result = true;
4352 goto copy_char;
4353 }
4346 4354
4347 ++n; 4355 ++n;
4348 if (! (n < nargs)) 4356 if (! (n < nargs))
@@ -4352,6 +4360,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4352 if (nspec < ispec) 4360 if (nspec < ispec)
4353 { 4361 {
4354 spec->argument = args[n]; 4362 spec->argument = args[n];
4363 spec->new_string = false;
4355 spec->intervals = false; 4364 spec->intervals = false;
4356 nspec = ispec; 4365 nspec = ispec;
4357 } 4366 }
@@ -4369,11 +4378,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4369 { 4378 {
4370 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; 4379 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
4371 spec->argument = arg = Fprin1_to_string (arg, noescape); 4380 spec->argument = arg = Fprin1_to_string (arg, noescape);
4381 spec->new_string = true;
4372 if (STRING_MULTIBYTE (arg) && ! multibyte) 4382 if (STRING_MULTIBYTE (arg) && ! multibyte)
4373 { 4383 {
4374 multibyte = true; 4384 multibyte = true;
4375 goto retry; 4385 goto retry;
4376 } 4386 }
4387 new_result = false;
4377 } 4388 }
4378 conversion = 's'; 4389 conversion = 's';
4379 } 4390 }
@@ -4387,6 +4398,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4387 goto retry; 4398 goto retry;
4388 } 4399 }
4389 spec->argument = arg = Fchar_to_string (arg); 4400 spec->argument = arg = Fchar_to_string (arg);
4401 spec->new_string = true;
4390 } 4402 }
4391 4403
4392 if (!EQ (arg, args[n])) 4404 if (!EQ (arg, args[n]))
@@ -4409,6 +4421,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4409 4421
4410 if (conversion == 's') 4422 if (conversion == 's')
4411 { 4423 {
4424 if (format == end && format - format_start == 2
4425 && (!new_result || spec->new_string)
4426 && ! string_intervals (args[0]))
4427 return arg;
4428
4412 /* handle case (precision[n] >= 0) */ 4429 /* handle case (precision[n] >= 0) */
4413 4430
4414 ptrdiff_t prec = -1; 4431 ptrdiff_t prec = -1;
@@ -4487,6 +4504,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4487 if (string_intervals (arg)) 4504 if (string_intervals (arg))
4488 spec->intervals = arg_intervals = true; 4505 spec->intervals = arg_intervals = true;
4489 4506
4507 new_result = true;
4490 continue; 4508 continue;
4491 } 4509 }
4492 } 4510 }
@@ -4754,6 +4772,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4754 } 4772 }
4755 spec->end = nchars; 4773 spec->end = nchars;
4756 4774
4775 new_result = true;
4757 continue; 4776 continue;
4758 } 4777 }
4759 } 4778 }
@@ -4772,9 +4791,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4772 } 4791 }
4773 convsrc = format_char == '`' ? uLSQM : uRSQM; 4792 convsrc = format_char == '`' ? uLSQM : uRSQM;
4774 convbytes = 3; 4793 convbytes = 3;
4794 new_result = true;
4775 } 4795 }
4776 else if (format_char == '`' && quoting_style == STRAIGHT_QUOTING_STYLE) 4796 else if (format_char == '`' && quoting_style == STRAIGHT_QUOTING_STYLE)
4777 convsrc = "'"; 4797 {
4798 convsrc = "'";
4799 new_result = true;
4800 }
4778 else 4801 else
4779 { 4802 {
4780 /* Copy a single character from format to buf. */ 4803 /* Copy a single character from format to buf. */
@@ -4798,6 +4821,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4798 int c = BYTE8_TO_CHAR (format_char); 4821 int c = BYTE8_TO_CHAR (format_char);
4799 convbytes = CHAR_STRING (c, str); 4822 convbytes = CHAR_STRING (c, str);
4800 convsrc = (char *) str; 4823 convsrc = (char *) str;
4824 new_result = true;
4801 } 4825 }
4802 } 4826 }
4803 4827
@@ -4844,6 +4868,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4844 if (bufsize < p - buf) 4868 if (bufsize < p - buf)
4845 emacs_abort (); 4869 emacs_abort ();
4846 4870
4871 if (! new_result)
4872 return args[0];
4873
4847 if (maybe_combine_byte) 4874 if (maybe_combine_byte)
4848 nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf); 4875 nchars = multibyte_chars_in_text ((unsigned char *) buf, p - buf);
4849 Lisp_Object val = make_specified_string (buf, nchars, p - buf, multibyte); 4876 Lisp_Object val = make_specified_string (buf, nchars, p - buf, multibyte);
diff --git a/src/lisp.h b/src/lisp.h
index c5030824427..0c3ca3ae06b 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3969,6 +3969,7 @@ extern _Noreturn void time_overflow (void);
3969extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool); 3969extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
3970extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, 3970extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
3971 ptrdiff_t, bool); 3971 ptrdiff_t, bool);
3972extern Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool, bool);
3972extern void init_editfns (bool); 3973extern void init_editfns (bool);
3973extern void syms_of_editfns (void); 3974extern void syms_of_editfns (void);
3974 3975
diff --git a/src/xdisp.c b/src/xdisp.c
index 141275f15a0..86164eb9f6f 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 = Fformat_message (nargs, args); 10197 msg = styled_format (nargs, args, true, false);
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 = Fformat (nargs, args); 19528 Lisp_Object s = styled_format (nargs, args, false, false);
19529 fwrite (SDATA (s), 1, SBYTES (s), stderr); 19529 fwrite (SDATA (s), 1, SBYTES (s), stderr);
19530 return Qnil; 19530 return Qnil;
19531} 19531}