@@ -2261,6 +2261,22 @@ function initSearch(rawSearchIndex) {
2261
2261
}
2262
2262
}
2263
2263
} else if ( parsedQuery . foundElems > 0 ) {
2264
+ // Sort input and output so that generic type variables go first and
2265
+ // types with generic parameters go last.
2266
+ // That's because of the way unification is structured: it eats off
2267
+ // the end, and hits a fast path if the last item is a simple atom.
2268
+ const sortQ = ( a , b ) => {
2269
+ const ag = a . generics . length === 0 && a . bindings . size === 0 ;
2270
+ const bg = b . generics . length === 0 && b . bindings . size === 0 ;
2271
+ if ( ag !== bg ) {
2272
+ return ag - bg ;
2273
+ }
2274
+ const ai = a . id > 0 ;
2275
+ const bi = b . id > 0 ;
2276
+ return ai - bi ;
2277
+ } ;
2278
+ parsedQuery . elems . sort ( sortQ ) ;
2279
+ parsedQuery . returned . sort ( sortQ ) ;
2264
2280
for ( let i = 0 , nSearchWords = searchWords . length ; i < nSearchWords ; ++ i ) {
2265
2281
handleArgs ( searchIndex [ i ] , i , results_others ) ;
2266
2282
}
@@ -2823,23 +2839,44 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2823
2839
* @param {Set<number> } fps - Set of distinct items
2824
2840
*/
2825
2841
function buildFunctionTypeFingerprint ( type , output , fps ) {
2826
-
2827
2842
let input = type . id ;
2828
2843
// All forms of `[]` get collapsed down to one thing in the bloom filter.
2829
2844
// Differentiating between arrays and slices, if the user asks for it, is
2830
2845
// still done in the matching algorithm.
2831
2846
if ( input === typeNameIdOfArray || input === typeNameIdOfSlice ) {
2832
2847
input = typeNameIdOfArrayOrSlice ;
2833
2848
}
2849
+ // http://burtleburtle.net/bob/hash/integer.html
2850
+ // ~~ is toInt32. It's used before adding, so
2851
+ // the number stays in safe integer range.
2852
+ const hashint1 = k => {
2853
+ k = ( ~ ~ k + 0x7ed55d16 ) + ( k << 12 ) ;
2854
+ k = ( k ^ 0xc761c23c ) ^ ( k >>> 19 ) ;
2855
+ k = ( ~ ~ k + 0x165667b1 ) + ( k << 5 ) ;
2856
+ k = ( ~ ~ k + 0xd3a2646c ) ^ ( k << 9 ) ;
2857
+ k = ( ~ ~ k + 0xfd7046c5 ) + ( k << 3 ) ;
2858
+ return ( k ^ 0xb55a4f09 ) ^ ( k >>> 16 ) ;
2859
+ } ;
2860
+ const hashint2 = k => {
2861
+ k = ~ k + ( k << 15 ) ;
2862
+ k ^= k >>> 12 ;
2863
+ k += k << 2 ;
2864
+ k ^= k >>> 4 ;
2865
+ k = Math . imul ( k , 2057 ) ;
2866
+ return k ^ ( k >> 16 ) ;
2867
+ } ;
2834
2868
if ( input !== null ) {
2835
- // https://docs.rs/rustc-hash/1.1.0/src/rustc_hash/lib.rs.html#60
2836
- // Rotate is skipped because we're only doing one cycle anyway.
2837
- const h0 = Math . imul ( input , 0x9e3779b9 ) ;
2838
- const h1 = Math . imul ( 479001599 ^ input , 0x9e3779b9 ) ;
2839
- const h2 = Math . imul ( 433494437 ^ input , 0x9e3779b9 ) ;
2840
- output [ 0 ] |= 1 << ( h0 % 32 ) ;
2841
- output [ 1 ] |= 1 << ( h1 % 32 ) ;
2842
- output [ 2 ] |= 1 << ( h2 % 32 ) ;
2869
+ const h0a = hashint1 ( input ) ;
2870
+ const h0b = hashint2 ( input ) ;
2871
+ // Less Hashing, Same Performance: Building a Better Bloom Filter
2872
+ // doi=10.1.1.72.2442
2873
+ const h1a = ~ ~ ( h0a + Math . imul ( h0b , 2 ) ) ;
2874
+ const h1b = ~ ~ ( h0a + Math . imul ( h0b , 3 ) ) ;
2875
+ const h2a = ~ ~ ( h0a + Math . imul ( h0b , 4 ) ) ;
2876
+ const h2b = ~ ~ ( h0a + Math . imul ( h0b , 5 ) ) ;
2877
+ output [ 0 ] |= ( 1 << ( h0a % 32 ) ) | ( 1 << ( h1b % 32 ) ) ;
2878
+ output [ 1 ] |= ( 1 << ( h1a % 32 ) ) | ( 1 << ( h2b % 32 ) ) ;
2879
+ output [ 2 ] |= ( 1 << ( h2a % 32 ) ) | ( 1 << ( h0b % 32 ) ) ;
2843
2880
fps . add ( input ) ;
2844
2881
}
2845
2882
for ( const g of type . generics ) {
@@ -2868,7 +2905,6 @@ ${item.displayPath}<span class="${type}">${name}</span>\
2868
2905
* This function might return 0!
2869
2906
*/
2870
2907
function compareTypeFingerprints ( fullId , queryFingerprint ) {
2871
-
2872
2908
const fh0 = functionTypeFingerprint [ fullId * 4 ] ;
2873
2909
const fh1 = functionTypeFingerprint [ ( fullId * 4 ) + 1 ] ;
2874
2910
const fh2 = functionTypeFingerprint [ ( fullId * 4 ) + 2 ] ;
0 commit comments