diff options
Diffstat (limited to 'src/bytecode.c')
-rw-r--r-- | src/bytecode.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 0f7420c19ee..af94d03b17d 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -267,6 +267,8 @@ DEFINE (Bstack_set, 0262) \ DEFINE (Bstack_set2, 0263) \ DEFINE (BdiscardN, 0266) \ \ +DEFINE (Bswitch, 0267) \ + \ DEFINE (Bconstant, 0300) enum byte_code_op @@ -1411,6 +1413,43 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, DISCARD (op); NEXT; + 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; + ptrdiff_t i; + struct Lisp_Hash_Table *h = XHASH_TABLE(jmp_table); + + /* h->count is a faster approximation for HASH_TABLE_SIZE (h) + here. */ + if (h->count <= 5) + { /* Do a linear search if there are not many cases + FIXME: 5 is arbitrarily chosen. */ + Lisp_Object hash_code = h->test.cmpfn + ? make_number(h->test.hashfn (&h->test, v1)) : Qnil; + + for (i = h->count; 0 <= --i;) + if (EQ (v1, HASH_KEY (h, i)) + || (h->test.cmpfn + && EQ (hash_code, HASH_HASH (h, i)) + && h->test.cmpfn (&h->test, v1, HASH_KEY (h, i)))) + break; + + } + else + i = hash_lookup(h, v1, NULL); + + if (i >= 0) + { + op = XINT (HASH_VALUE (h, i)); + goto op_branch; + } + } + NEXT; + CASE_DEFAULT CASE (Bconstant): if (BYTE_CODE_SAFE |