From 1f02cf226efa6749d10e44b2467bd9f4a8590946 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Thu, 7 Sep 2017 17:29:41 +0100 Subject: [PATCH] fix `eq[v]?` hashing with many collisions Normally, it's impossible to generate lots of `eq?`-hashing collisions, but when the compiler inlines a function, it can duplicate variables in a way that gives each copy the same `eq?` hash code. The immutable-hash tree implementation failed when more than 32 collisions occurred (which triggers a subtree in the collision node). It's similarly very difficult to generate > 32 values that collide on `eqv?` hashes but are not `eqv?` (although it must be possible using exact rationals or complex numbers). --- .../tests/racket/optimize.rktl | 150 ++++++++++++++++++ racket/src/racket/src/hash.c | 2 +- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/pkgs/racket-test-core/tests/racket/optimize.rktl b/pkgs/racket-test-core/tests/racket/optimize.rktl index 1b78069f26..588055e7f9 100644 --- a/pkgs/racket-test-core/tests/racket/optimize.rktl +++ b/pkgs/racket-test-core/tests/racket/optimize.rktl @@ -6043,6 +6043,156 @@ (test 'fail "compilation took too long" (/ b a 1.0)) (loop (sub1 tries))))))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Try a program that triggers lots of inlining, which at one point +;; exposed a bug related to the closing of `lambda` forms within +;; an inlined function. Thanks to Tom Gilray for the test. + +(module inline-a-lot racket/base + ((((((((((((((lambda (x84) + (lambda (x85) + (lambda (x86) + (lambda (x87) + (lambda (x88) + (lambda (x89) + (lambda (x90) + (lambda (x91) + (lambda (x92) + (lambda (x93) + (lambda (x94) + (lambda (x95) + (lambda (x96) + ((lambda (x97) + (x97 + (lambda (x98) + (lambda (x99) + (x98 + (x98 + (x98 (x98 (x98 x99))))))))) + (x84 + (lambda (x100) + (lambda (x101) + ((((x95 + (lambda (x102) + (lambda (x103) x103))) + x101) + (lambda (x104) + (lambda (x105) + (lambda (x106) + (x105 x106))))) + (lambda (x107) + ((x93 x101) + (x100 + ((x92 x101) + (lambda (x108) + (lambda (x109) + (x108 + x109))))))))))))))))))))))))) + ((lambda (x110) (x110 x110)) + (lambda (x111) + (lambda (x112) + (x112 (lambda (x113) (((x111 x111) x112) x113))))))) + (lambda (x114) + ((x114 + (lambda (x115) + (lambda (x116) + (lambda (x117) + (lambda (x118) (x118 (lambda (x119) x119))))))) + (lambda (x120) + (lambda (x121) + (lambda (x122) (x121 (lambda (x123) x123)))))))) + (lambda (x124) + (lambda (x125) + (lambda (x126) (lambda (x127) ((x126 x124) x125)))))) + (lambda (x128) + ((x128 (lambda (x129) (lambda (x130) x129))) + (lambda (x131) (lambda (x132) x132))))) + (lambda (x133) + ((x133 (lambda (x134) (lambda (x135) x135))) + (lambda (x136) (lambda (x137) x137))))) + (lambda (x138) + (lambda (x139) (lambda (x140) (x139 ((x138 x139) x140)))))) + (lambda (x141) + (lambda (x142) + (lambda (x143) + (((x141 (lambda (x144) (lambda (x145) (x145 (x144 x142))))) + (lambda (x146) x143)) + (lambda (x147) x147)))))) + (lambda (x148) + (lambda (x149) + (lambda (x150) (lambda (x151) ((x149 x150) ((x148 x150) x151))))))) + (lambda (x152) + (lambda (x153) + ((x153 + (lambda (x154) + (lambda (x155) + (lambda (x156) + (((x154 (lambda (x157) (lambda (x158) (x158 (x157 x155))))) + (lambda (x159) x156)) + (lambda (x160) x160)))))) + x152)))) + (lambda (x161) + (lambda (x162) + (lambda (x163) (lambda (x164) ((x161 (x162 x163)) x164)))))) + (lambda (x165) + ((x165 + (lambda (x166) + (lambda (x167) (lambda (x168) (x168 (lambda (x169) x169)))))) + (lambda (x170) (lambda (x171) (x170 (lambda (x172) x172))))))) + (lambda (x173) + (lambda (x174) + ((((lambda (x175) + ((x175 + (lambda (x176) + (lambda (x177) (lambda (x178) (x178 (lambda (x179) x179)))))) + (lambda (x180) (lambda (x181) (x180 (lambda (x182) x182)))))) + (((lambda (x183) + (lambda (x184) + ((x184 + (lambda (x185) + (lambda (x186) + (lambda (x187) + (((x185 + (lambda (x188) (lambda (x189) (x189 (x188 x186))))) + (lambda (x190) x187)) + (lambda (x191) x191)))))) + x183))) + x173) + x174)) + (lambda (x192) + ((((lambda (x193) + ((x193 + (lambda (x194) + (lambda (x195) + (lambda (x196) (x196 (lambda (x197) x197)))))) + (lambda (x198) (lambda (x199) (x198 (lambda (x200) x200)))))) + (((lambda (x201) + (lambda (x202) + ((x202 + (lambda (x203) + (lambda (x204) + (lambda (x205) + (((x203 + (lambda (x206) + (lambda (x207) (x207 (x206 x204))))) + (lambda (x208) x205)) + (lambda (x209) x209)))))) + x201))) + x174) + x173)) + (lambda (x210) + (lambda (x211) (lambda (x212) (x211 (lambda (x213) x213)))))) + (lambda (x214) + (lambda (x215) (lambda (x216) (x216 (lambda (x217) x217)))))))) + (lambda (x218) + (lambda (x219) (lambda (x220) (x220 (lambda (x221) x221))))))))) + (lambda (x222) + ((x222 + (lambda (x223) + (lambda (x224) (lambda (x225) (x225 (lambda (x226) x226)))))) + (lambda (x227) + (lambda (x228) (lambda (x229) (x228 (lambda (x230) x230))))))))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/racket/src/hash.c b/racket/src/racket/src/hash.c index 5d1a18ec9d..242ec5cd6e 100644 --- a/racket/src/racket/src/hash.c +++ b/racket/src/racket/src/hash.c @@ -2494,7 +2494,7 @@ XFORM_NONGCING Scheme_Object *_mzHAMT_VAL(Scheme_Hash_Tree *ht, int pos, int pop XFORM_NONGCING uintptr_t mzHAMT_KEY_CODE(Scheme_Object *o) { while (1) { - if (HASHTR_COLLISIONP(o)) + if (HASHTR_COLLISIONP(o) || HASHTR_SUBTREEP(o)) o = ((Scheme_Hash_Tree *)o)->els[0]; else { uintptr_t h;