1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 06:20:43 -08:00

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.
This commit is contained in:
Vibhav Pant 2017-02-09 12:18:54 +05:30
parent 96c4e367f9
commit dde800c8c9
3 changed files with 33 additions and 15 deletions

View file

@ -1411,10 +1411,8 @@
;; Replace all addresses with TAGs. ;; Replace all addresses with TAGs.
(maphash #'(lambda (value tag) (maphash #'(lambda (value tag)
(let (newtag) (let (newtag)
(cl-assert (consp tag)
nil "Invalid address for byte-switch")
(setq newtag (byte-compile-make-tag)) (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))) (puthash value newtag last-constant)))
last-constant) last-constant)
;; Replace the hash table referenced in the lapcode with our ;; Replace the hash table referenced in the lapcode with our

View file

@ -917,10 +917,11 @@ CONST2 may be evaluated multiple times."
(if (> (car bytes-tail) 255) (error "Bytecode overflow"))) (if (> (car bytes-tail) 255) (error "Bytecode overflow")))
(dolist (hash-table byte-compile-jump-tables) (dolist (hash-table byte-compile-jump-tables)
(cl-loop for k being the hash-keys of hash-table do (maphash #'(lambda (value tag)
(let ((tag (cdr (gethash k hash-table)))) (setq pc (cadr tag))
(setq pc (car tag)) (puthash value (+ (logand pc 255) (lsh (lsh pc -8) 8))
(puthash k (cons (logand pc 255) (lsh pc -8)) hash-table)))) hash-table))
hash-table))
(apply 'unibyte-string (nreverse bytes)))) (apply 'unibyte-string (nreverse bytes))))

View file

@ -1415,20 +1415,39 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
CASE (Bswitch): 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 jmp_table = POP;
Lisp_Object v1 = POP; Lisp_Object v1 = POP;
#ifdef BYTE_CODE_SAFE #ifdef BYTE_CODE_SAFE
CHECK_TYPE (HASH_TABLE_P (jmp_table), Qhash_table_p, jmp_table); CHECK_TYPE (HASH_TABLE_P (jmp_table), Qhash_table_p, jmp_table);
#endif #endif
ptrdiff_t i;
struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table); struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table);
ptrdiff_t i = hash_lookup(h, v1, NULL); if (HASH_TABLE_SIZE (h) <= 5)
if (i >= 0) { { /* Do a linear search if there are not many cases
Lisp_Object dest = HASH_VALUE(h, i); FIXME: 5 is arbitrarily chosen. */
int car = XINT(XCAR(dest)); for (i = 0; i < HASH_TABLE_SIZE (h); i++)
int cdr = XINT(XCDR(dest)); {
op = car + (cdr << 8); /* Simulate FETCH2 */ if (!NILP (HASH_HASH (h, i)) &&
goto op_branch; (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; NEXT;