lib/keyword.h, src/method-impl.lisp: Check user keywords first.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 15:01:56 +0000 (16:01 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 15:46:22 +0000 (16:46 +0100)
For better performance, check the user's specific keywords before the
magic built-in ones.

lib/keyword.h
src/method-impl.lisp

index 5b486bf..525b31f 100644 (file)
@@ -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 ------------------------------*/
 
index d0c7a54..7fdceb1 100644 (file)
                                                   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.
          (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)
        (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++"))