diff options
| author | Stefan Monnier | 2012-11-08 14:12:23 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2012-11-08 14:12:23 -0500 |
| commit | b7432bb20f48902994bee522bea15acdb0c0e209 (patch) | |
| tree | 940e242625e16ade096c4144d728c56107aa7005 /src | |
| parent | 880027430c5580abf612a82273bd49b75b9fb73c (diff) | |
| download | emacs-b7432bb20f48902994bee522bea15acdb0c0e209.tar.gz emacs-b7432bb20f48902994bee522bea15acdb0c0e209.zip | |
Use ad-hoc comparison function for the profiler's hash-tables.
* src/profiler.c (Qprofiler_backtrace_equal, hashtest_profiler): New vars.
(make_log): Use them.
(handle_profiler_signal): Don't inhibit quit any longer since we don't
call Fequal any more.
(Ffunction_equal): New function.
(cmpfn_profiler, hashfn_profiler): New functions.
(syms_of_profiler): Initialize them.
* src/lisp.h (struct hash_table_test): New struct.
(struct Lisp_Hash_Table): Use it.
* src/alloc.c (mark_object): Mark hash_table_test fields of hash tables.
* src/fns.c (make_hash_table): Take a struct to describe the test.
(cmpfn_eql, cmpfn_equal, cmpfn_user_defined, hashfn_eq, hashfn_eql)
(hashfn_equal, hashfn_user_defined): Adjust to new calling convention.
(hash_lookup, hash_remove_from_table): Move assertion checking of
hashfn result here. Check hash-equality before calling cmpfn.
(Fmake_hash_table): Adjust call to make_hash_table.
(hashtest_eq, hashtest_eql, hashtest_equal): New structs.
(syms_of_fns): Initialize them.
* src/emacs.c (main): Move syms_of_fns earlier.
* src/xterm.c (syms_of_xterm):
* src/category.c (hash_get_category_set): Adjust call to make_hash_table.
* src/print.c (print_object): Adjust to new hash-table struct.
* src/composite.c (composition_gstring_put_cache): Adjust to new hashfn.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 27 | ||||
| -rw-r--r-- | src/alloc.c | 3 | ||||
| -rw-r--r-- | src/category.c | 4 | ||||
| -rw-r--r-- | src/composite.c | 4 | ||||
| -rw-r--r-- | src/emacs.c | 4 | ||||
| -rw-r--r-- | src/fns.c | 138 | ||||
| -rw-r--r-- | src/lisp.h | 44 | ||||
| -rw-r--r-- | src/print.c | 6 | ||||
| -rw-r--r-- | src/profiler.c | 91 | ||||
| -rw-r--r-- | src/regex.c | 2 | ||||
| -rw-r--r-- | src/xterm.c | 4 |
11 files changed, 204 insertions, 123 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 8f2aa41bef0..24f3305b870 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,30 @@ | |||
| 1 | 2012-11-08 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | Use ad-hoc comparison function for the profiler's hash-tables. | ||
| 4 | * profiler.c (Qprofiler_backtrace_equal, hashtest_profiler): New vars. | ||
| 5 | (make_log): Use them. | ||
| 6 | (handle_profiler_signal): Don't inhibit quit any longer since we don't | ||
| 7 | call Fequal any more. | ||
| 8 | (Ffunction_equal): New function. | ||
| 9 | (cmpfn_profiler, hashfn_profiler): New functions. | ||
| 10 | (syms_of_profiler): Initialize them. | ||
| 11 | * lisp.h (struct hash_table_test): New struct. | ||
| 12 | (struct Lisp_Hash_Table): Use it. | ||
| 13 | * alloc.c (mark_object): Mark hash_table_test fields of hash tables. | ||
| 14 | * fns.c (make_hash_table): Take a struct to describe the test. | ||
| 15 | (cmpfn_eql, cmpfn_equal, cmpfn_user_defined, hashfn_eq, hashfn_eql) | ||
| 16 | (hashfn_equal, hashfn_user_defined): Adjust to new calling convention. | ||
| 17 | (hash_lookup, hash_remove_from_table): Move assertion checking of | ||
| 18 | hashfn result here. Check hash-equality before calling cmpfn. | ||
| 19 | (Fmake_hash_table): Adjust call to make_hash_table. | ||
| 20 | (hashtest_eq, hashtest_eql, hashtest_equal): New structs. | ||
| 21 | (syms_of_fns): Initialize them. | ||
| 22 | * emacs.c (main): Move syms_of_fns earlier. | ||
| 23 | * xterm.c (syms_of_xterm): | ||
| 24 | * category.c (hash_get_category_set): Adjust call to make_hash_table. | ||
| 25 | * print.c (print_object): Adjust to new hash-table struct. | ||
| 26 | * composite.c (composition_gstring_put_cache): Adjust to new hashfn. | ||
| 27 | |||
| 1 | 2012-11-08 Eli Zaretskii <eliz@gnu.org> | 28 | 2012-11-08 Eli Zaretskii <eliz@gnu.org> |
| 2 | 29 | ||
| 3 | * w32fns.c (modifier_set): Fix handling of Scroll Lock when the | 30 | * w32fns.c (modifier_set): Fix handling of Scroll Lock when the |
diff --git a/src/alloc.c b/src/alloc.c index 557c68ca5af..808557dd70f 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -5809,6 +5809,9 @@ mark_object (Lisp_Object arg) | |||
| 5809 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; | 5809 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; |
| 5810 | 5810 | ||
| 5811 | mark_vectorlike (ptr); | 5811 | mark_vectorlike (ptr); |
| 5812 | mark_object (h->test.name); | ||
| 5813 | mark_object (h->test.user_hash_function); | ||
| 5814 | mark_object (h->test.user_cmp_function); | ||
| 5812 | /* If hash table is not weak, mark all keys and values. | 5815 | /* If hash table is not weak, mark all keys and values. |
| 5813 | For weak tables, mark only the vector. */ | 5816 | For weak tables, mark only the vector. */ |
| 5814 | if (NILP (h->weak)) | 5817 | if (NILP (h->weak)) |
diff --git a/src/category.c b/src/category.c index fe02303f679..31cc90bca68 100644 --- a/src/category.c +++ b/src/category.c | |||
| @@ -78,10 +78,10 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set) | |||
| 78 | if (NILP (XCHAR_TABLE (table)->extras[1])) | 78 | if (NILP (XCHAR_TABLE (table)->extras[1])) |
| 79 | set_char_table_extras | 79 | set_char_table_extras |
| 80 | (table, 1, | 80 | (table, 1, |
| 81 | make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), | 81 | make_hash_table (hashtest_equal, make_number (DEFAULT_HASH_SIZE), |
| 82 | make_float (DEFAULT_REHASH_SIZE), | 82 | make_float (DEFAULT_REHASH_SIZE), |
| 83 | make_float (DEFAULT_REHASH_THRESHOLD), | 83 | make_float (DEFAULT_REHASH_THRESHOLD), |
| 84 | Qnil, Qnil, Qnil)); | 84 | Qnil)); |
| 85 | h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]); | 85 | h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]); |
| 86 | i = hash_lookup (h, category_set, &hash); | 86 | i = hash_lookup (h, category_set, &hash); |
| 87 | if (i >= 0) | 87 | if (i >= 0) |
diff --git a/src/composite.c b/src/composite.c index 6c603fab3fc..bcde0a4c9e6 100644 --- a/src/composite.c +++ b/src/composite.c | |||
| @@ -676,7 +676,7 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len) | |||
| 676 | ptrdiff_t i; | 676 | ptrdiff_t i; |
| 677 | 677 | ||
| 678 | header = LGSTRING_HEADER (gstring); | 678 | header = LGSTRING_HEADER (gstring); |
| 679 | hash = h->hashfn (h, header); | 679 | hash = h->test.hashfn (&h->test, header); |
| 680 | if (len < 0) | 680 | if (len < 0) |
| 681 | { | 681 | { |
| 682 | ptrdiff_t j, glyph_len = LGSTRING_GLYPH_LEN (gstring); | 682 | ptrdiff_t j, glyph_len = LGSTRING_GLYPH_LEN (gstring); |
| @@ -1382,7 +1382,7 @@ composition_update_it (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff | |||
| 1382 | } | 1382 | } |
| 1383 | else | 1383 | else |
| 1384 | { | 1384 | { |
| 1385 | /* automatic composition */ | 1385 | /* Automatic composition. */ |
| 1386 | Lisp_Object gstring = composition_gstring_from_id (cmp_it->id); | 1386 | Lisp_Object gstring = composition_gstring_from_id (cmp_it->id); |
| 1387 | Lisp_Object glyph; | 1387 | Lisp_Object glyph; |
| 1388 | ptrdiff_t from; | 1388 | ptrdiff_t from; |
diff --git a/src/emacs.c b/src/emacs.c index f12713b9628..fee9c332c55 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1154,6 +1154,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1154 | 1154 | ||
| 1155 | /* Called before syms_of_fileio, because it sets up Qerror_condition. */ | 1155 | /* Called before syms_of_fileio, because it sets up Qerror_condition. */ |
| 1156 | syms_of_data (); | 1156 | syms_of_data (); |
| 1157 | syms_of_fns (); /* Before syms_of_charset which uses hashtables. */ | ||
| 1157 | syms_of_fileio (); | 1158 | syms_of_fileio (); |
| 1158 | /* Before syms_of_coding to initialize Vgc_cons_threshold. */ | 1159 | /* Before syms_of_coding to initialize Vgc_cons_threshold. */ |
| 1159 | syms_of_alloc (); | 1160 | syms_of_alloc (); |
| @@ -1165,7 +1166,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1165 | 1166 | ||
| 1166 | init_window_once (); /* Init the window system. */ | 1167 | init_window_once (); /* Init the window system. */ |
| 1167 | #ifdef HAVE_WINDOW_SYSTEM | 1168 | #ifdef HAVE_WINDOW_SYSTEM |
| 1168 | init_fringe_once (); /* Swap bitmaps if necessary. */ | 1169 | init_fringe_once (); /* Swap bitmaps if necessary. */ |
| 1169 | #endif /* HAVE_WINDOW_SYSTEM */ | 1170 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 1170 | } | 1171 | } |
| 1171 | 1172 | ||
| @@ -1348,7 +1349,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem | |||
| 1348 | syms_of_lread (); | 1349 | syms_of_lread (); |
| 1349 | syms_of_print (); | 1350 | syms_of_print (); |
| 1350 | syms_of_eval (); | 1351 | syms_of_eval (); |
| 1351 | syms_of_fns (); | ||
| 1352 | syms_of_floatfns (); | 1352 | syms_of_floatfns (); |
| 1353 | 1353 | ||
| 1354 | syms_of_buffer (); | 1354 | syms_of_buffer (); |
| @@ -2014,7 +2014,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props) | |||
| 2014 | d1 = extract_float (o1); | 2014 | d1 = extract_float (o1); |
| 2015 | d2 = extract_float (o2); | 2015 | d2 = extract_float (o2); |
| 2016 | /* If d is a NaN, then d != d. Two NaNs should be `equal' even | 2016 | /* If d is a NaN, then d != d. Two NaNs should be `equal' even |
| 2017 | though they are not =. */ | 2017 | though they are not =. */ |
| 2018 | return d1 == d2 || (d1 != d1 && d2 != d2); | 2018 | return d1 == d2 || (d1 != d1 && d2 != d2); |
| 2019 | } | 2019 | } |
| 2020 | 2020 | ||
| @@ -3424,14 +3424,16 @@ larger_vector (Lisp_Object vec, ptrdiff_t incr_min, ptrdiff_t nitems_max) | |||
| 3424 | Low-level Functions | 3424 | Low-level Functions |
| 3425 | ***********************************************************************/ | 3425 | ***********************************************************************/ |
| 3426 | 3426 | ||
| 3427 | struct hash_table_test hashtest_eq, hashtest_eql, hashtest_equal; | ||
| 3428 | |||
| 3427 | /* Compare KEY1 which has hash code HASH1 and KEY2 with hash code | 3429 | /* Compare KEY1 which has hash code HASH1 and KEY2 with hash code |
| 3428 | HASH2 in hash table H using `eql'. Value is true if KEY1 and | 3430 | HASH2 in hash table H using `eql'. Value is true if KEY1 and |
| 3429 | KEY2 are the same. */ | 3431 | KEY2 are the same. */ |
| 3430 | 3432 | ||
| 3431 | static bool | 3433 | static bool |
| 3432 | cmpfn_eql (struct Lisp_Hash_Table *h, | 3434 | cmpfn_eql (struct hash_table_test *ht, |
| 3433 | Lisp_Object key1, EMACS_UINT hash1, | 3435 | Lisp_Object key1, |
| 3434 | Lisp_Object key2, EMACS_UINT hash2) | 3436 | Lisp_Object key2) |
| 3435 | { | 3437 | { |
| 3436 | return (FLOATP (key1) | 3438 | return (FLOATP (key1) |
| 3437 | && FLOATP (key2) | 3439 | && FLOATP (key2) |
| @@ -3444,11 +3446,11 @@ cmpfn_eql (struct Lisp_Hash_Table *h, | |||
| 3444 | KEY2 are the same. */ | 3446 | KEY2 are the same. */ |
| 3445 | 3447 | ||
| 3446 | static bool | 3448 | static bool |
| 3447 | cmpfn_equal (struct Lisp_Hash_Table *h, | 3449 | cmpfn_equal (struct hash_table_test *ht, |
| 3448 | Lisp_Object key1, EMACS_UINT hash1, | 3450 | Lisp_Object key1, |
| 3449 | Lisp_Object key2, EMACS_UINT hash2) | 3451 | Lisp_Object key2) |
| 3450 | { | 3452 | { |
| 3451 | return hash1 == hash2 && !NILP (Fequal (key1, key2)); | 3453 | return !NILP (Fequal (key1, key2)); |
| 3452 | } | 3454 | } |
| 3453 | 3455 | ||
| 3454 | 3456 | ||
| @@ -3457,21 +3459,16 @@ cmpfn_equal (struct Lisp_Hash_Table *h, | |||
| 3457 | if KEY1 and KEY2 are the same. */ | 3459 | if KEY1 and KEY2 are the same. */ |
| 3458 | 3460 | ||
| 3459 | static bool | 3461 | static bool |
| 3460 | cmpfn_user_defined (struct Lisp_Hash_Table *h, | 3462 | cmpfn_user_defined (struct hash_table_test *ht, |
| 3461 | Lisp_Object key1, EMACS_UINT hash1, | 3463 | Lisp_Object key1, |
| 3462 | Lisp_Object key2, EMACS_UINT hash2) | 3464 | Lisp_Object key2) |
| 3463 | { | 3465 | { |
| 3464 | if (hash1 == hash2) | 3466 | Lisp_Object args[3]; |
| 3465 | { | ||
| 3466 | Lisp_Object args[3]; | ||
| 3467 | 3467 | ||
| 3468 | args[0] = h->user_cmp_function; | 3468 | args[0] = ht->user_cmp_function; |
| 3469 | args[1] = key1; | 3469 | args[1] = key1; |
| 3470 | args[2] = key2; | 3470 | args[2] = key2; |
| 3471 | return !NILP (Ffuncall (3, args)); | 3471 | return !NILP (Ffuncall (3, args)); |
| 3472 | } | ||
| 3473 | else | ||
| 3474 | return 0; | ||
| 3475 | } | 3472 | } |
| 3476 | 3473 | ||
| 3477 | 3474 | ||
| @@ -3480,54 +3477,48 @@ cmpfn_user_defined (struct Lisp_Hash_Table *h, | |||
| 3480 | in a Lisp integer. */ | 3477 | in a Lisp integer. */ |
| 3481 | 3478 | ||
| 3482 | static EMACS_UINT | 3479 | static EMACS_UINT |
| 3483 | hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key) | 3480 | hashfn_eq (struct hash_table_test *ht, Lisp_Object key) |
| 3484 | { | 3481 | { |
| 3485 | EMACS_UINT hash = XUINT (key) ^ XTYPE (key); | 3482 | EMACS_UINT hash = XUINT (key) ^ XTYPE (key); |
| 3486 | eassert ((hash & ~INTMASK) == 0); | ||
| 3487 | return hash; | 3483 | return hash; |
| 3488 | } | 3484 | } |
| 3489 | 3485 | ||
| 3490 | |||
| 3491 | /* Value is a hash code for KEY for use in hash table H which uses | 3486 | /* Value is a hash code for KEY for use in hash table H which uses |
| 3492 | `eql' to compare keys. The hash code returned is guaranteed to fit | 3487 | `eql' to compare keys. The hash code returned is guaranteed to fit |
| 3493 | in a Lisp integer. */ | 3488 | in a Lisp integer. */ |
| 3494 | 3489 | ||
| 3495 | static EMACS_UINT | 3490 | static EMACS_UINT |
| 3496 | hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key) | 3491 | hashfn_eql (struct hash_table_test *ht, Lisp_Object key) |
| 3497 | { | 3492 | { |
| 3498 | EMACS_UINT hash; | 3493 | EMACS_UINT hash; |
| 3499 | if (FLOATP (key)) | 3494 | if (FLOATP (key)) |
| 3500 | hash = sxhash (key, 0); | 3495 | hash = sxhash (key, 0); |
| 3501 | else | 3496 | else |
| 3502 | hash = XUINT (key) ^ XTYPE (key); | 3497 | hash = XUINT (key) ^ XTYPE (key); |
| 3503 | eassert ((hash & ~INTMASK) == 0); | ||
| 3504 | return hash; | 3498 | return hash; |
| 3505 | } | 3499 | } |
| 3506 | 3500 | ||
| 3507 | |||
| 3508 | /* Value is a hash code for KEY for use in hash table H which uses | 3501 | /* Value is a hash code for KEY for use in hash table H which uses |
| 3509 | `equal' to compare keys. The hash code returned is guaranteed to fit | 3502 | `equal' to compare keys. The hash code returned is guaranteed to fit |
| 3510 | in a Lisp integer. */ | 3503 | in a Lisp integer. */ |
| 3511 | 3504 | ||
| 3512 | static EMACS_UINT | 3505 | static EMACS_UINT |
| 3513 | hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key) | 3506 | hashfn_equal (struct hash_table_test *ht, Lisp_Object key) |
| 3514 | { | 3507 | { |
| 3515 | EMACS_UINT hash = sxhash (key, 0); | 3508 | EMACS_UINT hash = sxhash (key, 0); |
| 3516 | eassert ((hash & ~INTMASK) == 0); | ||
| 3517 | return hash; | 3509 | return hash; |
| 3518 | } | 3510 | } |
| 3519 | 3511 | ||
| 3520 | |||
| 3521 | /* Value is a hash code for KEY for use in hash table H which uses as | 3512 | /* Value is a hash code for KEY for use in hash table H which uses as |
| 3522 | user-defined function to compare keys. The hash code returned is | 3513 | user-defined function to compare keys. The hash code returned is |
| 3523 | guaranteed to fit in a Lisp integer. */ | 3514 | guaranteed to fit in a Lisp integer. */ |
| 3524 | 3515 | ||
| 3525 | static EMACS_UINT | 3516 | static EMACS_UINT |
| 3526 | hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key) | 3517 | hashfn_user_defined (struct hash_table_test *ht, Lisp_Object key) |
| 3527 | { | 3518 | { |
| 3528 | Lisp_Object args[2], hash; | 3519 | Lisp_Object args[2], hash; |
| 3529 | 3520 | ||
| 3530 | args[0] = h->user_hash_function; | 3521 | args[0] = ht->user_hash_function; |
| 3531 | args[1] = key; | 3522 | args[1] = key; |
| 3532 | hash = Ffuncall (2, args); | 3523 | hash = Ffuncall (2, args); |
| 3533 | if (!INTEGERP (hash)) | 3524 | if (!INTEGERP (hash)) |
| @@ -3563,9 +3554,9 @@ hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 3563 | one of the symbols `key', `value', `key-or-value', or `key-and-value'. */ | 3554 | one of the symbols `key', `value', `key-or-value', or `key-and-value'. */ |
| 3564 | 3555 | ||
| 3565 | Lisp_Object | 3556 | Lisp_Object |
| 3566 | make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size, | 3557 | make_hash_table (struct hash_table_test test, |
| 3567 | Lisp_Object rehash_threshold, Lisp_Object weak, | 3558 | Lisp_Object size, Lisp_Object rehash_size, |
| 3568 | Lisp_Object user_test, Lisp_Object user_hash) | 3559 | Lisp_Object rehash_threshold, Lisp_Object weak) |
| 3569 | { | 3560 | { |
| 3570 | struct Lisp_Hash_Table *h; | 3561 | struct Lisp_Hash_Table *h; |
| 3571 | Lisp_Object table; | 3562 | Lisp_Object table; |
| @@ -3574,7 +3565,7 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size, | |||
| 3574 | double index_float; | 3565 | double index_float; |
| 3575 | 3566 | ||
| 3576 | /* Preconditions. */ | 3567 | /* Preconditions. */ |
| 3577 | eassert (SYMBOLP (test)); | 3568 | eassert (SYMBOLP (test.name)); |
| 3578 | eassert (INTEGERP (size) && XINT (size) >= 0); | 3569 | eassert (INTEGERP (size) && XINT (size) >= 0); |
| 3579 | eassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0) | 3570 | eassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0) |
| 3580 | || (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size))); | 3571 | || (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size))); |
| @@ -3598,29 +3589,6 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size, | |||
| 3598 | 3589 | ||
| 3599 | /* Initialize hash table slots. */ | 3590 | /* Initialize hash table slots. */ |
| 3600 | h->test = test; | 3591 | h->test = test; |
| 3601 | if (EQ (test, Qeql)) | ||
| 3602 | { | ||
| 3603 | h->cmpfn = cmpfn_eql; | ||
| 3604 | h->hashfn = hashfn_eql; | ||
| 3605 | } | ||
| 3606 | else if (EQ (test, Qeq)) | ||
| 3607 | { | ||
| 3608 | h->cmpfn = NULL; | ||
| 3609 | h->hashfn = hashfn_eq; | ||
| 3610 | } | ||
| 3611 | else if (EQ (test, Qequal)) | ||
| 3612 | { | ||
| 3613 | h->cmpfn = cmpfn_equal; | ||
| 3614 | h->hashfn = hashfn_equal; | ||
| 3615 | } | ||
| 3616 | else | ||
| 3617 | { | ||
| 3618 | h->user_cmp_function = user_test; | ||
| 3619 | h->user_hash_function = user_hash; | ||
| 3620 | h->cmpfn = cmpfn_user_defined; | ||
| 3621 | h->hashfn = hashfn_user_defined; | ||
| 3622 | } | ||
| 3623 | |||
| 3624 | h->weak = weak; | 3592 | h->weak = weak; |
| 3625 | h->rehash_threshold = rehash_threshold; | 3593 | h->rehash_threshold = rehash_threshold; |
| 3626 | h->rehash_size = rehash_size; | 3594 | h->rehash_size = rehash_size; |
| @@ -3776,7 +3744,8 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) | |||
| 3776 | ptrdiff_t start_of_bucket; | 3744 | ptrdiff_t start_of_bucket; |
| 3777 | Lisp_Object idx; | 3745 | Lisp_Object idx; |
| 3778 | 3746 | ||
| 3779 | hash_code = h->hashfn (h, key); | 3747 | hash_code = h->test.hashfn (&h->test, key); |
| 3748 | eassert ((hash_code & ~INTMASK) == 0); | ||
| 3780 | if (hash) | 3749 | if (hash) |
| 3781 | *hash = hash_code; | 3750 | *hash = hash_code; |
| 3782 | 3751 | ||
| @@ -3788,9 +3757,9 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash) | |||
| 3788 | { | 3757 | { |
| 3789 | ptrdiff_t i = XFASTINT (idx); | 3758 | ptrdiff_t i = XFASTINT (idx); |
| 3790 | if (EQ (key, HASH_KEY (h, i)) | 3759 | if (EQ (key, HASH_KEY (h, i)) |
| 3791 | || (h->cmpfn | 3760 | || (h->test.cmpfn |
| 3792 | && h->cmpfn (h, key, hash_code, | 3761 | && hash_code == XUINT (HASH_HASH (h, i)) |
| 3793 | HASH_KEY (h, i), XUINT (HASH_HASH (h, i))))) | 3762 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) |
| 3794 | break; | 3763 | break; |
| 3795 | idx = HASH_NEXT (h, i); | 3764 | idx = HASH_NEXT (h, i); |
| 3796 | } | 3765 | } |
| @@ -3841,7 +3810,8 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 3841 | ptrdiff_t start_of_bucket; | 3810 | ptrdiff_t start_of_bucket; |
| 3842 | Lisp_Object idx, prev; | 3811 | Lisp_Object idx, prev; |
| 3843 | 3812 | ||
| 3844 | hash_code = h->hashfn (h, key); | 3813 | hash_code = h->test.hashfn (&h->test, key); |
| 3814 | eassert ((hash_code & ~INTMASK) == 0); | ||
| 3845 | start_of_bucket = hash_code % ASIZE (h->index); | 3815 | start_of_bucket = hash_code % ASIZE (h->index); |
| 3846 | idx = HASH_INDEX (h, start_of_bucket); | 3816 | idx = HASH_INDEX (h, start_of_bucket); |
| 3847 | prev = Qnil; | 3817 | prev = Qnil; |
| @@ -3852,9 +3822,9 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key) | |||
| 3852 | ptrdiff_t i = XFASTINT (idx); | 3822 | ptrdiff_t i = XFASTINT (idx); |
| 3853 | 3823 | ||
| 3854 | if (EQ (key, HASH_KEY (h, i)) | 3824 | if (EQ (key, HASH_KEY (h, i)) |
| 3855 | || (h->cmpfn | 3825 | || (h->test.cmpfn |
| 3856 | && h->cmpfn (h, key, hash_code, | 3826 | && hash_code == XUINT (HASH_HASH (h, i)) |
| 3857 | HASH_KEY (h, i), XUINT (HASH_HASH (h, i))))) | 3827 | && h->test.cmpfn (&h->test, key, HASH_KEY (h, i)))) |
| 3858 | { | 3828 | { |
| 3859 | /* Take entry out of collision chain. */ | 3829 | /* Take entry out of collision chain. */ |
| 3860 | if (NILP (prev)) | 3830 | if (NILP (prev)) |
| @@ -4303,7 +4273,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) | |||
| 4303 | (ptrdiff_t nargs, Lisp_Object *args) | 4273 | (ptrdiff_t nargs, Lisp_Object *args) |
| 4304 | { | 4274 | { |
| 4305 | Lisp_Object test, size, rehash_size, rehash_threshold, weak; | 4275 | Lisp_Object test, size, rehash_size, rehash_threshold, weak; |
| 4306 | Lisp_Object user_test, user_hash; | 4276 | struct hash_table_test testdesc; |
| 4307 | char *used; | 4277 | char *used; |
| 4308 | ptrdiff_t i; | 4278 | ptrdiff_t i; |
| 4309 | 4279 | ||
| @@ -4315,7 +4285,13 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) | |||
| 4315 | /* See if there's a `:test TEST' among the arguments. */ | 4285 | /* See if there's a `:test TEST' among the arguments. */ |
| 4316 | i = get_key_arg (QCtest, nargs, args, used); | 4286 | i = get_key_arg (QCtest, nargs, args, used); |
| 4317 | test = i ? args[i] : Qeql; | 4287 | test = i ? args[i] : Qeql; |
| 4318 | if (!EQ (test, Qeq) && !EQ (test, Qeql) && !EQ (test, Qequal)) | 4288 | if (EQ (test, Qeq)) |
| 4289 | testdesc = hashtest_eq; | ||
| 4290 | else if (EQ (test, Qeql)) | ||
| 4291 | testdesc = hashtest_eql; | ||
| 4292 | else if (EQ (test, Qequal)) | ||
| 4293 | testdesc = hashtest_equal; | ||
| 4294 | else | ||
| 4319 | { | 4295 | { |
| 4320 | /* See if it is a user-defined test. */ | 4296 | /* See if it is a user-defined test. */ |
| 4321 | Lisp_Object prop; | 4297 | Lisp_Object prop; |
| @@ -4323,11 +4299,12 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) | |||
| 4323 | prop = Fget (test, Qhash_table_test); | 4299 | prop = Fget (test, Qhash_table_test); |
| 4324 | if (!CONSP (prop) || !CONSP (XCDR (prop))) | 4300 | if (!CONSP (prop) || !CONSP (XCDR (prop))) |
| 4325 | signal_error ("Invalid hash table test", test); | 4301 | signal_error ("Invalid hash table test", test); |
| 4326 | user_test = XCAR (prop); | 4302 | testdesc.name = test; |
| 4327 | user_hash = XCAR (XCDR (prop)); | 4303 | testdesc.user_cmp_function = XCAR (prop); |
| 4304 | testdesc.user_hash_function = XCAR (XCDR (prop)); | ||
| 4305 | testdesc.hashfn = hashfn_user_defined; | ||
| 4306 | testdesc.cmpfn = cmpfn_user_defined; | ||
| 4328 | } | 4307 | } |
| 4329 | else | ||
| 4330 | user_test = user_hash = Qnil; | ||
| 4331 | 4308 | ||
| 4332 | /* See if there's a `:size SIZE' argument. */ | 4309 | /* See if there's a `:size SIZE' argument. */ |
| 4333 | i = get_key_arg (QCsize, nargs, args, used); | 4310 | i = get_key_arg (QCsize, nargs, args, used); |
| @@ -4369,8 +4346,7 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */) | |||
| 4369 | if (!used[i]) | 4346 | if (!used[i]) |
| 4370 | signal_error ("Invalid argument list", args[i]); | 4347 | signal_error ("Invalid argument list", args[i]); |
| 4371 | 4348 | ||
| 4372 | return make_hash_table (test, size, rehash_size, rehash_threshold, weak, | 4349 | return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak); |
| 4373 | user_test, user_hash); | ||
| 4374 | } | 4350 | } |
| 4375 | 4351 | ||
| 4376 | 4352 | ||
| @@ -4424,7 +4400,7 @@ DEFUN ("hash-table-test", Fhash_table_test, Shash_table_test, 1, 1, 0, | |||
| 4424 | doc: /* Return the test TABLE uses. */) | 4400 | doc: /* Return the test TABLE uses. */) |
| 4425 | (Lisp_Object table) | 4401 | (Lisp_Object table) |
| 4426 | { | 4402 | { |
| 4427 | return check_hash_table (table)->test; | 4403 | return check_hash_table (table)->test.name; |
| 4428 | } | 4404 | } |
| 4429 | 4405 | ||
| 4430 | 4406 | ||
| @@ -4988,4 +4964,14 @@ this variable. */); | |||
| 4988 | defsubr (&Smd5); | 4964 | defsubr (&Smd5); |
| 4989 | defsubr (&Ssecure_hash); | 4965 | defsubr (&Ssecure_hash); |
| 4990 | defsubr (&Slocale_info); | 4966 | defsubr (&Slocale_info); |
| 4967 | |||
| 4968 | { | ||
| 4969 | struct hash_table_test | ||
| 4970 | eq = { Qeq, Qnil, Qnil, NULL, hashfn_eq }, | ||
| 4971 | eql = { Qeql, Qnil, Qnil, cmpfn_eql, hashfn_eql }, | ||
| 4972 | equal = { Qequal, Qnil, Qnil, cmpfn_equal, hashfn_equal }; | ||
| 4973 | hashtest_eq = eq; | ||
| 4974 | hashtest_eql = eql; | ||
| 4975 | hashtest_equal = equal; | ||
| 4976 | } | ||
| 4991 | } | 4977 | } |
diff --git a/src/lisp.h b/src/lisp.h index 66612e2987e..cac7d4b7012 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1159,14 +1159,29 @@ struct Lisp_Symbol | |||
| 1159 | 1159 | ||
| 1160 | /* The structure of a Lisp hash table. */ | 1160 | /* The structure of a Lisp hash table. */ |
| 1161 | 1161 | ||
| 1162 | struct hash_table_test | ||
| 1163 | { | ||
| 1164 | /* Name of the function used to compare keys. */ | ||
| 1165 | Lisp_Object name; | ||
| 1166 | |||
| 1167 | /* User-supplied hash function, or nil. */ | ||
| 1168 | Lisp_Object user_hash_function; | ||
| 1169 | |||
| 1170 | /* User-supplied key comparison function, or nil. */ | ||
| 1171 | Lisp_Object user_cmp_function; | ||
| 1172 | |||
| 1173 | /* C function to compare two keys. */ | ||
| 1174 | bool (*cmpfn) (struct hash_table_test *t, Lisp_Object, Lisp_Object); | ||
| 1175 | |||
| 1176 | /* C function to compute hash code. */ | ||
| 1177 | EMACS_UINT (*hashfn) (struct hash_table_test *t, Lisp_Object); | ||
| 1178 | }; | ||
| 1179 | |||
| 1162 | struct Lisp_Hash_Table | 1180 | struct Lisp_Hash_Table |
| 1163 | { | 1181 | { |
| 1164 | /* This is for Lisp; the hash table code does not refer to it. */ | 1182 | /* This is for Lisp; the hash table code does not refer to it. */ |
| 1165 | struct vectorlike_header header; | 1183 | struct vectorlike_header header; |
| 1166 | 1184 | ||
| 1167 | /* Function used to compare keys. */ | ||
| 1168 | Lisp_Object test; | ||
| 1169 | |||
| 1170 | /* Nil if table is non-weak. Otherwise a symbol describing the | 1185 | /* Nil if table is non-weak. Otherwise a symbol describing the |
| 1171 | weakness of the table. */ | 1186 | weakness of the table. */ |
| 1172 | Lisp_Object weak; | 1187 | Lisp_Object weak; |
| @@ -1197,12 +1212,6 @@ struct Lisp_Hash_Table | |||
| 1197 | hash table size to reduce collisions. */ | 1212 | hash table size to reduce collisions. */ |
| 1198 | Lisp_Object index; | 1213 | Lisp_Object index; |
| 1199 | 1214 | ||
| 1200 | /* User-supplied hash function, or nil. */ | ||
| 1201 | Lisp_Object user_hash_function; | ||
| 1202 | |||
| 1203 | /* User-supplied key comparison function, or nil. */ | ||
| 1204 | Lisp_Object user_cmp_function; | ||
| 1205 | |||
| 1206 | /* Only the fields above are traced normally by the GC. The ones below | 1215 | /* Only the fields above are traced normally by the GC. The ones below |
| 1207 | `count' are special and are either ignored by the GC or traced in | 1216 | `count' are special and are either ignored by the GC or traced in |
| 1208 | a special way (e.g. because of weakness). */ | 1217 | a special way (e.g. because of weakness). */ |
| @@ -1215,17 +1224,12 @@ struct Lisp_Hash_Table | |||
| 1215 | This is gc_marked specially if the table is weak. */ | 1224 | This is gc_marked specially if the table is weak. */ |
| 1216 | Lisp_Object key_and_value; | 1225 | Lisp_Object key_and_value; |
| 1217 | 1226 | ||
| 1227 | /* The comparison and hash functions. */ | ||
| 1228 | struct hash_table_test test; | ||
| 1229 | |||
| 1218 | /* Next weak hash table if this is a weak hash table. The head | 1230 | /* Next weak hash table if this is a weak hash table. The head |
| 1219 | of the list is in weak_hash_tables. */ | 1231 | of the list is in weak_hash_tables. */ |
| 1220 | struct Lisp_Hash_Table *next_weak; | 1232 | struct Lisp_Hash_Table *next_weak; |
| 1221 | |||
| 1222 | /* C function to compare two keys. */ | ||
| 1223 | bool (*cmpfn) (struct Lisp_Hash_Table *, | ||
| 1224 | Lisp_Object, EMACS_UINT, | ||
| 1225 | Lisp_Object, EMACS_UINT); | ||
| 1226 | |||
| 1227 | /* C function to compute hash code. */ | ||
| 1228 | EMACS_UINT (*hashfn) (struct Lisp_Hash_Table *, Lisp_Object); | ||
| 1229 | }; | 1233 | }; |
| 1230 | 1234 | ||
| 1231 | 1235 | ||
| @@ -2707,12 +2711,12 @@ extern Lisp_Object Qstring_lessp; | |||
| 2707 | extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq, Qeql; | 2711 | extern Lisp_Object QCsize, QCtest, QCweakness, Qequal, Qeq, Qeql; |
| 2708 | EMACS_UINT hash_string (char const *, ptrdiff_t); | 2712 | EMACS_UINT hash_string (char const *, ptrdiff_t); |
| 2709 | EMACS_UINT sxhash (Lisp_Object, int); | 2713 | EMACS_UINT sxhash (Lisp_Object, int); |
| 2710 | Lisp_Object make_hash_table (Lisp_Object, Lisp_Object, Lisp_Object, | 2714 | Lisp_Object make_hash_table (struct hash_table_test, Lisp_Object, Lisp_Object, |
| 2711 | Lisp_Object, Lisp_Object, Lisp_Object, | 2715 | Lisp_Object, Lisp_Object); |
| 2712 | Lisp_Object); | ||
| 2713 | ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); | 2716 | ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *); |
| 2714 | ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, | 2717 | ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object, |
| 2715 | EMACS_UINT); | 2718 | EMACS_UINT); |
| 2719 | extern struct hash_table_test hashtest_eq, hashtest_eql, hashtest_equal; | ||
| 2716 | 2720 | ||
| 2717 | extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, | 2721 | extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, |
| 2718 | ptrdiff_t, ptrdiff_t); | 2722 | ptrdiff_t, ptrdiff_t); |
diff --git a/src/print.c b/src/print.c index ccf0e8ed7cc..af6eda7298f 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1815,14 +1815,14 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag | |||
| 1815 | #endif | 1815 | #endif |
| 1816 | /* Implement a readable output, e.g.: | 1816 | /* Implement a readable output, e.g.: |
| 1817 | #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ | 1817 | #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ |
| 1818 | /* Always print the size. */ | 1818 | /* Always print the size. */ |
| 1819 | len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); | 1819 | len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); |
| 1820 | strout (buf, len, len, printcharfun); | 1820 | strout (buf, len, len, printcharfun); |
| 1821 | 1821 | ||
| 1822 | if (!NILP (h->test)) | 1822 | if (!NILP (h->test.name)) |
| 1823 | { | 1823 | { |
| 1824 | strout (" test ", -1, -1, printcharfun); | 1824 | strout (" test ", -1, -1, printcharfun); |
| 1825 | print_object (h->test, printcharfun, escapeflag); | 1825 | print_object (h->test.name, printcharfun, escapeflag); |
| 1826 | } | 1826 | } |
| 1827 | 1827 | ||
| 1828 | if (!NILP (h->weak)) | 1828 | if (!NILP (h->weak)) |
diff --git a/src/profiler.c b/src/profiler.c index 51580710f28..6f112440902 100644 --- a/src/profiler.c +++ b/src/profiler.c | |||
| @@ -35,6 +35,9 @@ saturated_add (EMACS_INT a, EMACS_INT b) | |||
| 35 | 35 | ||
| 36 | typedef struct Lisp_Hash_Table log_t; | 36 | typedef struct Lisp_Hash_Table log_t; |
| 37 | 37 | ||
| 38 | static Lisp_Object Qprofiler_backtrace_equal; | ||
| 39 | static struct hash_table_test hashtest_profiler; | ||
| 40 | |||
| 38 | static Lisp_Object | 41 | static Lisp_Object |
| 39 | make_log (int heap_size, int max_stack_depth) | 42 | make_log (int heap_size, int max_stack_depth) |
| 40 | { | 43 | { |
| @@ -42,10 +45,11 @@ make_log (int heap_size, int max_stack_depth) | |||
| 42 | a special way. This is OK as long as the object is not exposed | 45 | a special way. This is OK as long as the object is not exposed |
| 43 | to Elisp, i.e. until it is returned by *-profiler-log, after which | 46 | to Elisp, i.e. until it is returned by *-profiler-log, after which |
| 44 | it can't be used any more. */ | 47 | it can't be used any more. */ |
| 45 | Lisp_Object log = make_hash_table (Qequal, make_number (heap_size), | 48 | Lisp_Object log = make_hash_table (hashtest_profiler, |
| 49 | make_number (heap_size), | ||
| 46 | make_float (DEFAULT_REHASH_SIZE), | 50 | make_float (DEFAULT_REHASH_SIZE), |
| 47 | make_float (DEFAULT_REHASH_THRESHOLD), | 51 | make_float (DEFAULT_REHASH_THRESHOLD), |
| 48 | Qnil, Qnil, Qnil); | 52 | Qnil); |
| 49 | struct Lisp_Hash_Table *h = XHASH_TABLE (log); | 53 | struct Lisp_Hash_Table *h = XHASH_TABLE (log); |
| 50 | 54 | ||
| 51 | /* What is special about our hash-tables is that the keys are pre-filled | 55 | /* What is special about our hash-tables is that the keys are pre-filled |
| @@ -238,8 +242,6 @@ handle_profiler_signal (int signal) | |||
| 238 | cpu_gc_count = saturated_add (cpu_gc_count, 1); | 242 | cpu_gc_count = saturated_add (cpu_gc_count, 1); |
| 239 | else | 243 | else |
| 240 | { | 244 | { |
| 241 | Lisp_Object oquit; | ||
| 242 | bool saved_pending_signals; | ||
| 243 | EMACS_INT count = 1; | 245 | EMACS_INT count = 1; |
| 244 | #ifdef HAVE_ITIMERSPEC | 246 | #ifdef HAVE_ITIMERSPEC |
| 245 | if (profiler_timer_ok) | 247 | if (profiler_timer_ok) |
| @@ -249,19 +251,8 @@ handle_profiler_signal (int signal) | |||
| 249 | count += overruns; | 251 | count += overruns; |
| 250 | } | 252 | } |
| 251 | #endif | 253 | #endif |
| 252 | /* record_backtrace uses hash functions that call Fequal, which | ||
| 253 | uses QUIT, which can call malloc, which can cause disaster in | ||
| 254 | a signal handler. So inhibit QUIT. */ | ||
| 255 | oquit = Vinhibit_quit; | ||
| 256 | saved_pending_signals = pending_signals; | ||
| 257 | Vinhibit_quit = Qt; | ||
| 258 | pending_signals = 0; | ||
| 259 | |||
| 260 | eassert (HASH_TABLE_P (cpu_log)); | 254 | eassert (HASH_TABLE_P (cpu_log)); |
| 261 | record_backtrace (XHASH_TABLE (cpu_log), count); | 255 | record_backtrace (XHASH_TABLE (cpu_log), count); |
| 262 | |||
| 263 | Vinhibit_quit = oquit; | ||
| 264 | pending_signals = saved_pending_signals; | ||
| 265 | } | 256 | } |
| 266 | } | 257 | } |
| 267 | 258 | ||
| @@ -515,6 +506,66 @@ malloc_probe (size_t size) | |||
| 515 | record_backtrace (XHASH_TABLE (memory_log), min (size, MOST_POSITIVE_FIXNUM)); | 506 | record_backtrace (XHASH_TABLE (memory_log), min (size, MOST_POSITIVE_FIXNUM)); |
| 516 | } | 507 | } |
| 517 | 508 | ||
| 509 | DEFUN ("function-equal", Ffunction_equal, Sfunction_equal, 2, 2, 0, | ||
| 510 | doc: /* Return non-nil if F1 and F2 come from the same source. | ||
| 511 | Used to determine if different closures are just different instances of | ||
| 512 | the same lambda expression, or are really unrelated function. */) | ||
| 513 | (Lisp_Object f1, Lisp_Object f2) | ||
| 514 | { | ||
| 515 | bool res; | ||
| 516 | if (EQ (f1, f2)) | ||
| 517 | res = true; | ||
| 518 | else if (COMPILEDP (f1) && COMPILEDP (f2)) | ||
| 519 | res = EQ (AREF (f1, COMPILED_BYTECODE), AREF (f2, COMPILED_BYTECODE)); | ||
| 520 | else if (CONSP (f1) && CONSP (f2) && CONSP (XCDR (f1)) && CONSP (XCDR (f2)) | ||
| 521 | && EQ (Qclosure, XCAR (f1)) | ||
| 522 | && EQ (Qclosure, XCAR (f2))) | ||
| 523 | res = EQ (XCDR (XCDR (f1)), XCDR (XCDR (f2))); | ||
| 524 | else | ||
| 525 | res = false; | ||
| 526 | return res ? Qt : Qnil; | ||
| 527 | } | ||
| 528 | |||
| 529 | static bool | ||
| 530 | cmpfn_profiler (struct hash_table_test *t, | ||
| 531 | Lisp_Object bt1, Lisp_Object bt2) | ||
| 532 | { | ||
| 533 | if (VECTORP (bt1) && VECTORP (bt2)) | ||
| 534 | { | ||
| 535 | ptrdiff_t i, l = ASIZE (bt1); | ||
| 536 | if (l != ASIZE (bt2)) | ||
| 537 | return false; | ||
| 538 | for (i = 0; i < l; i++) | ||
| 539 | if (NILP (Ffunction_equal (AREF (bt1, i), AREF (bt2, i)))) | ||
| 540 | return false; | ||
| 541 | return true; | ||
| 542 | } | ||
| 543 | else | ||
| 544 | return EQ (bt1, bt2); | ||
| 545 | } | ||
| 546 | |||
| 547 | static EMACS_UINT | ||
| 548 | hashfn_profiler (struct hash_table_test *ht, Lisp_Object bt) | ||
| 549 | { | ||
| 550 | if (VECTORP (bt)) | ||
| 551 | { | ||
| 552 | EMACS_UINT hash = 0; | ||
| 553 | ptrdiff_t i, l = ASIZE (bt); | ||
| 554 | for (i = 0; i < l; i++) | ||
| 555 | { | ||
| 556 | Lisp_Object f = AREF (bt, i); | ||
| 557 | EMACS_UINT hash1 | ||
| 558 | = (COMPILEDP (f) ? XUINT (AREF (f, COMPILED_BYTECODE)) | ||
| 559 | : (CONSP (f) && CONSP (XCDR (f)) && EQ (Qclosure, XCAR (f))) | ||
| 560 | ? XUINT (XCDR (XCDR (f))) : XUINT (f)); | ||
| 561 | hash = hash1 + (hash << 1) + (hash == (EMACS_INT) hash); | ||
| 562 | } | ||
| 563 | return (hash & INTMASK); | ||
| 564 | } | ||
| 565 | else | ||
| 566 | return XUINT (bt); | ||
| 567 | } | ||
| 568 | |||
| 518 | void | 569 | void |
| 519 | syms_of_profiler (void) | 570 | syms_of_profiler (void) |
| 520 | { | 571 | { |
| @@ -527,6 +578,16 @@ If the log gets full, some of the least-seen call-stacks will be evicted | |||
| 527 | to make room for new entries. */); | 578 | to make room for new entries. */); |
| 528 | profiler_log_size = 10000; | 579 | profiler_log_size = 10000; |
| 529 | 580 | ||
| 581 | DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal"); | ||
| 582 | { | ||
| 583 | struct hash_table_test test | ||
| 584 | = { Qprofiler_backtrace_equal, Qnil, Qnil, | ||
| 585 | cmpfn_profiler, hashfn_profiler }; | ||
| 586 | hashtest_profiler = test; | ||
| 587 | } | ||
| 588 | |||
| 589 | defsubr (&Sfunction_equal); | ||
| 590 | |||
| 530 | #ifdef PROFILER_CPU_SUPPORT | 591 | #ifdef PROFILER_CPU_SUPPORT |
| 531 | profiler_cpu_running = NOT_RUNNING; | 592 | profiler_cpu_running = NOT_RUNNING; |
| 532 | cpu_log = Qnil; | 593 | cpu_log = Qnil; |
diff --git a/src/regex.c b/src/regex.c index 7443eff3977..1473551e6cc 100644 --- a/src/regex.c +++ b/src/regex.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | rather than at run-time, so that re_match can be reentrant. | 28 | rather than at run-time, so that re_match can be reentrant. |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | /* AIX requires this to be the first thing in the file. */ | 31 | /* AIX requires this to be the first thing in the file. */ |
| 32 | #if defined _AIX && !defined REGEX_MALLOC | 32 | #if defined _AIX && !defined REGEX_MALLOC |
| 33 | #pragma alloca | 33 | #pragma alloca |
| 34 | #endif | 34 | #endif |
diff --git a/src/xterm.c b/src/xterm.c index 4dd1dee0f75..f89fbabaecc 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -10868,10 +10868,10 @@ default is nil, which is the same as `super'. */); | |||
| 10868 | 10868 | ||
| 10869 | DEFVAR_LISP ("x-keysym-table", Vx_keysym_table, | 10869 | DEFVAR_LISP ("x-keysym-table", Vx_keysym_table, |
| 10870 | doc: /* Hash table of character codes indexed by X keysym codes. */); | 10870 | doc: /* Hash table of character codes indexed by X keysym codes. */); |
| 10871 | Vx_keysym_table = make_hash_table (Qeql, make_number (900), | 10871 | Vx_keysym_table = make_hash_table (hashtest_eql, make_number (900), |
| 10872 | make_float (DEFAULT_REHASH_SIZE), | 10872 | make_float (DEFAULT_REHASH_SIZE), |
| 10873 | make_float (DEFAULT_REHASH_THRESHOLD), | 10873 | make_float (DEFAULT_REHASH_THRESHOLD), |
| 10874 | Qnil, Qnil, Qnil); | 10874 | Qnil); |
| 10875 | } | 10875 | } |
| 10876 | 10876 | ||
| 10877 | #endif /* HAVE_X_WINDOWS */ | 10877 | #endif /* HAVE_X_WINDOWS */ |