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/fns.c | |
| 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/fns.c')
| -rw-r--r-- | src/fns.c | 138 |
1 files changed, 62 insertions, 76 deletions
| @@ -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 | } |