diff --git a/src/svalue.c b/src/svalue.c index 0f960b2e53b8c5c02b4adb1e29f1c9df74bcae7f..40704c84730ddc01d58db6c9cd00bc9eda604951 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -408,6 +408,14 @@ PMOD_EXPORT void assign_short_svalue(union anything *to, } } +static INLINE unsigned INT32 hash_ptr(void * ptr) { +#if SIZEOF_CHAR_P > 4 + return DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(ptr) >> 2)); +#else + return DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(ptr))); +#endif +} + PMOD_EXPORT unsigned INT32 hash_svalue(const struct svalue *s) { unsigned INT32 q; @@ -450,11 +458,19 @@ PMOD_EXPORT unsigned INT32 hash_svalue(const struct svalue *s) } /* FALL THROUGH */ default: -#if SIZEOF_CHAR_P > 4 - q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr) >> 2)); -#else - q=DO_NOT_WARN((unsigned INT32)(PTR_TO_INT(s->u.ptr))); -#endif + q = hash_ptr(s->u.ptr); + break; + case T_FUNCTION: + if ((SUBTYPEOF(*s) != FUNCTION_BUILTIN) && s->u.object + && s->u.object->prog == pike_trampoline_program) { + + struct pike_trampoline *tramp = get_storage(s->u.object, pike_trampoline_program); + if (tramp) { + q = (unsigned INT32)tramp->func ^ hash_ptr(tramp->frame); + break; + } + } + q = hash_ptr(s->u.ptr); break; case T_INT: q=(unsigned INT32) s->u.integer; diff --git a/src/testsuite.in b/src/testsuite.in index 2091c4048778dbac009ed1541f66f7855d715f91..74ca4df03c00db3e947f1e90201da83690f94c76 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -11035,6 +11035,23 @@ test_hash_value(time) test_hash_value(ADT.Stack) dnl test_hash_value(String) test_hash_value(typeof(true)) +test_any([[ + int v = 0; + + void trampoline() { + v = 1; + }; + + int(0..1) check_hash() + { + function f1 = trampoline; + function f2 = trampoline; + return hash_value(f1) == hash_value(f2); + }; + + return check_hash(); +]], 1) + // - indices test_equal(indices("foo"),({0,1,2}))