Commit 83c9c6fc authored by Paul Eggert's avatar Paul Eggert

Use float instead of Lisp_Object for rehash_size

* src/alloc.c (purecopy_hash_table):
* src/fns.c (maybe_resize_hash_table, Fmake_hash_table):
(Fhash_table_rehash_size):
* src/lisp.h (struct Lisp_Hash_Table.rehash_size):
The rehash_size member of struct Lisp_Hash_Table is now a
float, not a Lisp_Object.
* src/alloc.c (purecopy_hash_table): Assign members in order.
* src/fns.c (make_hash_table): Use EMACS_INT for size and
float for rehash_size, instead of Lisp_Object for both.
All callers changed.
* src/lisp.h (DEFAULT_REHASH_SIZE): Now float, not double,
and 1 smaller.
* src/print.c (print_object): Simplify by calling
Fhash_table_rehash_size and Fhash_table_rehash_threshold.
Avoid unnecessary NILP.
parent 5cbdaa98
......@@ -133,10 +133,10 @@ it grows automatically. This value specifies how to make the hash table
larger, at that time.
If @var{rehash-size} is an integer, it should be positive, and the hash
table grows by adding that much to the nominal size. If
table grows by adding approximately that much to the nominal size. If
@var{rehash-size} is floating point, it had better be greater
than 1, and the hash table grows by multiplying the old size by that
number.
than 1, and the hash table grows by multiplying the old size by
approximately that number.
The default value is 1.5.
......
......@@ -5453,18 +5453,18 @@ purecopy_hash_table (struct Lisp_Hash_Table *table)
pure_test.user_hash_function = purecopy (table->test.user_hash_function);
pure_test.user_cmp_function = purecopy (table->test.user_cmp_function);
pure->test = pure_test;
pure->header = table->header;
pure->weak = purecopy (Qnil);
pure->rehash_size = purecopy (table->rehash_size);
pure->hash = purecopy (table->hash);
pure->next = purecopy (table->next);
pure->next_free = table->next_free;
pure->index = purecopy (table->index);
pure->count = table->count;
pure->next_free = table->next_free;
pure->pure = table->pure;
pure->rehash_threshold = table->rehash_threshold;
pure->rehash_size = table->rehash_size;
pure->key_and_value = purecopy (table->key_and_value);
pure->test = pure_test;
return pure;
}
......
......@@ -64,9 +64,8 @@ hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
if (NILP (XCHAR_TABLE (table)->extras[1]))
set_char_table_extras
(table, 1,
make_hash_table (hashtest_equal, make_number (DEFAULT_HASH_SIZE),
make_float (DEFAULT_REHASH_SIZE),
DEFAULT_REHASH_THRESHOLD,
make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
Qnil, false));
h = XHASH_TABLE (XCHAR_TABLE (table)->extras[1]);
i = hash_lookup (h, category_set, &hash);
......
......@@ -1013,9 +1013,8 @@ syms_of_module (void)
doc: /* Module global reference table. */);
Vmodule_refs_hash
= make_hash_table (hashtest_eq, make_number (DEFAULT_HASH_SIZE),
make_float (DEFAULT_REHASH_SIZE),
DEFAULT_REHASH_THRESHOLD,
= make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
Qnil, false);
Funintern (Qmodule_refs_hash, Qnil);
......
......@@ -3684,13 +3684,13 @@ allocate_hash_table (void)
`equal' or a symbol denoting a user-defined test named TEST with
test and hash functions USER_TEST and USER_HASH.
Give the table initial capacity SIZE, SIZE >= 0, an integer.
Give the table initial capacity SIZE, 0 <= SIZE <= MOST_POSITIVE_FIXNUM.
If REHASH_SIZE is an integer, it must be > 0, and this hash table's
new size when it becomes full is computed by adding REHASH_SIZE to
its old size. If REHASH_SIZE is a float, it must be > 1.0, and the
table's new size is computed by multiplying its old size with
REHASH_SIZE.
If REHASH_SIZE is equal to a negative integer, this hash table's
new size when it becomes full is computed by subtracting
REHASH_SIZE from its old size. Otherwise it must be positive, and
the table's new size is computed by multiplying its old size by
REHASH_SIZE + 1.
REHASH_THRESHOLD must be a float <= 1.0, and > 0. The table will
be resized when the approximate ratio of table entries to table
......@@ -3704,34 +3704,31 @@ allocate_hash_table (void)
changed after purecopy. */
Lisp_Object
make_hash_table (struct hash_table_test test,
Lisp_Object size, Lisp_Object rehash_size,
float rehash_threshold, Lisp_Object weak,
bool pure)
make_hash_table (struct hash_table_test test, EMACS_INT size,
float rehash_size, float rehash_threshold,
Lisp_Object weak, bool pure)
{
struct Lisp_Hash_Table *h;
Lisp_Object table;
EMACS_INT index_size, sz;
EMACS_INT index_size;
ptrdiff_t i;
double index_float;
/* Preconditions. */
eassert (SYMBOLP (test.name));
eassert (INTEGERP (size) && XINT (size) >= 0);
eassert ((INTEGERP (rehash_size) && XINT (rehash_size) > 0)
|| (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size)));
eassert (0 <= size && size <= MOST_POSITIVE_FIXNUM);
eassert (rehash_size <= -1 || 0 < rehash_size);
eassert (0 < rehash_threshold && rehash_threshold <= 1);
if (XFASTINT (size) == 0)
size = make_number (1);
if (size == 0)
size = 1;
sz = XFASTINT (size);
double threshold = rehash_threshold;
index_float = sz / threshold;
index_float = size / threshold;
index_size = (index_float < INDEX_SIZE_BOUND + 1
? next_almost_prime (index_float)
: INDEX_SIZE_BOUND + 1);
if (INDEX_SIZE_BOUND < max (index_size, 2 * sz))
if (INDEX_SIZE_BOUND < max (index_size, 2 * size))
error ("Hash table too large");
/* Allocate a table and initialize it. */
......@@ -3743,14 +3740,14 @@ make_hash_table (struct hash_table_test test,
h->rehash_threshold = rehash_threshold;
h->rehash_size = rehash_size;
h->count = 0;
h->key_and_value = Fmake_vector (make_number (2 * sz), Qnil);
h->hash = Fmake_vector (size, Qnil);
h->next = Fmake_vector (size, make_number (-1));
h->key_and_value = Fmake_vector (make_number (2 * size), Qnil);
h->hash = Fmake_vector (make_number (size), Qnil);
h->next = Fmake_vector (make_number (size), make_number (-1));
h->index = Fmake_vector (make_number (index_size), make_number (-1));
h->pure = pure;
/* Set up the free list. */
for (i = 0; i < sz - 1; ++i)
for (i = 0; i < size - 1; ++i)
set_hash_next_slot (h, i, i + 1);
h->next_free = 0;
......@@ -3810,22 +3807,21 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
ptrdiff_t old_size = HASH_TABLE_SIZE (h);
EMACS_INT new_size, index_size, nsize;
ptrdiff_t i;
double rehash_size = h->rehash_size;
double index_float;
if (INTEGERP (h->rehash_size))
new_size = old_size + XFASTINT (h->rehash_size);
if (rehash_size < 0)
new_size = old_size - rehash_size;
else
{
double float_new_size = old_size * XFLOAT_DATA (h->rehash_size);
double float_new_size = old_size * (rehash_size + 1);
if (float_new_size < INDEX_SIZE_BOUND + 1)
{
new_size = float_new_size;
if (new_size <= old_size)
new_size = old_size + 1;
}
new_size = float_new_size;
else
new_size = INDEX_SIZE_BOUND + 1;
}
if (new_size <= old_size)
new_size = old_size + 1;
double threshold = h->rehash_threshold;
index_float = new_size / threshold;
index_size = (index_float < INDEX_SIZE_BOUND + 1
......@@ -4408,7 +4404,7 @@ in an error.
usage: (make-hash-table &rest KEYWORD-ARGS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object test, size, rehash_size, weak;
Lisp_Object test, weak;
bool pure;
struct hash_table_test testdesc;
ptrdiff_t i;
......@@ -4448,18 +4444,26 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
pure = i && !NILP (args[i]);
/* See if there's a `:size SIZE' argument. */
i = get_key_arg (QCsize, nargs, args, used);
size = i ? args[i] : Qnil;
if (NILP (size))
size = make_number (DEFAULT_HASH_SIZE);
else if (!INTEGERP (size) || XINT (size) < 0)
signal_error ("Invalid hash table size", size);
Lisp_Object size_arg = i ? args[i] : Qnil;
EMACS_INT size;
if (NILP (size_arg))
size = DEFAULT_HASH_SIZE;
else if (NATNUMP (size_arg))
size = XFASTINT (size_arg);
else
signal_error ("Invalid hash table size", size_arg);
/* Look for `:rehash-size SIZE'. */
float rehash_size;
i = get_key_arg (QCrehash_size, nargs, args, used);
rehash_size = i ? args[i] : make_float (DEFAULT_REHASH_SIZE);
if (! ((INTEGERP (rehash_size) && 0 < XINT (rehash_size))
|| (FLOATP (rehash_size) && 1 < XFLOAT_DATA (rehash_size))))
signal_error ("Invalid hash table rehash size", rehash_size);
if (!i)
rehash_size = DEFAULT_REHASH_SIZE;
else if (INTEGERP (args[i]) && 0 < XINT (args[i]))
rehash_size = - XINT (args[i]);
else if (FLOATP (args[i]) && 0 < (float) (XFLOAT_DATA (args[i]) - 1))
rehash_size = (float) (XFLOAT_DATA (args[i]) - 1);
else
signal_error ("Invalid hash table rehash size", args[i]);
/* Look for `:rehash-threshold THRESHOLD'. */
i = get_key_arg (QCrehash_threshold, nargs, args, used);
......@@ -4513,7 +4517,14 @@ DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size,
doc: /* Return the current rehash size of TABLE. */)
(Lisp_Object table)
{
return check_hash_table (table)->rehash_size;
double rehash_size = check_hash_table (table)->rehash_size;
if (rehash_size < 0)
{
EMACS_INT s = -rehash_size;
return make_number (min (s, MOST_POSITIVE_FIXNUM));
}
else
return make_float (rehash_size + 1);
}
......
......@@ -4017,9 +4017,8 @@ xpm_make_color_table_h (void (**put_func) (Lisp_Object, const char *, int,
{
*put_func = xpm_put_color_table_h;
*get_func = xpm_get_color_table_h;
return make_hash_table (hashtest_equal, make_number (DEFAULT_HASH_SIZE),
make_float (DEFAULT_REHASH_SIZE),
DEFAULT_REHASH_THRESHOLD,
return make_hash_table (hashtest_equal, DEFAULT_HASH_SIZE,
DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
Qnil, false);
}
......
......@@ -1969,11 +1969,6 @@ struct Lisp_Hash_Table
weakness of the table. */
Lisp_Object weak;
/* When the table is resized, and this is an integer, compute the
new size by adding this to the old size. If a float, compute the
new size by multiplying the old size with this factor. */
Lisp_Object rehash_size;
/* Vector of hash codes. If hash[I] is nil, this means that the
I-th entry is unused. */
Lisp_Object hash;
......@@ -2008,6 +2003,13 @@ struct Lisp_Hash_Table
ratio. */
float rehash_threshold;
/* Used when the table is resized. If equal to a negative integer,
the user rehash-size is the integer -REHASH_SIZE, and the new
size is the old size plus -REHASH_SIZE. If positive, the user
rehash-size is the floating-point value REHASH_SIZE + 1, and the
new size is the old size times REHASH_SIZE + 1. */
float rehash_size;
/* Vector of keys and values. The key of item I is found at index
2 * I, the value is found at index 2 * I + 1.
This is gc_marked specially if the table is weak. */
......@@ -2076,9 +2078,9 @@ enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE = 65 };
static float const DEFAULT_REHASH_THRESHOLD = 0.8125;
/* Default factor by which to increase the size of a hash table. */
/* Default factor by which to increase the size of a hash table, minus 1. */
static double const DEFAULT_REHASH_SIZE = 1.5;
static float const DEFAULT_REHASH_SIZE = 1.5 - 1;
/* Combine two integers X and Y for hashing. The result might not fit
into a Lisp integer. */
......@@ -3347,10 +3349,8 @@ extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t);
extern void sweep_weak_hash_tables (void);
EMACS_UINT hash_string (char const *, ptrdiff_t);
EMACS_UINT sxhash (Lisp_Object, int);
Lisp_Object make_hash_table (struct hash_table_test test,
Lisp_Object size, Lisp_Object rehash_size,
float rehash_threshold, Lisp_Object weak,
bool pure);
Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,
Lisp_Object, bool);
ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *);
ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
EMACS_UINT);
......
......@@ -1806,14 +1806,12 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
print_object (h->weak, printcharfun, escapeflag);
}
if (!NILP (h->rehash_size))
{
print_c_string (" rehash-size ", printcharfun);
print_object (h->rehash_size, printcharfun, escapeflag);
}
print_c_string (" rehash-size ", printcharfun);
print_object (Fhash_table_rehash_size (obj),
printcharfun, escapeflag);
print_c_string (" rehash-threshold ", printcharfun);
print_object (make_float (h->rehash_threshold),
print_object (Fhash_table_rehash_threshold (obj),
printcharfun, escapeflag);
if (h->pure)
......
......@@ -44,9 +44,8 @@ make_log (EMACS_INT heap_size, EMACS_INT max_stack_depth)
a special way. This is OK as long as the object is not exposed
to Elisp, i.e. until it is returned by *-profiler-log, after which
it can't be used any more. */
Lisp_Object log = make_hash_table (hashtest_profiler,
make_number (heap_size),
make_float (DEFAULT_REHASH_SIZE),
Lisp_Object log = make_hash_table (hashtest_profiler, heap_size,
DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD,
Qnil, false);
struct Lisp_Hash_Table *h = XHASH_TABLE (log);
......
......@@ -12874,8 +12874,8 @@ keysyms. The default is nil, which is the same as `super'. */);
DEFVAR_LISP ("x-keysym-table", Vx_keysym_table,
doc: /* Hash table of character codes indexed by X keysym codes. */);
Vx_keysym_table = make_hash_table (hashtest_eql, make_number (900),
make_float (DEFAULT_REHASH_SIZE),
Vx_keysym_table = make_hash_table (hashtest_eql, 900,
DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD,
Qnil, false);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment