summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVibhav Pant <vibhavp@gmail.com>2017-02-09 12:18:54 +0530
committerVibhav Pant <vibhavp@gmail.com>2017-02-09 12:18:54 +0530
commitdde800c8c9ea198996229d03df1fc45c7d057339 (patch)
tree5101a2f8260e141a64af96e84ca565dd8e49a568 /src
parent96c4e367f973626cbab38af55a2c448b7274eeee (diff)
downloademacs-dde800c8c9ea198996229d03df1fc45c7d057339.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/bytecode.c35
1 files changed, 27 insertions, 8 deletions
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,
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;