Commit 0de4bb68 authored by Paul Eggert's avatar Paul Eggert
Browse files

Remove arbitrary limit of 2**31 entries in hash tables.

* category.c (hash_get_category_set): Use 'EMACS_UINT' and 'EMACS_INT'
for hashes and hash indexes, instead of 'unsigned' and 'int'.
* ccl.c (ccl_driver): Likewise.
* charset.c (Fdefine_charset_internal): Likewise.
* charset.h (struct charset.hash_index): Likewise.
* composite.c (get_composition_id, gstring_lookup_cache):
(composition_gstring_put_cache): Likewise.
* composite.h (struct composition.hash_index): Likewise.
* dispextern.h (struct image.hash): Likewise.
* fns.c (next_almost_prime, larger_vector, cmpfn_eql):
(cmpfn_equal, cmpfn_user_defined, hashfn_eq, hashfn_eql):
(hashfn_equal, hashfn_user_defined, make_hash_table):
(maybe_resize_hash_table, hash_lookup, hash_put):
(hash_remove_from_table, hash_clear, sweep_weak_table, SXHASH_COMBINE):
(sxhash_string, sxhash_list, sxhash_vector, sxhash_bool_vector):
(Fsxhash, Fgethash, Fputhash, Fmaphash): Likewise.
* image.c (make_image, search_image_cache, lookup_image):
(xpm_put_color_table_h): Likewise.
* lisp.h (struct Lisp_Hash_Table): Likewise, for 'count', 'cmpfn',
and 'hashfn' members.
* minibuf.c (Ftry_completion, Fall_completions, Ftest_completion):
Likewise.
* print.c (print): Likewise.
* alloc.c (allocate_vectorlike): Check for overflow in vector size
calculations.
* ccl.c (ccl_driver): Check for overflow when converting EMACS_INT
to int.
* fns.c, image.c: Remove unnecessary static decls that would otherwise
need to be updated by these changes.
* fns.c (make_hash_table, maybe_resize_hash_table): Check for integer
overflow with large hash tables.
(make_hash_table, maybe_resize_hash_table, Fmake_hash_table):
Prefer the faster XFLOAT_DATA to XFLOATINT where either will do.
(SXHASH_REDUCE): New macro.
(sxhash_string, sxhash_list, sxhash_vector, sxhash_bool_vector):
Use it instead of discarding useful hash info with large hash values.
(sxhash_float): New function.
(sxhash): Use it.  No more need for "& INTMASK" due to above changes.
* lisp.h (FIXNUM_BITS): New macro, useful for SXHASH_REDUCE etc.
(MOST_NEGATIVE_FIXNUM, MOST_POSITIVE_FIXNUM, INTMASK): Rewrite
to use FIXNUM_BITS, as this simplifies things.
(next_almost_prime, larger_vector, sxhash, hash_lookup, hash_put):
Adjust signatures to match updated version of code.
(consing_since_gc): Now EMACS_INT, since a single hash table can
use more than INT_MAX bytes.
parent b9627cfb
2011-05-31 Paul Eggert <eggert@cs.ucla.edu>
Remove arbitrary limit of 2**31 entries in hash tables.
* category.c (hash_get_category_set): Use 'EMACS_UINT' and 'EMACS_INT'
for hashes and hash indexes, instead of 'unsigned' and 'int'.
* ccl.c (ccl_driver): Likewise.
* charset.c (Fdefine_charset_internal): Likewise.
* charset.h (struct charset.hash_index): Likewise.
* composite.c (get_composition_id, gstring_lookup_cache):
(composition_gstring_put_cache): Likewise.
* composite.h (struct composition.hash_index): Likewise.
* dispextern.h (struct image.hash): Likewise.
* fns.c (next_almost_prime, larger_vector, cmpfn_eql):
(cmpfn_equal, cmpfn_user_defined, hashfn_eq, hashfn_eql):
(hashfn_equal, hashfn_user_defined, make_hash_table):
(maybe_resize_hash_table, hash_lookup, hash_put):
(hash_remove_from_table, hash_clear, sweep_weak_table, SXHASH_COMBINE):
(sxhash_string, sxhash_list, sxhash_vector, sxhash_bool_vector):
(Fsxhash, Fgethash, Fputhash, Fmaphash): Likewise.
* image.c (make_image, search_image_cache, lookup_image):
(xpm_put_color_table_h): Likewise.
* lisp.h (struct Lisp_Hash_Table): Likewise, for 'count', 'cmpfn',
and 'hashfn' members.
* minibuf.c (Ftry_completion, Fall_completions, Ftest_completion):
Likewise.
* print.c (print): Likewise.
* alloc.c (allocate_vectorlike): Check for overflow in vector size
calculations.
* ccl.c (ccl_driver): Check for overflow when converting EMACS_INT
to int.
* fns.c, image.c: Remove unnecessary static decls that would otherwise
need to be updated by these changes.
* fns.c (make_hash_table, maybe_resize_hash_table): Check for integer
overflow with large hash tables.
(make_hash_table, maybe_resize_hash_table, Fmake_hash_table):
Prefer the faster XFLOAT_DATA to XFLOATINT where either will do.
(SXHASH_REDUCE): New macro.
(sxhash_string, sxhash_list, sxhash_vector, sxhash_bool_vector):
Use it instead of discarding useful hash info with large hash values.
(sxhash_float): New function.
(sxhash): Use it. No more need for "& INTMASK" due to above changes.
* lisp.h (FIXNUM_BITS): New macro, useful for SXHASH_REDUCE etc.
(MOST_NEGATIVE_FIXNUM, MOST_POSITIVE_FIXNUM, INTMASK): Rewrite
to use FIXNUM_BITS, as this simplifies things.
(next_almost_prime, larger_vector, sxhash, hash_lookup, hash_put):
Adjust signatures to match updated version of code.
(consing_since_gc): Now EMACS_INT, since a single hash table can
use more than INT_MAX bytes.
2011-05-31 Paul Eggert <eggert@cs.ucla.edu> 2011-05-31 Paul Eggert <eggert@cs.ucla.edu>
Use 'inline', not 'INLINE'. Use 'inline', not 'INLINE'.
......
...@@ -157,7 +157,7 @@ struct emacs_globals globals; ...@@ -157,7 +157,7 @@ struct emacs_globals globals;
/* Number of bytes of consing done since the last gc. */ /* Number of bytes of consing done since the last gc. */
int consing_since_gc; EMACS_INT consing_since_gc;
/* Similar minimum, computed from Vgc_cons_percentage. */ /* Similar minimum, computed from Vgc_cons_percentage. */
...@@ -2788,6 +2788,11 @@ allocate_vectorlike (EMACS_INT len) ...@@ -2788,6 +2788,11 @@ allocate_vectorlike (EMACS_INT len)
{ {
struct Lisp_Vector *p; struct Lisp_Vector *p;
size_t nbytes; size_t nbytes;
int header_size = offsetof (struct Lisp_Vector, contents);
int word_size = sizeof p->contents[0];
if ((SIZE_MAX - header_size) / word_size < len)
memory_full ();
MALLOC_BLOCK_INPUT; MALLOC_BLOCK_INPUT;
...@@ -2801,8 +2806,7 @@ allocate_vectorlike (EMACS_INT len) ...@@ -2801,8 +2806,7 @@ allocate_vectorlike (EMACS_INT len)
/* This gets triggered by code which I haven't bothered to fix. --Stef */ /* This gets triggered by code which I haven't bothered to fix. --Stef */
/* eassert (!handling_signal); */ /* eassert (!handling_signal); */
nbytes = (offsetof (struct Lisp_Vector, contents) nbytes = header_size + len * word_size;
+ len * sizeof p->contents[0]);
p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE);
#ifdef DOUG_LEA_MALLOC #ifdef DOUG_LEA_MALLOC
......
...@@ -67,8 +67,8 @@ static Lisp_Object ...@@ -67,8 +67,8 @@ static Lisp_Object
hash_get_category_set (Lisp_Object table, Lisp_Object category_set) hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
{ {
struct Lisp_Hash_Table *h; struct Lisp_Hash_Table *h;
int i; EMACS_INT i;
unsigned hash; EMACS_UINT hash;
if (NILP (XCHAR_TABLE (table)->extras[1])) if (NILP (XCHAR_TABLE (table)->extras[1]))
XCHAR_TABLE (table)->extras[1] XCHAR_TABLE (table)->extras[1]
......
...@@ -1307,15 +1307,15 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size ...@@ -1307,15 +1307,15 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
: -1)); : -1));
h = GET_HASH_TABLE (eop); h = GET_HASH_TABLE (eop);
op = hash_lookup (h, make_number (reg[RRR]), NULL); eop = hash_lookup (h, make_number (reg[RRR]), NULL);
if (op >= 0) if (eop >= 0)
{ {
Lisp_Object opl; Lisp_Object opl;
opl = HASH_VALUE (h, op); opl = HASH_VALUE (h, eop);
if (! CHARACTERP (opl)) if (! (IN_INT_RANGE (eop) && CHARACTERP (opl)))
CCL_INVALID_CMD; CCL_INVALID_CMD;
reg[RRR] = charset_unicode; reg[RRR] = charset_unicode;
reg[rrr] = op; reg[rrr] = eop;
reg[7] = 1; /* r7 true for success */ reg[7] = 1; /* r7 true for success */
} }
else else
...@@ -1334,11 +1334,11 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size ...@@ -1334,11 +1334,11 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]); i = CCL_DECODE_CHAR (reg[RRR], reg[rrr]);
h = GET_HASH_TABLE (eop); h = GET_HASH_TABLE (eop);
op = hash_lookup (h, make_number (i), NULL); eop = hash_lookup (h, make_number (i), NULL);
if (op >= 0) if (eop >= 0)
{ {
Lisp_Object opl; Lisp_Object opl;
opl = HASH_VALUE (h, op); opl = HASH_VALUE (h, eop);
if (! (INTEGERP (opl) && IN_INT_RANGE (XINT (opl)))) if (! (INTEGERP (opl) && IN_INT_RANGE (XINT (opl))))
CCL_INVALID_CMD; CCL_INVALID_CMD;
reg[RRR] = XINT (opl); reg[RRR] = XINT (opl);
......
...@@ -849,7 +849,7 @@ usage: (define-charset-internal ...) */) ...@@ -849,7 +849,7 @@ usage: (define-charset-internal ...) */)
/* Charset attr vector. */ /* Charset attr vector. */
Lisp_Object attrs; Lisp_Object attrs;
Lisp_Object val; Lisp_Object val;
unsigned hash_code; EMACS_UINT hash_code;
struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table); struct Lisp_Hash_Table *hash_table = XHASH_TABLE (Vcharset_hash_table);
int i, j; int i, j;
struct charset charset; struct charset charset;
......
...@@ -146,7 +146,7 @@ struct charset ...@@ -146,7 +146,7 @@ struct charset
int id; int id;
/* Index to Vcharset_hash_table. */ /* Index to Vcharset_hash_table. */
int hash_index; EMACS_INT hash_index;
/* Dimension of the charset: 1, 2, 3, or 4. */ /* Dimension of the charset: 1, 2, 3, or 4. */
int dimension; int dimension;
......
...@@ -179,8 +179,8 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars, ...@@ -179,8 +179,8 @@ get_composition_id (EMACS_INT charpos, EMACS_INT bytepos, EMACS_INT nchars,
Lisp_Object id, length, components, key, *key_contents; Lisp_Object id, length, components, key, *key_contents;
int glyph_len; int glyph_len;
struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table); struct Lisp_Hash_Table *hash_table = XHASH_TABLE (composition_hash_table);
int hash_index; EMACS_INT hash_index;
unsigned hash_code; EMACS_UINT hash_code;
struct composition *cmp; struct composition *cmp;
EMACS_INT i; EMACS_INT i;
int ch; int ch;
...@@ -656,7 +656,7 @@ static Lisp_Object ...@@ -656,7 +656,7 @@ static Lisp_Object
gstring_lookup_cache (Lisp_Object header) gstring_lookup_cache (Lisp_Object header)
{ {
struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
int i = hash_lookup (h, header, NULL); EMACS_INT i = hash_lookup (h, header, NULL);
return (i >= 0 ? HASH_VALUE (h, i) : Qnil); return (i >= 0 ? HASH_VALUE (h, i) : Qnil);
} }
...@@ -665,7 +665,7 @@ Lisp_Object ...@@ -665,7 +665,7 @@ Lisp_Object
composition_gstring_put_cache (Lisp_Object gstring, EMACS_INT len) composition_gstring_put_cache (Lisp_Object gstring, EMACS_INT len)
{ {
struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table); struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
unsigned hash; EMACS_UINT hash;
Lisp_Object header, copy; Lisp_Object header, copy;
EMACS_INT i; EMACS_INT i;
......
...@@ -186,7 +186,7 @@ struct composition { ...@@ -186,7 +186,7 @@ struct composition {
enum composition_method method; enum composition_method method;
/* Index to the composition hash table. */ /* Index to the composition hash table. */
int hash_index; EMACS_INT hash_index;
/* For which font we have calculated the remaining members. The /* For which font we have calculated the remaining members. The
actual type is device dependent. */ actual type is device dependent. */
......
...@@ -2798,7 +2798,7 @@ struct image ...@@ -2798,7 +2798,7 @@ struct image
} data; } data;
/* Hash value of image specification to speed up comparisons. */ /* Hash value of image specification to speed up comparisons. */
unsigned hash; EMACS_UINT hash;
/* Image id of this image. */ /* Image id of this image. */
int id; int id;
......
...@@ -3358,21 +3358,6 @@ static Lisp_Object Qhash_table_test, Qkey_or_value, Qkey_and_value; ...@@ -3358,21 +3358,6 @@ static Lisp_Object Qhash_table_test, Qkey_or_value, Qkey_and_value;
static struct Lisp_Hash_Table *check_hash_table (Lisp_Object); static struct Lisp_Hash_Table *check_hash_table (Lisp_Object);
static size_t get_key_arg (Lisp_Object, size_t, Lisp_Object *, char *); static size_t get_key_arg (Lisp_Object, size_t, Lisp_Object *, char *);
static void maybe_resize_hash_table (struct Lisp_Hash_Table *); static void maybe_resize_hash_table (struct Lisp_Hash_Table *);
static int cmpfn_eql (struct Lisp_Hash_Table *, Lisp_Object, unsigned,
Lisp_Object, unsigned);
static int cmpfn_equal (struct Lisp_Hash_Table *, Lisp_Object, unsigned,
Lisp_Object, unsigned);
static int cmpfn_user_defined (struct Lisp_Hash_Table *, Lisp_Object,
unsigned, Lisp_Object, unsigned);
static unsigned hashfn_eq (struct Lisp_Hash_Table *, Lisp_Object);
static unsigned hashfn_eql (struct Lisp_Hash_Table *, Lisp_Object);
static unsigned hashfn_equal (struct Lisp_Hash_Table *, Lisp_Object);
static unsigned hashfn_user_defined (struct Lisp_Hash_Table *,
Lisp_Object);
static unsigned sxhash_string (unsigned char *, int);
static unsigned sxhash_list (Lisp_Object, int);
static unsigned sxhash_vector (Lisp_Object, int);
static unsigned sxhash_bool_vector (Lisp_Object);
static int sweep_weak_table (struct Lisp_Hash_Table *, int); static int sweep_weak_table (struct Lisp_Hash_Table *, int);
...@@ -3395,8 +3380,8 @@ check_hash_table (Lisp_Object obj) ...@@ -3395,8 +3380,8 @@ check_hash_table (Lisp_Object obj)
/* Value is the next integer I >= N, N >= 0 which is "almost" a prime /* Value is the next integer I >= N, N >= 0 which is "almost" a prime
number. */ number. */
int EMACS_INT
next_almost_prime (int n) next_almost_prime (EMACS_INT n)
{ {
if (n % 2 == 0) if (n % 2 == 0)
n += 1; n += 1;
...@@ -3436,10 +3421,10 @@ get_key_arg (Lisp_Object key, size_t nargs, Lisp_Object *args, char *used) ...@@ -3436,10 +3421,10 @@ get_key_arg (Lisp_Object key, size_t nargs, Lisp_Object *args, char *used)
vector that are not copied from VEC are set to INIT. */ vector that are not copied from VEC are set to INIT. */
Lisp_Object Lisp_Object
larger_vector (Lisp_Object vec, int new_size, Lisp_Object init) larger_vector (Lisp_Object vec, EMACS_INT new_size, Lisp_Object init)
{ {
struct Lisp_Vector *v; struct Lisp_Vector *v;
int i, old_size; EMACS_INT i, old_size;
xassert (VECTORP (vec)); xassert (VECTORP (vec));
old_size = ASIZE (vec); old_size = ASIZE (vec);
...@@ -3463,7 +3448,9 @@ larger_vector (Lisp_Object vec, int new_size, Lisp_Object init) ...@@ -3463,7 +3448,9 @@ larger_vector (Lisp_Object vec, int new_size, Lisp_Object init)
KEY2 are the same. */ KEY2 are the same. */
static int static int
cmpfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Lisp_Object key2, unsigned int hash2) cmpfn_eql (struct Lisp_Hash_Table *h,
Lisp_Object key1, EMACS_UINT hash1,
Lisp_Object key2, EMACS_UINT hash2)
{ {
return (FLOATP (key1) return (FLOATP (key1)
&& FLOATP (key2) && FLOATP (key2)
...@@ -3476,7 +3463,9 @@ cmpfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Lisp ...@@ -3476,7 +3463,9 @@ cmpfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Lisp
KEY2 are the same. */ KEY2 are the same. */
static int static int
cmpfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Lisp_Object key2, unsigned int hash2) cmpfn_equal (struct Lisp_Hash_Table *h,
Lisp_Object key1, EMACS_UINT hash1,
Lisp_Object key2, EMACS_UINT hash2)
{ {
return hash1 == hash2 && !NILP (Fequal (key1, key2)); return hash1 == hash2 && !NILP (Fequal (key1, key2));
} }
...@@ -3487,7 +3476,9 @@ cmpfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Li ...@@ -3487,7 +3476,9 @@ cmpfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Li
if KEY1 and KEY2 are the same. */ if KEY1 and KEY2 are the same. */
static int static int
cmpfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int hash1, Lisp_Object key2, unsigned int hash2) cmpfn_user_defined (struct Lisp_Hash_Table *h,
Lisp_Object key1, EMACS_UINT hash1,
Lisp_Object key2, EMACS_UINT hash2)
{ {
if (hash1 == hash2) if (hash1 == hash2)
{ {
...@@ -3507,10 +3498,10 @@ cmpfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int ha ...@@ -3507,10 +3498,10 @@ cmpfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key1, unsigned int ha
`eq' to compare keys. The hash code returned is guaranteed to fit `eq' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */ in a Lisp integer. */
static unsigned static EMACS_UINT
hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key) hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key)
{ {
unsigned hash = XUINT (key) ^ XTYPE (key); EMACS_UINT hash = XUINT (key) ^ XTYPE (key);
xassert ((hash & ~INTMASK) == 0); xassert ((hash & ~INTMASK) == 0);
return hash; return hash;
} }
...@@ -3520,10 +3511,10 @@ hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key) ...@@ -3520,10 +3511,10 @@ hashfn_eq (struct Lisp_Hash_Table *h, Lisp_Object key)
`eql' to compare keys. The hash code returned is guaranteed to fit `eql' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */ in a Lisp integer. */
static unsigned static EMACS_UINT
hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key) hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key)
{ {
unsigned hash; EMACS_UINT hash;
if (FLOATP (key)) if (FLOATP (key))
hash = sxhash (key, 0); hash = sxhash (key, 0);
else else
...@@ -3537,10 +3528,10 @@ hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key) ...@@ -3537,10 +3528,10 @@ hashfn_eql (struct Lisp_Hash_Table *h, Lisp_Object key)
`equal' to compare keys. The hash code returned is guaranteed to fit `equal' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */ in a Lisp integer. */
static unsigned static EMACS_UINT
hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key) hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key)
{ {
unsigned hash = sxhash (key, 0); EMACS_UINT hash = sxhash (key, 0);
xassert ((hash & ~INTMASK) == 0); xassert ((hash & ~INTMASK) == 0);
return hash; return hash;
} }
...@@ -3550,7 +3541,7 @@ hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key) ...@@ -3550,7 +3541,7 @@ hashfn_equal (struct Lisp_Hash_Table *h, Lisp_Object key)
user-defined function to compare keys. The hash code returned is user-defined function to compare keys. The hash code returned is
guaranteed to fit in a Lisp integer. */ guaranteed to fit in a Lisp integer. */
static unsigned static EMACS_UINT
hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key) hashfn_user_defined (struct Lisp_Hash_Table *h, Lisp_Object key)
{ {
Lisp_Object args[2], hash; Lisp_Object args[2], hash;
...@@ -3593,26 +3584,33 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size, ...@@ -3593,26 +3584,33 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size,
{ {
struct Lisp_Hash_Table *h; struct Lisp_Hash_Table *h;
Lisp_Object table; Lisp_Object table;
int index_size, i, sz; EMACS_INT index_size, i, sz;
double index_float;
/* Preconditions. */ /* Preconditions. */
xassert (SYMBOLP (test)); xassert (SYMBOLP (test));
xassert (INTEGERP (size) && XINT (size) >= 0); xassert (INTEGERP (size) && XINT (size) >= 0);
xassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0) xassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
|| (FLOATP (rehash_size) && XFLOATINT (rehash_size) > 1.0)); || (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size)));
xassert (FLOATP (rehash_threshold) xassert (FLOATP (rehash_threshold)
&& XFLOATINT (rehash_threshold) > 0 && 0 < XFLOAT_DATA (rehash_threshold)
&& XFLOATINT (rehash_threshold) <= 1.0); && XFLOAT_DATA (rehash_threshold) <= 1.0);
if (XFASTINT (size) == 0) if (XFASTINT (size) == 0)
size = make_number (1); size = make_number (1);
sz = XFASTINT (size);
index_float = sz / XFLOAT_DATA (rehash_threshold);
index_size = (index_float < MOST_POSITIVE_FIXNUM + 1
? next_almost_prime (index_float)
: MOST_POSITIVE_FIXNUM + 1);
if (MOST_POSITIVE_FIXNUM < max (index_size, 2 * sz))
error ("Hash table too large");
/* Allocate a table and initialize it. */ /* Allocate a table and initialize it. */
h = allocate_hash_table (); h = allocate_hash_table ();
/* Initialize hash table slots. */ /* Initialize hash table slots. */
sz = XFASTINT (size);
h->test = test; h->test = test;
if (EQ (test, Qeql)) if (EQ (test, Qeql))
{ {
...@@ -3644,8 +3642,6 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size, ...@@ -3644,8 +3642,6 @@ make_hash_table (Lisp_Object test, Lisp_Object size, Lisp_Object rehash_size,
h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil); h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil);
h->hash = Fmake_vector (size, Qnil); h->hash = Fmake_vector (size, Qnil);
h->next = Fmake_vector (size, Qnil); h->next = Fmake_vector (size, Qnil);
/* Cast to int here avoids losing with gcc 2.95 on Tru64/Alpha... */
index_size = next_almost_prime ((int) (sz / XFLOATINT (rehash_threshold)));
h->index = Fmake_vector (make_number (index_size), Qnil); h->index = Fmake_vector (make_number (index_size), Qnil);
/* Set up the free list. */ /* Set up the free list. */
...@@ -3709,20 +3705,29 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) ...@@ -3709,20 +3705,29 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
{ {
if (NILP (h->next_free)) if (NILP (h->next_free))
{ {
int old_size = HASH_TABLE_SIZE (h); EMACS_INT old_size = HASH_TABLE_SIZE (h);
int i, new_size, index_size; EMACS_INT i, new_size, index_size;
EMACS_INT nsize; EMACS_INT nsize;
double index_float;
if (INTEGERP (h->rehash_size)) if (INTEGERP (h->rehash_size))
new_size = old_size + XFASTINT (h->rehash_size); new_size = old_size + XFASTINT (h->rehash_size);
else else
new_size = old_size * XFLOATINT (h->rehash_size); {
new_size = max (old_size + 1, new_size); double float_new_size = old_size * XFLOAT_DATA (h->rehash_size);
index_size = next_almost_prime ((int) if (float_new_size < MOST_POSITIVE_FIXNUM + 1)
(new_size {
/ XFLOATINT (h->rehash_threshold))); new_size = float_new_size;
/* Assignment to EMACS_INT stops GCC whining about limited range if (new_size <= old_size)
of data type. */ new_size = old_size + 1;
}
else
new_size = MOST_POSITIVE_FIXNUM + 1;
}
index_float = new_size / XFLOAT_DATA (h->rehash_threshold);
index_size = (index_float < MOST_POSITIVE_FIXNUM + 1
? next_almost_prime (index_float)
: MOST_POSITIVE_FIXNUM + 1);
nsize = max (index_size, 2 * new_size); nsize = max (index_size, 2 * new_size);
if (nsize > MOST_POSITIVE_FIXNUM) if (nsize > MOST_POSITIVE_FIXNUM)
error ("Hash table too large to resize"); error ("Hash table too large to resize");
...@@ -3756,8 +3761,8 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) ...@@ -3756,8 +3761,8 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
for (i = 0; i < old_size; ++i) for (i = 0; i < old_size; ++i)
if (!NILP (HASH_HASH (h, i))) if (!NILP (HASH_HASH (h, i)))
{ {
unsigned hash_code = XUINT (HASH_HASH (h, i)); EMACS_UINT hash_code = XUINT (HASH_HASH (h, i));
int start_of_bucket = hash_code % ASIZE (h->index); EMACS_INT start_of_bucket = hash_code % ASIZE (h->index);
HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket); HASH_NEXT (h, i) = HASH_INDEX (h, start_of_bucket);
HASH_INDEX (h, start_of_bucket) = make_number (i); HASH_INDEX (h, start_of_bucket) = make_number (i);
} }
...@@ -3769,11 +3774,11 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h) ...@@ -3769,11 +3774,11 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
the hash code of KEY. Value is the index of the entry in H the hash code of KEY. Value is the index of the entry in H
matching KEY, or -1 if not found. */ matching KEY, or -1 if not found. */
int EMACS_INT
hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, unsigned int *hash) hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash)
{ {
unsigned hash_code; EMACS_UINT hash_code;
int start_of_bucket; EMACS_INT start_of_bucket;
Lisp_Object idx; Lisp_Object idx;
hash_code = h->hashfn (h, key); hash_code = h->hashfn (h, key);
...@@ -3786,7 +3791,7 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, unsigned int *hash) ...@@ -3786,7 +3791,7 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, unsigned int *hash)
/* We need not gcpro idx since it's either an integer or nil. */ /* We need not gcpro idx since it's either an integer or nil. */
while (!NILP (idx)) while (!NILP (idx))
{ {
int i = XFASTINT (idx); EMACS_INT i = XFASTINT (idx);
if (EQ (key, HASH_KEY (h, i)) if (EQ (key, HASH_KEY (h, i))
|| (h->cmpfn || (h->cmpfn
&& h->cmpfn (h, key, hash_code, && h->cmpfn (h, key, hash_code,
...@@ -3803,10 +3808,11 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, unsigned int *hash) ...@@ -3803,10 +3808,11 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, unsigned int *hash)
HASH is a previously computed hash code of KEY. HASH is a previously computed hash code of KEY.
Value is the index of the entry in H matching KEY. */ Value is the index of the entry in H matching KEY. */
int EMACS_INT
hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, unsigned int hash) hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
EMACS_UINT hash)
{ {
int start_of_bucket, i; EMACS_INT start_of_bucket, i;
xassert ((hash & ~INTMASK) == 0); xassert ((hash & ~INTMASK) == 0);