diff options
| author | Mattias EngdegÄrd | 2020-07-05 13:47:34 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2020-07-06 12:54:17 +0200 |
| commit | fb63a64d2159be9cd9bf63a0a6ebff582e385528 (patch) | |
| tree | 627cd64caae202c90d8fe746285ece65c6a09f17 | |
| parent | 10a0941f4dcc85d95279ae67032ec04463a44d59 (diff) | |
| download | emacs-fb63a64d2159be9cd9bf63a0a6ebff582e385528.tar.gz emacs-fb63a64d2159be9cd9bf63a0a6ebff582e385528.zip | |
Mark more functions pure (bug#42147)
Extend the list of 'pure' functions to many predicates and numerical
functions that we are reasonably confident will give portable results.
Also include various list and array accessors, because our use of purity
in the byte compiler isn't affected by the mutability of arguments.
* lisp/emacs-lisp/byte-opt.el: Update example in comment.
(pure-fns): Add many functions.
(byte-optimize-form-code-walker) Don't signal errors during evaluation
of calls to pure functions with constant arguments at compile time,
since such calls are not necessarily reachable.
| -rw-r--r-- | lisp/emacs-lisp/byte-opt.el | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index bf9e6a728a3..971e4ddbcc9 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -557,7 +557,10 @@ | |||
| 557 | (let ((args (mapcar #'byte-optimize-form (cdr form)))) | 557 | (let ((args (mapcar #'byte-optimize-form (cdr form)))) |
| 558 | (if (and (get fn 'pure) | 558 | (if (and (get fn 'pure) |
| 559 | (byte-optimize-all-constp args)) | 559 | (byte-optimize-all-constp args)) |
| 560 | (list 'quote (apply fn (mapcar #'eval args))) | 560 | (let ((arg-values (mapcar #'eval args))) |
| 561 | (condition-case nil | ||
| 562 | (list 'quote (apply fn arg-values)) | ||
| 563 | (error (cons fn args)))) | ||
| 561 | (cons fn args))))))) | 564 | (cons fn args))))))) |
| 562 | 565 | ||
| 563 | (defun byte-optimize-all-constp (list) | 566 | (defun byte-optimize-all-constp (list) |
| @@ -1274,9 +1277,9 @@ | |||
| 1274 | ;; Pure functions are side-effect free functions whose values depend | 1277 | ;; Pure functions are side-effect free functions whose values depend |
| 1275 | ;; only on their arguments, not on the platform. For these functions, | 1278 | ;; only on their arguments, not on the platform. For these functions, |
| 1276 | ;; calls with constant arguments can be evaluated at compile time. | 1279 | ;; calls with constant arguments can be evaluated at compile time. |
| 1277 | ;; This may shift runtime errors to compile time. For example, logand | 1280 | ;; For example, ash is pure since its results are machine-independent, |
| 1278 | ;; is pure since its results are machine-independent, whereas ash is | 1281 | ;; whereas lsh is not pure because (lsh -1 -1)'s value depends on the |
| 1279 | ;; not pure because (ash 1 29)'s value depends on machine word size. | 1282 | ;; fixnum range. |
| 1280 | ;; | 1283 | ;; |
| 1281 | ;; When deciding whether a function is pure, do not worry about | 1284 | ;; When deciding whether a function is pure, do not worry about |
| 1282 | ;; mutable strings or markers, as they are so unlikely in real code | 1285 | ;; mutable strings or markers, as they are so unlikely in real code |
| @@ -1286,9 +1289,41 @@ | |||
| 1286 | ;; values if a marker is moved. | 1289 | ;; values if a marker is moved. |
| 1287 | 1290 | ||
| 1288 | (let ((pure-fns | 1291 | (let ((pure-fns |
| 1289 | '(% concat logand logcount logior lognot logxor | 1292 | '(concat regexp-opt regexp-quote |
| 1290 | regexp-opt regexp-quote | 1293 | string-to-char string-to-syntax symbol-name |
| 1291 | string-to-char string-to-syntax symbol-name))) | 1294 | eq eql |
| 1295 | = /= < <= => > min max | ||
| 1296 | + - * / % mod abs ash 1+ 1- sqrt | ||
| 1297 | logand logior lognot logxor logcount | ||
| 1298 | copysign isnan ldexp float logb | ||
| 1299 | floor ceiling round truncate | ||
| 1300 | ffloor fceiling fround ftruncate | ||
| 1301 | string= string-equal string< string-lessp | ||
| 1302 | consp atom listp nlistp propert-list-p | ||
| 1303 | sequencep arrayp vectorp stringp bool-vector-p hash-table-p | ||
| 1304 | null not | ||
| 1305 | numberp integerp floatp natnump characterp | ||
| 1306 | integer-or-marker-p number-or-marker-p char-or-string-p | ||
| 1307 | symbolp keywordp | ||
| 1308 | type-of | ||
| 1309 | identity ignore | ||
| 1310 | |||
| 1311 | ;; The following functions are pure up to mutation of their | ||
| 1312 | ;; arguments. This is pure enough for the purposes of | ||
| 1313 | ;; constant folding, but not necessarily for all kinds of | ||
| 1314 | ;; code motion. | ||
| 1315 | car cdr car-safe cdr-safe nth nthcdr last | ||
| 1316 | equal | ||
| 1317 | length safe-length | ||
| 1318 | memq memql member | ||
| 1319 | ;; `assoc' and `assoc-default' are excluded since they are | ||
| 1320 | ;; impure if the test function is (consider `string-match'). | ||
| 1321 | assq rassq rassoc | ||
| 1322 | plist-get lax-plist-get plist-member | ||
| 1323 | aref elt | ||
| 1324 | bool-vector-subsetp | ||
| 1325 | bool-vector-count-population bool-vector-count-consecutive | ||
| 1326 | ))) | ||
| 1292 | (while pure-fns | 1327 | (while pure-fns |
| 1293 | (put (car pure-fns) 'pure t) | 1328 | (put (car pure-fns) 'pure t) |
| 1294 | (setq pure-fns (cdr pure-fns))) | 1329 | (setq pure-fns (cdr pure-fns))) |