From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#28625: [PROPOSED] Speed up (format "%s" STRING) and the like Date: Wed, 27 Sep 2017 11:52:12 -0700 Message-ID: <20170927185212.1846-1-eggert@cs.ucla.edu> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1506538400 29343 195.159.176.226 (27 Sep 2017 18:53:20 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 27 Sep 2017 18:53:20 +0000 (UTC) Cc: Paul Eggert To: 28625@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Sep 27 20:53:14 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dxHSG-0006jN-BD for geb-bug-gnu-emacs@m.gmane.org; Wed, 27 Sep 2017 20:53:08 +0200 Original-Received: from localhost ([::1]:55957 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxHSN-0008Ij-JX for geb-bug-gnu-emacs@m.gmane.org; Wed, 27 Sep 2017 14:53:15 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:57951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxHSE-0008HX-LN for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:53:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dxHSA-0003wF-Op for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:53:06 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:54895) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dxHSA-0003w6-LK for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:53:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dxHSA-0007WA-CC for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:53:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 27 Sep 2017 18:53:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 28625 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.150653835928866 (code B ref -1); Wed, 27 Sep 2017 18:53:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 27 Sep 2017 18:52:39 +0000 Original-Received: from localhost ([127.0.0.1]:35343 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dxHRn-0007VV-0t for submit@debbugs.gnu.org; Wed, 27 Sep 2017 14:52:39 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:38558) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dxHRk-0007VH-D5 for submit@debbugs.gnu.org; Wed, 27 Sep 2017 14:52:37 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dxHRd-0003lP-GV for submit@debbugs.gnu.org; Wed, 27 Sep 2017 14:52:31 -0400 Original-Received: from lists.gnu.org ([2001:4830:134:3::11]:56286) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dxHRd-0003lE-Cl for submit@debbugs.gnu.org; Wed, 27 Sep 2017 14:52:29 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:57726) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dxHRb-0007qb-Jx for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:52:29 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dxHRX-0003iq-KU for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:52:27 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:60094) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dxHRX-0003iW-Av for bug-gnu-emacs@gnu.org; Wed, 27 Sep 2017 14:52:23 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 6DDEF160E2F for ; Wed, 27 Sep 2017 11:52:21 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id QJy69-SXcqlg; Wed, 27 Sep 2017 11:52:20 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 259BA160E31; Wed, 27 Sep 2017 11:52:20 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id SqdEMgEehpqx; Wed, 27 Sep 2017 11:52:20 -0700 (PDT) Original-Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id A84FE160E2E; Wed, 27 Sep 2017 11:52:19 -0700 (PDT) X-Mailer: git-send-email 2.13.5 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:137511 Archived-At: Although the Lisp manual said that =E2=80=98format=E2=80=99 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"). * doc/lispref/strings.texi (Formatting Strings): * etc/NEWS: Say that the result of =E2=80=98format=E2=80=99 might not be newly alloca= ted. * 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=E2=80=99s 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. --- doc/lispref/strings.texi | 10 +++++++--- etc/NEWS | 7 +++++++ src/callint.c | 4 ++-- src/dbusbind.c | 3 +-- src/editfns.c | 26 ++++++++++---------------- src/lisp.h | 1 - src/xdisp.c | 4 ++-- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 219225d412..5a56ed14a1 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -812,15 +812,19 @@ Formatting Strings in how they use the result of formatting. =20 @defun format string &rest objects -This function returns a new string that is made by copying -@var{string} and then replacing any format specification -in the copy with encodings of the corresponding @var{objects}. The +This function returns a string equal to @var{string}, replacing any form= at +specifications with encodings of the corresponding @var{objects}. The arguments @var{objects} are the computed values to be formatted. =20 The characters in @var{string}, other than the format specifications, are copied directly into the output, including their text properties, if any. Any text properties of the format specifications are copied to the produced string representations of the argument @var{objects}. + +The output string need not be newly-allocated. For example, if +@code{x} is the string @code{"foo"}, the expressions @code{(eq x +(format x))} and @code{(eq x (format "%s" x))} might both yield +@code{t}. @end defun =20 @defun format-message string &rest objects diff --git a/etc/NEWS b/etc/NEWS index 1b5ae658f6..48f34d0df7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1548,6 +1548,13 @@ Emacs integers with %e, %f, or %g conversions. Fo= r example, on these hosts (eql N (string-to-number (format "%.0f" N))) now returns t for all Emacs integers N. =20 ++++ +** 'format' is no longer documented to return a newly-allocated string. +This documentation was not correct, as (eq x (format x)) returned t +when x was the empty string. 'format' now takes advantage of the doc +change to avoid making copies of strings in common cases like (format +"foo") and (format "%s" "foo"). + --- ** Calls that accept floating-point integers (for use on hosts with limited integer range) now signal an error if arguments are not diff --git a/src/callint.c b/src/callint.c index 469205cc38..5d88082e38 100644 --- a/src/callint.c +++ b/src/callint.c @@ -272,7 +272,7 @@ invoke it. If KEYS is omitted or nil, the return val= ue 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 i= f we - pass it to styled_format it will be understandable to a human. */ + pass it to Fformat_message it will be understandable to a human. *= / Lisp_Object *args, *visargs; Lisp_Object specs; Lisp_Object filter_specs; @@ -502,7 +502,7 @@ invoke it. If KEYS is omitted or nil, the return val= ue of for (i =3D 2; *tem; i++) { visargs[1] =3D make_string (tem + 1, strcspn (tem + 1, "\n")); - callint_message =3D styled_format (i - 1, visargs + 1, true, false= ); + callint_message =3D Fformat_message (i - 1, visargs + 1); =20 switch (*tem) { diff --git a/src/dbusbind.c b/src/dbusbind.c index 789aa00861..4a7068416f 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -237,8 +237,7 @@ static char * XD_OBJECT_TO_STRING (Lisp_Object object) { AUTO_STRING (format, "%s"); - Lisp_Object args[] =3D { format, object }; - return SSDATA (styled_format (ARRAYELTS (args), args, false, false)); + return SSDATA (CALLN (Fformat, format, object)); } =20 #define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \ diff --git a/src/editfns.c b/src/editfns.c index e326604467..92c8f0f005 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -74,6 +74,7 @@ static Lisp_Object format_time_string (char const *, pt= rdiff_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); =20 #ifndef HAVE_TM_GMTOFF # define HAVE_TM_GMTOFF false @@ -3958,7 +3959,7 @@ usage: (message FORMAT-STRING &rest ARGS) */) } else { - Lisp_Object val =3D styled_format (nargs, args, true, false); + Lisp_Object val =3D Fformat_message (nargs, args); message3 (val); return val; } @@ -3984,7 +3985,7 @@ usage: (message-box FORMAT-STRING &rest ARGS) */) } else { - Lisp_Object val =3D styled_format (nargs, args, true, false); + Lisp_Object val =3D Fformat_message (nargs, args); Lisp_Object pane, menu; =20 pane =3D list1 (Fcons (build_string ("OK"), Qt)); @@ -4140,7 +4141,7 @@ produced text. usage: (format STRING &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - return styled_format (nargs, args, false, true); + return styled_format (nargs, args, false); } =20 DEFUN ("format-message", Fformat_message, Sformat_message, 1, MANY, 0, @@ -4156,16 +4157,13 @@ and right quote replacement characters are specif= ied by usage: (format-message STRING &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - return styled_format (nargs, args, true, true); + return styled_format (nargs, args, true); } =20 -/* Implement =E2=80=98format-message=E2=80=99 if MESSAGE is true, =E2=80= =98format=E2=80=99 otherwise. - If NEW_RESULT, the result is a new string; otherwise, the result - may be one of the arguments. */ +/* Implement =E2=80=98format-message=E2=80=99 if MESSAGE is true, =E2=80= =98format=E2=80=99 otherwise. */ =20 Lisp_Object -styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message, - bool new_result) +styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) { ptrdiff_t n; /* The number of the next arg to substitute. */ char initial_buffer[4000]; @@ -4195,9 +4193,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, /* The start and end bytepos in the output string. */ ptrdiff_t start, end; =20 - /* 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; @@ -4241,6 +4236,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, ptrdiff_t ispec; ptrdiff_t nspec =3D 0; =20 + /* True if a string needs to be allocated to hold the result. */ + bool new_result =3D false; + /* If we start out planning a unibyte result, then discover it has to be multibyte, we jump back to retry. */ retry: @@ -4360,7 +4358,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, if (nspec < ispec) { spec->argument =3D args[n]; - spec->new_string =3D false; spec->intervals =3D false; nspec =3D ispec; } @@ -4378,7 +4375,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, { Lisp_Object noescape =3D conversion =3D=3D 'S' ? Qnil : Qt; spec->argument =3D arg =3D Fprin1_to_string (arg, noescape); - spec->new_string =3D true; if (STRING_MULTIBYTE (arg) && ! multibyte) { multibyte =3D true; @@ -4397,7 +4393,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, goto retry; } spec->argument =3D arg =3D Fchar_to_string (arg); - spec->new_string =3D true; } =20 if (!EQ (arg, args[n])) @@ -4421,7 +4416,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, = bool message, if (conversion =3D=3D 's') { if (format =3D=3D end && format - format_start =3D=3D 2 - && (!new_result || spec->new_string) && ! string_intervals (args[0])) return arg; =20 diff --git a/src/lisp.h b/src/lisp.h index 0c3ca3ae06..c503082442 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3969,7 +3969,6 @@ 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, ptrdif= f_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); =20 diff --git a/src/xdisp.c b/src/xdisp.c index 86164eb9f6..141275f15a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -10194,7 +10194,7 @@ vadd_to_log (char const *format, va_list ap) for (ptrdiff_t i =3D 1; i <=3D nargs; i++) args[i] =3D va_arg (ap, Lisp_Object); Lisp_Object msg =3D Qnil; - msg =3D styled_format (nargs, args, true, false); + msg =3D Fformat_message (nargs, args); =20 ptrdiff_t len =3D SBYTES (msg) + 1; USE_SAFE_ALLOCA; @@ -19525,7 +19525,7 @@ DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strac= e_to_stderr, 1, MANY, "", usage: (trace-to-stderr STRING &rest OBJECTS) */) (ptrdiff_t nargs, Lisp_Object *args) { - Lisp_Object s =3D styled_format (nargs, args, false, false); + Lisp_Object s =3D Fformat (nargs, args); fwrite (SDATA (s), 1, SBYTES (s), stderr); return Qnil; } --=20 2.13.5