;; 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
(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
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;