From 0f3e0094b8b7b00e4f00233e65ce24143af64b8d Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Wed, 31 May 2023 00:55:34 -0400 Subject: [PATCH 1/3] parsers,lisp: speed up token lookup --- parsers/lisp.c | 178 +++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 95 deletions(-) diff --git a/parsers/lisp.c b/parsers/lisp.c index 01ddef31cb..4ec57532cd 100644 --- a/parsers/lisp.c +++ b/parsers/lisp.c @@ -149,106 +149,94 @@ static int lisp_hint2kind (const vString *const hint) return k; } -/* TODO: implement this in hashtable. */ +/* Lookup code produced by gperf version 3.1 */ +static unsigned int hash_hint (const char *str, size_t len) +{ + static unsigned char asso_values[] = + { + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 8, 41, 30, + 41, 41, 0, 20, 41, 5, 41, 41, 41, 5, + 41, 41, 41, 41, 41, 0, 15, 15, 0, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41 + }; + return len + asso_values[(unsigned char)str[4]]; +} + static int elisp_hint2kind (const vString *const hint) { - int k = eK_UNKNOWN; - int n; - /* 4 means strlen("(def"). */ -#define EQN(X) strncmp(vStringValue (hint) + 4, &X[3], n) == 0 - switch (vStringLength (hint) - 4) +#define MIN_WORD_LENGTH 6 +#define MAX_WORD_LENGTH 31 +#define MAX_HASH_VALUE 40 + + static const char *wordlist[] = { - case 2: - n = 2; - if (EQN("defun")) - k = eK_FUNCTION; - break; - case 3: - n = 3; - if (EQN("defvar")) - k = eK_VARIABLE; - else if (EQN("defun*")) - k = eK_FUNCTION; - break; - case 4: - n = 4; - if (EQN("defface")) - k = eK_FACE; - case 5: - n = 5; - if (EQN("defconst")) - k = eK_CONST; - else if (EQN("defmacro")) - k = eK_MACRO; - else if (EQN("defalias")) - k = eK_ALIAS; - else if (EQN("defsubst")) - k = eK_SUBST; - else if (EQN("defgroup")) - k = eK_GROUP; - else if (EQN("deftheme")) - k = eK_THEME; - break; - case 6: - n = 6; - if (EQN("defcustom")) - k = eK_CUSTOM; - else if (EQN("defsubst*")) - k = eK_SUBST; - else if (EQN("defmacro*")) - k = eK_MACRO; - break; - case 7: - n = 7; - if (EQN("define-key")) - k = KIND_GHOST_INDEX; - break; - case 9: - n = 9; - if (EQN("defvar-local")) - k = eK_VARIABLE; - else if (EQN("define-error")) - k = eK_ERROR; - break; - case 8: - n = 8; - if (EQN("defvaralias")) - k = eK_VARALIAS; - break; - case 10: - n = 10; - if (EQN("define-inline")) - k = eK_INLINE; - break; - case 14: - n = 14; - if (EQN("define-minor-mode")) - k = eK_MINOR_MODE; - break; - case 16: - n = 16; - if (EQN("define-derived-mode")) - k = eK_DERIVED_MODE; - break; - case 21: - n = 21; - if (EQN("define-global-minor-mode")) - k = eK_MINOR_MODE; - break; - case 25: - n = 25; - if (EQN("define-globalized-minor-mode")) - k = eK_MINOR_MODE; - break; - case 27: - n = 27; - if (EQN("define-obsolete-function-alias")) - k = eK_ALIAS; - break; + "", "", "", "", "", "", "", "(defvar", "(defface", + "(defsubst", "(defsubst*", "", "(defvaralias", + "(defvar-local", "(defmacro", "(defmacro*", "(define-key", + "(defalias", "(define-error", "(define-inline", + "", "(defun", "(defun*", "(define-minor-mode", + "(deftheme", "(define-derived-mode", "", "", + "", "(defgroup", "(define-global-minor-mode", + "", "", "", "(define-globalized-minor-mode", "", + "(define-obsolete-function-alias", "", "", "(defconst", + "(defcustom" + }; + + static const int tokenKinds[] = + { + eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, + eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_VARIABLE, eK_FACE, + eK_SUBST, eK_SUBST, eK_UNKNOWN, eK_VARALIAS, eK_VARIABLE, + eK_MACRO, eK_MACRO, KIND_GHOST_INDEX, eK_ALIAS, eK_ERROR, + eK_INLINE, eK_UNKNOWN, eK_FUNCTION, eK_FUNCTION, + eK_MINOR_MODE, eK_THEME, eK_DERIVED_MODE, eK_UNKNOWN, + eK_UNKNOWN, eK_UNKNOWN, eK_GROUP, eK_MINOR_MODE, + eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_MINOR_MODE, + eK_UNKNOWN, eK_ALIAS, eK_UNKNOWN, eK_UNKNOWN, eK_CONST, + eK_CUSTOM, + }; + + const char *const str = vStringValue (hint); + const size_t len = vStringLength (hint); + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + const unsigned int key = hash_hint (str, len); + if (key <= MAX_HASH_VALUE) + { + const char *const s = wordlist[key]; + if (*str == *s && 0 == strncmp (str + 1, s + 1, len - 1)) + return tokenKinds[key]; + } } -#undef EQN - return k; + return eK_UNKNOWN; + +#undef MIN_WORD_LENGTH +#undef MAX_WORD_LENGTH +#undef MAX_HASH_VALUE + } static void L_getit (vString *const name, const unsigned char *dbp, From 45214ed36a5b4df9fb73bcd088a479f3e51713c3 Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Wed, 31 May 2023 12:13:52 -0400 Subject: [PATCH 2/3] Make more maintainable --- parsers/lisp.c | 75 +++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/parsers/lisp.c b/parsers/lisp.c index 4ec57532cd..7aa202e7d6 100644 --- a/parsers/lisp.c +++ b/parsers/lisp.c @@ -191,32 +191,51 @@ static int elisp_hint2kind (const vString *const hint) #define MAX_WORD_LENGTH 31 #define MAX_HASH_VALUE 40 - static const char *wordlist[] = - { - "", "", "", "", "", "", "", "(defvar", "(defface", - "(defsubst", "(defsubst*", "", "(defvaralias", - "(defvar-local", "(defmacro", "(defmacro*", "(define-key", - "(defalias", "(define-error", "(define-inline", - "", "(defun", "(defun*", "(define-minor-mode", - "(deftheme", "(define-derived-mode", "", "", - "", "(defgroup", "(define-global-minor-mode", - "", "", "", "(define-globalized-minor-mode", "", - "(define-obsolete-function-alias", "", "", "(defconst", - "(defcustom" - }; - - static const int tokenKinds[] = - { - eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, - eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_VARIABLE, eK_FACE, - eK_SUBST, eK_SUBST, eK_UNKNOWN, eK_VARALIAS, eK_VARIABLE, - eK_MACRO, eK_MACRO, KIND_GHOST_INDEX, eK_ALIAS, eK_ERROR, - eK_INLINE, eK_UNKNOWN, eK_FUNCTION, eK_FUNCTION, - eK_MINOR_MODE, eK_THEME, eK_DERIVED_MODE, eK_UNKNOWN, - eK_UNKNOWN, eK_UNKNOWN, eK_GROUP, eK_MINOR_MODE, - eK_UNKNOWN, eK_UNKNOWN, eK_UNKNOWN, eK_MINOR_MODE, - eK_UNKNOWN, eK_ALIAS, eK_UNKNOWN, eK_UNKNOWN, eK_CONST, - eK_CUSTOM, + static const struct { + const char *str; + int kind; + } tokens[] = { + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "(defvar", eK_VARIABLE, }, + { "(defface", eK_FACE, }, + { "(defsubst", eK_SUBST, }, + { "(defsubst*", eK_SUBST, }, + { "", eK_UNKNOWN, }, + { "(defvaralias", eK_VARALIAS, }, + { "(defvar-local", eK_VARIABLE, }, + { "(defmacro", eK_MACRO, }, + { "(defmacro*", eK_MACRO, }, + { "(define-key", KIND_GHOST_INDEX, }, + { "(defalias", eK_ALIAS, }, + { "(define-error", eK_ERROR, }, + { "(define-inline", eK_INLINE, }, + { "", eK_UNKNOWN, }, + { "(defun", eK_FUNCTION, }, + { "(defun*", eK_FUNCTION, }, + { "(define-minor-mode", eK_MINOR_MODE, }, + { "(deftheme", eK_THEME, }, + { "(define-derived-mode", eK_DERIVED_MODE, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "(defgroup", eK_GROUP, }, + { "(define-global-minor-mode", eK_MINOR_MODE, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "(define-globalized-minor-mode", eK_MINOR_MODE, }, + { "", eK_UNKNOWN, }, + { "(define-obsolete-function-alias", eK_ALIAS, }, + { "", eK_UNKNOWN, }, + { "", eK_UNKNOWN, }, + { "(defconst", eK_CONST, }, + { "(defcustom", eK_CUSTOM, }, }; const char *const str = vStringValue (hint); @@ -226,9 +245,9 @@ static int elisp_hint2kind (const vString *const hint) const unsigned int key = hash_hint (str, len); if (key <= MAX_HASH_VALUE) { - const char *const s = wordlist[key]; + const char *const s = tokens[key].str; if (*str == *s && 0 == strncmp (str + 1, s + 1, len - 1)) - return tokenKinds[key]; + return tokens[key].kind; } } return eK_UNKNOWN; From 156c8358f21fdf99676bb6552cf1dc9c3a3dd0ee Mon Sep 17 00:00:00 2001 From: Dmitri Tikhonov Date: Wed, 31 May 2023 12:26:21 -0400 Subject: [PATCH 3/3] Update comment: no code changes --- parsers/lisp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/parsers/lisp.c b/parsers/lisp.c index 7aa202e7d6..4e9a489c56 100644 --- a/parsers/lisp.c +++ b/parsers/lisp.c @@ -149,7 +149,15 @@ static int lisp_hint2kind (const vString *const hint) return k; } -/* Lookup code produced by gperf version 3.1 */ +/* Lookup code produced by gperf version 3.1 + * + * For example, run + * + * echo -e "(defconst\n(defmacro\n(defgroup\n(defalias" | gperf + * + * This is not included in the build process because gperf might not be + * available on all systems. + */ static unsigned int hash_hint (const char *str, size_t len) { static unsigned char asso_values[] =