aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVibhav Pant2017-02-09 12:18:54 +0530
committerVibhav Pant2017-02-09 12:18:54 +0530
commitdde800c8c9ea198996229d03df1fc45c7d057339 (patch)
tree5101a2f8260e141a64af96e84ca565dd8e49a568
parent96c4e367f973626cbab38af55a2c448b7274eeee (diff)
downloademacs-dde800c8c9ea198996229d03df1fc45c7d057339.tar.gz
emacs-dde800c8c9ea198996229d03df1fc45c7d057339.zip
Improve byte-switch execution.
* lisp/emacs-lisp/byte-opt.el, lisp/emacs-lisp/bytecomp.el (byte-decompile-bytecode-1), (byte-compile-lapcode): Calculate the actual jump address while compiling, store it in the jump table. * src/bytecode.c: Jump to the looked up value directly, do a linear search when the number of elements is <= 5.
-rw-r--r--lisp/emacs-lisp/byte-opt.el4
-rw-r--r--lisp/emacs-lisp/bytecomp.el9
-rw-r--r--src/bytecode.c35
3 files changed, 33 insertions, 15 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 888a5f85007..3bec3e61df9 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1411,10 +1411,8 @@
1411 ;; Replace all addresses with TAGs. 1411 ;; Replace all addresses with TAGs.
1412 (maphash #'(lambda (value tag) 1412 (maphash #'(lambda (value tag)
1413 (let (newtag) 1413 (let (newtag)
1414 (cl-assert (consp tag)
1415 nil "Invalid address for byte-switch")
1416 (setq newtag (byte-compile-make-tag)) 1414 (setq newtag (byte-compile-make-tag))
1417 (push (cons (+ (car tag) (lsh (cdr tag) 8)) newtag) tags) 1415 (push (cons tag newtag) tags)
1418 (puthash value newtag last-constant))) 1416 (puthash value newtag last-constant)))
1419 last-constant) 1417 last-constant)
1420 ;; Replace the hash table referenced in the lapcode with our 1418 ;; Replace the hash table referenced in the lapcode with our
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index d5a163e5fdd..748a8cd01f3 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -917,10 +917,11 @@ CONST2 may be evaluated multiple times."
917 (if (> (car bytes-tail) 255) (error "Bytecode overflow"))) 917 (if (> (car bytes-tail) 255) (error "Bytecode overflow")))
918 918
919 (dolist (hash-table byte-compile-jump-tables) 919 (dolist (hash-table byte-compile-jump-tables)
920 (cl-loop for k being the hash-keys of hash-table do 920 (maphash #'(lambda (value tag)
921 (let ((tag (cdr (gethash k hash-table)))) 921 (setq pc (cadr tag))
922 (setq pc (car tag)) 922 (puthash value (+ (logand pc 255) (lsh (lsh pc -8) 8))
923 (puthash k (cons (logand pc 255) (lsh pc -8)) hash-table)))) 923 hash-table))
924 hash-table))
924 (apply 'unibyte-string (nreverse bytes)))) 925 (apply 'unibyte-string (nreverse bytes))))
925 926
926 927
diff --git a/src/bytecode.c b/src/bytecode.c
index f9531761b3c..9bb7bd4e685 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1415,20 +1415,39 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1415 1415
1416 CASE (Bswitch): 1416 CASE (Bswitch):
1417 { 1417 {
1418 /*TODO: Perhaps introduce another byte-code for switch when the
1419 number of cases is less, which uses a simple vector for linear
1420 search as the jump table. */
1418 Lisp_Object jmp_table = POP; 1421 Lisp_Object jmp_table = POP;
1419 Lisp_Object v1 = POP; 1422 Lisp_Object v1 = POP;
1420#ifdef BYTE_CODE_SAFE 1423#ifdef BYTE_CODE_SAFE
1421 CHECK_TYPE (HASH_TABLE_P (jmp_table), Qhash_table_p, jmp_table); 1424 CHECK_TYPE (HASH_TABLE_P (jmp_table), Qhash_table_p, jmp_table);
1422#endif 1425#endif
1426 ptrdiff_t i;
1423 struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table); 1427 struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table);
1424 ptrdiff_t i = hash_lookup(h, v1, NULL); 1428 if (HASH_TABLE_SIZE (h) <= 5)
1425 if (i >= 0) { 1429 { /* Do a linear search if there are not many cases
1426 Lisp_Object dest = HASH_VALUE(h, i); 1430 FIXME: 5 is arbitrarily chosen. */
1427 int car = XINT(XCAR(dest)); 1431 for (i = 0; i < HASH_TABLE_SIZE (h); i++)
1428 int cdr = XINT(XCDR(dest)); 1432 {
1429 op = car + (cdr << 8); /* Simulate FETCH2 */ 1433 if (!NILP (HASH_HASH (h, i)) &&
1430 goto op_branch; 1434 (EQ (v1, HASH_KEY (h, i)) ||
1431 } 1435 (h->test.cmpfn &&
1436 h->test.cmpfn (&h->test, v1, HASH_KEY (h, i)))))
1437 {
1438 op = XINT (HASH_VALUE (h, i));
1439 goto op_branch;
1440 }
1441 }
1442 }
1443 else
1444 {
1445 i = hash_lookup(h, v1, NULL);
1446 if (i >= 0) {
1447 op = XINT(HASH_VALUE (h, i));
1448 goto op_branch;
1449 }
1450 }
1432 } 1451 }
1433 NEXT; 1452 NEXT;
1434 1453