]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve byte-switch execution.
authorVibhav Pant <vibhavp@gmail.com>
Thu, 9 Feb 2017 06:48:54 +0000 (12:18 +0530)
committerVibhav Pant <vibhavp@gmail.com>
Thu, 9 Feb 2017 06:48:54 +0000 (12:18 +0530)
* 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.

lisp/emacs-lisp/byte-opt.el
lisp/emacs-lisp/bytecomp.el
src/bytecode.c

index 888a5f85007d3f78cfe671808645de8306e84390..3bec3e61df93641bcee7278ff9037e699d1ea09f 100644 (file)
                ;; Replace all addresses with TAGs.
                (maphash #'(lambda (value tag)
                             (let (newtag)
-                              (cl-assert (consp tag)
-                                         nil "Invalid address for byte-switch")
                               (setq newtag (byte-compile-make-tag))
-                              (push (cons (+ (car tag) (lsh (cdr tag) 8)) newtag) tags)
+                              (push (cons tag newtag) tags)
                               (puthash value newtag last-constant)))
                         last-constant)
                ;; Replace the hash table referenced in the lapcode with our
index d5a163e5fdd913e4d5a6da376fcbef1ecdbad10f..748a8cd01f3d54550e8ee70807541cc433b70d97 100644 (file)
@@ -917,10 +917,11 @@ CONST2 may be evaluated multiple times."
       (if (> (car bytes-tail) 255) (error "Bytecode overflow")))
 
     (dolist (hash-table byte-compile-jump-tables)
-      (cl-loop for k being the hash-keys of hash-table do
-               (let ((tag (cdr (gethash k hash-table))))
-                 (setq pc (car tag))
-                 (puthash k (cons (logand pc 255) (lsh pc -8)) hash-table))))
+      (maphash #'(lambda (value tag)
+                   (setq pc (cadr tag))
+                   (puthash value (+ (logand pc 255) (lsh (lsh pc -8) 8))
+                            hash-table))
+               hash-table))
     (apply 'unibyte-string (nreverse bytes))))
 
 \f
index f9531761b3c105e088c0d5fb0b87dc88fc21055d..9bb7bd4e6852e3de94176db691ad0452a33a1b38 100644 (file)
@@ -1415,20 +1415,39 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
 
         CASE (Bswitch):
           {
+            /*TODO: Perhaps introduce another byte-code for switch when the
+              number of cases is less, which uses a simple vector for linear
+              search as the jump table.  */
             Lisp_Object jmp_table = POP;
             Lisp_Object v1 = POP;
 #ifdef BYTE_CODE_SAFE
             CHECK_TYPE (HASH_TABLE_P (jmp_table), Qhash_table_p, jmp_table);
 #endif
+            ptrdiff_t i;
             struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table);
-            ptrdiff_t i = hash_lookup(h, v1, NULL);
-            if (i >= 0) {
-              Lisp_Object dest = HASH_VALUE(h, i);
-              int car = XINT(XCAR(dest));
-              int cdr = XINT(XCDR(dest));
-              op = car + (cdr << 8); /* Simulate FETCH2 */
-              goto op_branch;
-            }
+            if (HASH_TABLE_SIZE (h) <= 5)
+              { /* Do a linear search if there are not many cases
+                   FIXME: 5 is arbitrarily chosen.  */
+                for (i = 0; i < HASH_TABLE_SIZE (h); i++)
+                  {
+                    if (!NILP (HASH_HASH (h, i)) &&
+                        (EQ (v1, HASH_KEY (h, i)) ||
+                         (h->test.cmpfn &&
+                          h->test.cmpfn (&h->test, v1, HASH_KEY (h, i)))))
+                      {
+                        op = XINT (HASH_VALUE (h, i));
+                        goto op_branch;
+                      }
+                  }
+              }
+            else
+              {
+                i = hash_lookup(h, v1, NULL);
+                if (i >= 0) {
+                  op = XINT(HASH_VALUE (h, i));
+                  goto op_branch;
+                }
+              }
           }
           NEXT;