Abandoned atoms work: hardly any performance benefit. mdw/atoms-abandoned
authorMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 18:28:13 +0000 (19:28 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 3 Aug 2019 18:28:13 +0000 (19:28 +0100)
lib/keyword.h
test/Makefile.am

index 525b31f..58dd29c 100644 (file)
@@ -113,6 +113,44 @@ typedef void kw_unkhookfn(const char */*set*/, const char */*kw*/);
  */
 extern kw_unkhookfn *kw_unkhook;
 
+/*----- Atoms -------------------------------------------------------------*/
+
+#ifdef __arm__
+#  define KW__SECTTY "%"
+#else
+#  define KW__SECTTY "@"
+#endif
+
+#if defined(__GNUC__) && defined(__ELF__) && 0
+#  define KWATOM_DECL(id, name)                                                \
+       __asm__(        ".ifndef " #id "\n"                             \
+                       ".pushsection .rodata." #id ", "                \
+                               "\"aGS\", " KW__SECTTY "progbits, "     \
+                               ".rodata." #id ", comdat\n"             \
+                       ".globl " #id "\n"                              \
+               #id ": .asciz " #name "\n"                              \
+                       ".popsection\n"                                 \
+                       ".endif");                                      \
+       extern const char id[]
+#endif
+
+#ifdef KWATOM_DECL
+#  define KW_ATOM(id, name) id
+#else
+#  define KWATOM_DECL(id, name) extern int kw__fake_##id
+#  define KW_ATOM(id, name) (name + 0*sizeof(kw__fake_##id))
+#endif
+
+#define KADECL(atom) KWATOM_DECL(kw__atom__##atom, #atom)
+#define KA(atom) KW_ATOM(kw__atom__##atom, #atom)
+#define KA_TAB KW_ATOM(kw__atom_kw_tab, "kw.tab")
+#define KA_UNKNOWN KW_ATOM(kw__atom_kw_unknown, "kw.unknown")
+#define KA_VALIST KW_ATOM(kw__atom_kw_valist, "kw.valist")
+
+KWATOM_DECL(kw__atom_kw_tab, "kw.tab");
+KWATOM_DECL(kw__atom_kw_unknown, "kw.unknown");
+KWATOM_DECL(kw__atom_kw_valist, "kw.valist");
+
 /*----- Argument list macros ----------------------------------------------*/
 
 /* These macros are intended to be conveniences rather than a proper
@@ -172,7 +210,7 @@ extern kw_unkhookfn *kw_unkhook;
  * Use:                Bundles a keyword @kw@ and value @val@ together.
  */
 
-#define K(kw, val) #kw, (val),
+#define K(kw, val) KA(kw), (val),
 
 /* --- @K_VALIST@ --- *
  *
@@ -182,7 +220,7 @@ extern kw_unkhookfn *kw_unkhook;
  *             function.
  */
 
-#define K_VALIST(ap) "kw.valist", &(ap),
+#define K_VALIST(ap) KA_VALIST, &(ap),
 
 /* --- @K_TAB@ --- *
  *
@@ -193,7 +231,7 @@ extern kw_unkhookfn *kw_unkhook;
  *             function.
  */
 
-#define K_TAB(v, n) "kw.tab", (v), (size_t)(n),
+#define K_TAB(v, n) KA_TAB, (v), (size_t)(n),
 
 /*----- Keyword set definitions -------------------------------------------*
  *
@@ -359,6 +397,75 @@ extern kw_unkhookfn *kw_unkhook;
     kw->name = *(type const *)v->val;                                  \
   } else
 
+#define KWSET_PARSEFN_ATOMS(set)                                       \
+  void set##_kwparse(struct set##_kwargs *kw,                          \
+                    const char *kwfirst, va_list *ap,                  \
+                    const struct kwval *v, size_t n)                   \
+  {                                                                    \
+    const char *k, *kk;                                                        \
+    va_list *aap;                                                      \
+    const struct kwtab *t;                                             \
+    const struct kwval *vv;                                            \
+    size_t nn;                                                         \
+                                                                       \
+    for (k = kwfirst; k; k = va_arg(*ap, const char *)) {              \
+      set##_KWSET(KWSET__ARGVA_ATOM)                                   \
+      /*else*/ if (k == KA_VALIST) {                                   \
+       aap = va_arg(*ap, va_list *);                                   \
+       kk = va_arg(*aap, const char *);                                \
+       set##_kwparse(kw, kk, aap, 0, 0);                               \
+      } else if (k == KA_TAB) {                                                \
+       vv = va_arg(*ap, const struct kwval *);                         \
+       nn = va_arg(*ap, size_t);                                       \
+       set##_kwparse(kw, 0, 0, vv, nn);                                \
+      } else set##_KWSET(KWSET__ARGVA)                                 \
+      /*else*/ if (!strcmp(k, KA_VALIST)) {                            \
+       aap = va_arg(*ap, va_list *);                                   \
+       kk = va_arg(*aap, const char *);                                \
+       set##_kwparse(kw, kk, aap, 0, 0);                               \
+      } else if (!strcmp(k, KA_TAB)) {                                 \
+       vv = va_arg(*ap, const struct kwval *);                         \
+       nn = va_arg(*ap, size_t);                                       \
+       set##_kwparse(kw, 0, 0, vv, nn);                                \
+      } else kw_unknown(#set, k);                                      \
+    }                                                                  \
+                                                                       \
+    while (n) {                                                                \
+      set##_KWSET(KWSET__ARGTAB)                                       \
+      /*else*/ if (!strcmp(v->kw, KA_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, KA_TAB)) {                             \
+       t = (const struct kwtab *)v->val;                               \
+       set##_kwparse(kw, 0, 0, t->v, t->n);                            \
+      } else kw_unknown(#set, v->kw);                                  \
+      v++; n--;                                                                \
+    }                                                                  \
+  }
+
+#define KWSET__ARGVA_ATOM(type, name, dflt)                            \
+  if (k == KA(name)) {                                                 \
+    kw->name##_suppliedp = 1;                                          \
+    kw->name = va_arg(*ap, type);                                      \
+  } else
+#define KWSET__ARGTAB_ATOM(type, name, dflt)                           \
+  if (v->kw == KA(name)) {                                             \
+    kw->name##_suppliedp = 1;                                          \
+    kw->name = *(type const *)v->val;                                  \
+  } else
+
+#define KWSET__ARGVA(type, name, dflt)                                 \
+  if (!strcmp(k, #name)) {                                             \
+    kw->name##_suppliedp = 1;                                          \
+    kw->name = va_arg(*ap, type);                                      \
+  } else
+#define KWSET__ARGTAB(type, name, dflt)                                        \
+  if (!strcmp(v->kw, #name)) {                                         \
+    kw->name##_suppliedp = 1;                                          \
+    kw->name = *(type const *)v->val;                                  \
+  } else
+
 /*----- Defining keyword-accepting functions ------------------------------*/
 
 /* --- @KWDECL@ --- *
index de5b634..71b3908 100644 (file)
@@ -58,6 +58,9 @@ check-local:: kwtest kwtest.ref
        ./kwtest >kwtest.out
        diff -u $(srcdir)/kwtest.ref kwtest.out
 
+check_PROGRAMS         += kwbench
+kwbench_SOURCES                 = kwbench-back.c kwbench.c kwbench.h
+
 check_PROGRAMS         += rat
 
 EXTRA_DIST             += rat.sod rat.ref