Skip to content

Commit

Permalink
Use float instead of Lisp_Object for rehash_size
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
eggert committed Feb 21, 2017
1 parent 5cbdaa9 commit 83c9c6f
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 79 deletions.
6 changes: 3 additions & 3 deletions doc/lispref/hash.texi
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
6 changes: 3 additions & 3 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 2 additions & 3 deletions src/category.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions src/emacs-module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
95 changes: 53 additions & 42 deletions src/fns.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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. */
Expand All @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}


Expand Down
5 changes: 2 additions & 3 deletions src/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
22 changes: 11 additions & 11 deletions src/lisp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 4 additions & 6 deletions src/print.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 2 additions & 3 deletions src/profiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions src/xterm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 83c9c6f

Please sign in to comment.