diff options
| author | Mattias EngdegÄrd | 2024-08-18 14:20:36 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-08-21 14:14:39 +0200 |
| commit | 46f3452b30f39a69f610faab58c1490b34dd367d (patch) | |
| tree | 229ea33505e1c3bdfd27e1511babe858c4ee621a /src | |
| parent | 5d0e5f086505848631f9f79926b526597fc60688 (diff) | |
| download | emacs-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.c | 112 |
1 files changed, 42 insertions, 70 deletions
| @@ -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 | |||
| 4647 | static ptrdiff_t | ||
| 4648 | get_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. | |||
| 5762 | usage: (make-hash-table &rest KEYWORD-ARGS) */) | 5738 | usage: (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 | ||