aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2024-08-18 14:20:36 +0200
committerMattias EngdegÄrd2024-08-21 14:14:39 +0200
commit46f3452b30f39a69f610faab58c1490b34dd367d (patch)
tree229ea33505e1c3bdfd27e1511babe858c4ee621a /src
parent5d0e5f086505848631f9f79926b526597fc60688 (diff)
downloademacs-46f3452b30f39a69f610faab58c1490b34dd367d.tar.gz
emacs-46f3452b30f39a69f610faab58c1490b34dd367d.zip
Simplify and speed up make-hash-table argument parsing
* src/fns.c (get_key_arg): Remove. (Fmake_hash_table): Traverse argument list once only. Don't allocate a helper array. Use faster comparisons.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c112
1 files changed, 42 insertions, 70 deletions
diff --git a/src/fns.c b/src/fns.c
index 80794bc73a0..80ae554c86e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4637,30 +4637,6 @@ next_almost_prime (EMACS_INT n)
4637 return n; 4637 return n;
4638} 4638}
4639 4639
4640
4641/* Find KEY in ARGS which has size NARGS. Don't consider indices for
4642 which USED[I] is non-zero. If found at index I in ARGS, set
4643 USED[I] and USED[I + 1] to 1, and return I + 1. Otherwise return
4644 0. This function is used to extract a keyword/argument pair from
4645 a DEFUN parameter list. */
4646
4647static ptrdiff_t
4648get_key_arg (Lisp_Object key, ptrdiff_t nargs, Lisp_Object *args, char *used)
4649{
4650 ptrdiff_t i;
4651
4652 for (i = 1; i < nargs; i++)
4653 if (!used[i - 1] && EQ (args[i - 1], key))
4654 {
4655 used[i - 1] = 1;
4656 used[i] = 1;
4657 return i;
4658 }
4659
4660 return 0;
4661}
4662
4663
4664/* Return a Lisp vector which has the same contents as VEC but has 4640/* Return a Lisp vector which has the same contents as VEC but has
4665 at least INCR_MIN more entries, where INCR_MIN is positive. 4641 at least INCR_MIN more entries, where INCR_MIN is positive.
4666 If NITEMS_MAX is not -1, do not grow the vector to be any larger 4642 If NITEMS_MAX is not -1, do not grow the vector to be any larger
@@ -5762,32 +5738,43 @@ and ignored.
5762usage: (make-hash-table &rest KEYWORD-ARGS) */) 5738usage: (make-hash-table &rest KEYWORD-ARGS) */)
5763 (ptrdiff_t nargs, Lisp_Object *args) 5739 (ptrdiff_t nargs, Lisp_Object *args)
5764{ 5740{
5765 USE_SAFE_ALLOCA; 5741 Lisp_Object test_arg = Qnil;
5742 Lisp_Object weakness_arg = Qnil;
5743 Lisp_Object size_arg = Qnil;
5744 Lisp_Object purecopy_arg = Qnil;
5745
5746 if (nargs & 1)
5747 error ("Odd number of arguments");
5748 while (nargs >= 2)
5749 {
5750 Lisp_Object arg = maybe_remove_pos_from_symbol (args[--nargs]);
5751 Lisp_Object kw = maybe_remove_pos_from_symbol (args[--nargs]);
5752 if (BASE_EQ (kw, QCtest))
5753 test_arg = arg;
5754 else if (BASE_EQ (kw, QCweakness))
5755 weakness_arg = arg;
5756 else if (BASE_EQ (kw, QCsize))
5757 size_arg = arg;
5758 else if (BASE_EQ (kw, QCpurecopy))
5759 purecopy_arg = arg;
5760 else if (BASE_EQ (kw, QCrehash_threshold) || BASE_EQ (kw, QCrehash_size))
5761 ; /* ignore obsolete keyword arguments */
5762 else
5763 signal_error ("Invalid keyword argument", kw);
5764 }
5766 5765
5767 /* The vector `used' is used to keep track of arguments that 5766 const struct hash_table_test *test;
5768 have been consumed. */ 5767 if (NILP (test_arg) || BASE_EQ (test_arg, Qeql))
5769 char *used = SAFE_ALLOCA (nargs * sizeof *used); 5768 test = &hashtest_eql;
5770 memset (used, 0, nargs * sizeof *used); 5769 else if (BASE_EQ (test_arg, Qeq))
5771 5770 test = &hashtest_eq;
5772 /* See if there's a `:test TEST' among the arguments. */ 5771 else if (BASE_EQ (test_arg, Qequal))
5773 ptrdiff_t i = get_key_arg (QCtest, nargs, args, used); 5772 test = &hashtest_equal;
5774 Lisp_Object test = i ? maybe_remove_pos_from_symbol (args[i]) : Qeql;
5775 const struct hash_table_test *testdesc;
5776 if (BASE_EQ (test, Qeq))
5777 testdesc = &hashtest_eq;
5778 else if (BASE_EQ (test, Qeql))
5779 testdesc = &hashtest_eql;
5780 else if (BASE_EQ (test, Qequal))
5781 testdesc = &hashtest_equal;
5782 else 5773 else
5783 testdesc = get_hash_table_user_test (test); 5774 test = get_hash_table_user_test (test_arg);
5784 5775
5785 /* See if there's a `:purecopy PURECOPY' argument. */ 5776 bool purecopy = !NILP (purecopy_arg);
5786 i = get_key_arg (QCpurecopy, nargs, args, used); 5777
5787 bool purecopy = i && !NILP (args[i]);
5788 /* See if there's a `:size SIZE' argument. */
5789 i = get_key_arg (QCsize, nargs, args, used);
5790 Lisp_Object size_arg = i ? args[i] : Qnil;
5791 EMACS_INT size; 5778 EMACS_INT size;
5792 if (NILP (size_arg)) 5779 if (NILP (size_arg))
5793 size = DEFAULT_HASH_SIZE; 5780 size = DEFAULT_HASH_SIZE;
@@ -5796,36 +5783,21 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
5796 else 5783 else
5797 signal_error ("Invalid hash table size", size_arg); 5784 signal_error ("Invalid hash table size", size_arg);
5798 5785
5799 /* Look for `:weakness WEAK'. */
5800 i = get_key_arg (QCweakness, nargs, args, used);
5801 Lisp_Object weakness = i ? args[i] : Qnil;
5802 hash_table_weakness_t weak; 5786 hash_table_weakness_t weak;
5803 if (NILP (weakness)) 5787 if (NILP (weakness_arg))
5804 weak = Weak_None; 5788 weak = Weak_None;
5805 else if (EQ (weakness, Qkey)) 5789 else if (BASE_EQ (weakness_arg, Qkey))
5806 weak = Weak_Key; 5790 weak = Weak_Key;
5807 else if (EQ (weakness, Qvalue)) 5791 else if (BASE_EQ (weakness_arg, Qvalue))
5808 weak = Weak_Value; 5792 weak = Weak_Value;
5809 else if (EQ (weakness, Qkey_or_value)) 5793 else if (BASE_EQ (weakness_arg, Qkey_or_value))
5810 weak = Weak_Key_Or_Value; 5794 weak = Weak_Key_Or_Value;
5811 else if (EQ (weakness, Qt) || EQ (weakness, Qkey_and_value)) 5795 else if (BASE_EQ (weakness_arg, Qt) || BASE_EQ (weakness_arg, Qkey_and_value))
5812 weak = Weak_Key_And_Value; 5796 weak = Weak_Key_And_Value;
5813 else 5797 else
5814 signal_error ("Invalid hash table weakness", weakness); 5798 signal_error ("Invalid hash table weakness", weakness_arg);
5815 5799
5816 /* Now, all args should have been used up, or there's a problem. */ 5800 return make_hash_table (test, size, weak, purecopy);
5817 for (i = 0; i < nargs; ++i)
5818 if (!used[i])
5819 {
5820 /* Ignore obsolete arguments. */
5821 if (EQ (args[i], QCrehash_threshold) || EQ (args[i], QCrehash_size))
5822 i++;
5823 else
5824 signal_error ("Invalid argument list", args[i]);
5825 }
5826
5827 SAFE_FREE ();
5828 return make_hash_table (testdesc, size, weak, purecopy);
5829} 5801}
5830 5802
5831 5803