From 0f3e4dbfdaf4709e5b713ca60734fd4bad22041b Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sat, 3 Aug 2019 16:01:56 +0100 Subject: [PATCH] lib/keyword.h, src/method-impl.lisp: Check user keywords first. For better performance, check the user's specific keywords before the magic built-in ones. --- lib/keyword.h | 23 +++++++++---------- src/method-impl.lisp | 63 +++++++++++++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/lib/keyword.h b/lib/keyword.h index 5b486bf..525b31f 100644 --- a/lib/keyword.h +++ b/lib/keyword.h @@ -322,7 +322,8 @@ extern kw_unkhookfn *kw_unkhook; size_t nn; \ \ for (k = kwfirst; k; k = va_arg(*ap, const char *)) { \ - if (!strcmp(k, "kw.valist")) { \ + set##_KWSET(KWSET__ARGVA) \ + /*else*/ if (!strcmp(k, "kw.valist")) { \ aap = va_arg(*ap, va_list *); \ kk = va_arg(*aap, const char *); \ set##_kwparse(kw, kk, aap, 0, 0); \ @@ -330,35 +331,33 @@ extern kw_unkhookfn *kw_unkhook; vv = va_arg(*ap, const struct kwval *); \ nn = va_arg(*ap, size_t); \ set##_kwparse(kw, 0, 0, vv, nn); \ - } \ - set##_KWSET(KWSET__ARGVA) \ - else kw_unknown(#set, k); \ + } else kw_unknown(#set, k); \ } \ \ while (n) { \ - if (!strcmp(v->kw, "kw.valist")) { \ + set##_KWSET(KWSET__ARGTAB) \ + /*else*/ if (!strcmp(v->kw, "kw.valist")) { \ aap = *(va_list *const *)v->val; \ kk = va_arg(*aap, const char *); \ set##_kwparse(kw, kk, aap, 0, 0); \ } else if (!strcmp(v->kw, "kw.tab")) { \ t = (const struct kwtab *)v->val; \ set##_kwparse(kw, 0, 0, t->v, t->n); \ - } \ - set##_KWSET(KWSET__ARGTAB) \ - else kw_unknown(#set, v->kw); \ + } else kw_unknown(#set, v->kw); \ v++; n--; \ } \ } + #define KWSET__ARGVA(type, name, dflt) \ - else if (!strcmp(k, #name)) { \ + if (!strcmp(k, #name)) { \ kw->name##_suppliedp = 1; \ kw->name = va_arg(*ap, type); \ - } + } else #define KWSET__ARGTAB(type, name, dflt) \ - else if (!strcmp(v->kw, #name)) { \ + if (!strcmp(v->kw, #name)) { \ kw->name##_suppliedp = 1; \ kw->name = *(type const *)v->val; \ - } + } else /*----- Defining keyword-accepting functions ------------------------------*/ diff --git a/src/method-impl.lisp b/src/method-impl.lisp index d0c7a54..7fdceb1 100644 --- a/src/method-impl.lisp +++ b/src/method-impl.lisp @@ -523,6 +523,38 @@ set "v->kw"))) (name (effective-method-keyword-parser-function-name method))) + ;; Deal with the special `kw.' keywords read via varargs. We're + ;; building the dispatch up backwards, so if we do these first, they + ;; get checked last, which priviliges the function-specific arguments + ;; over these special effects. + (codegen-push codegen) + (call "vv" "va_arg" "*ap" (c-type (* (struct "kwval" :const)))) + (call "nn" "va_arg" "*ap" c-type-size-t) + (call :void name "kw" *null-pointer* "vv" "nn") + (setf va-act (namecheck "k" "kw.tab" + (codegen-pop-block codegen) va-act)) + + (codegen-push codegen) + (call "aap" "va_arg" "*ap" (c-type (* va-list))) + (call :void name "kw" "aap" *null-pointer* 0) + (setf va-act (namecheck "k" "kw.valist" + (codegen-pop-block codegen) va-act)) + + ;; Deal with the special `kw.' keywords read from a table. + (codegen-push codegen) + (deliver-expr codegen "t" + (format nil "(~A)v->val" + (c-type (* (struct "kwtab" :const))))) + (call :void name "kw" *null-pointer* "t->v" "t->n") + (setf tab-act (namecheck "v->kw" "kw.tab" + (codegen-pop-block codegen) tab-act)) + + (codegen-push codegen) + (convert "aap" (c-type (* va-list))) + (call :void name "kw" "aap" *null-pointer* 0) + (setf tab-act (namecheck "v->kw" "kw.valist" + (codegen-pop-block codegen) tab-act)) + ;; Work through the keywords. We're going to be building up the ;; conditional dispatch from the end, so reverse the (nicely sorted) ;; list before processing it. @@ -544,20 +576,6 @@ (setf tab-act (namecheck "v->kw" key-name (codegen-pop-block codegen) tab-act)))) - ;; Deal with the special `kw.' keywords read via varargs. - (codegen-push codegen) - (call "vv" "va_arg" "*ap" (c-type (* (struct "kwval" :const)))) - (call "nn" "va_arg" "*ap" c-type-size-t) - (call :void name "kw" *null-pointer* "vv" "nn") - (setf va-act (namecheck "k" "kw.tab" - (codegen-pop-block codegen) va-act)) - - (codegen-push codegen) - (call "aap" "va_arg" "*ap" (c-type (* va-list))) - (call :void name "kw" "aap" *null-pointer* 0) - (setf va-act (namecheck "k" "kw.valist" - (codegen-pop-block codegen) va-act)) - ;; Finish up the varargs loop. (emit-banner codegen "Parse keywords from the variable-length tail.") (codegen-push codegen) @@ -568,23 +586,8 @@ (emit-inst codegen (make-if-inst "ap" (make-block-inst nil (list loop))))) - ;; Deal with the special `kw.' keywords read from a table. - (codegen-push codegen) - (deliver-expr codegen "t" - (format nil "(~A)v->val" - (c-type (* (struct "kwtab" :const))))) - (call :void name "kw" *null-pointer* "t->v" "t->n") - (setf tab-act (namecheck "v->kw" "kw.tab" - (codegen-pop-block codegen) tab-act)) - - (emit-banner codegen "Parse keywords from the argument table.") - (codegen-push codegen) - (convert "aap" (c-type (* va-list))) - (call :void name "kw" "aap" *null-pointer* 0) - (setf tab-act (namecheck "v->kw" "kw.valist" - (codegen-pop-block codegen) tab-act)) - ;; Finish off the table loop. + (emit-banner codegen "Parse keywords from the argument table.") (codegen-push codegen) (emit-inst codegen tab-act) (emit-inst codegen (make-expr-inst "v++")) -- 2.11.0