[Mesa-dev] [PATCH 12/12] glcpp: Substitute trivial macros in the fast path

Vladislav Egorov vegorov180 at gmail.com
Sat Jan 7 19:02:13 UTC 2017


The vast majority of macros are trivial, simple numbers or identifiers.
Substitute them in the fast path, no need to bailout for them to the
slow path.
---
 src/compiler/glsl/glcpp/glcpp-lex.l | 77 +++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 3 deletions(-)

diff --git a/src/compiler/glsl/glcpp/glcpp-lex.l b/src/compiler/glsl/glcpp/glcpp-lex.l
index 8e916a2..5b3dd5b 100644
--- a/src/compiler/glsl/glcpp/glcpp-lex.l
+++ b/src/compiler/glsl/glcpp/glcpp-lex.l
@@ -717,6 +717,70 @@ glcpp_fast_flush(glcpp_parser_t *parser, struct string_buffer *out,
 }
 
 static bool
+glcpp_fast_try_print_trivial_macro(macro_t *macro, glcpp_parser_t *parser,
+                                   struct string_buffer *out)
+{
+   token_t *tok;
+   token_node_t *head;
+   bool success;
+
+   /* If the macro is a function, there is no way we can substitute it
+    * without tokenization, argument validation and so on.
+    */
+   if (macro->is_function)
+      return false;
+
+   /* Always substitute empty macro with a single space */
+   if (!macro->replacements || !macro->replacements->head) {
+      glcpp_append_char(parser, out, ' ');
+      return true;
+   }
+
+   /* If the macro has more than one non-space token, it's too complex. */
+   if (macro->replacements->head != macro->replacements->non_space_tail)
+      return false;
+
+   head = macro->replacements->head;
+   tok = head->token;
+
+   switch (tok->type) {
+      case INTEGER:
+         glcpp_printf(parser, out, "%" PRIiMAX, tok->value.ival);
+         success = true;
+         break;
+
+      case INTEGER_STRING:
+         glcpp_append(parser, out, tok->value.str);
+         success = true;
+         break;
+
+      case IDENTIFIER:
+         /* We don't accept other macros to avoid recursion and excessive cost
+          * of macro's analysis in the _fast_ path.
+          */
+         if (!GLCPP_DEFINES_BLOOM_GET(parser, tok->value.str) ||
+             !_mesa_hash_table_search(parser->defines, tok->value.str)) {
+            glcpp_append(parser, out, tok->value.str);
+            success = true;
+         } else {
+            success = false;
+         }
+         break;
+
+      default:
+         success = false;
+         break;
+   }
+
+   /* Print trailing space to match the existing behavior */
+   if (success) {
+      while ((head = head->next) != NULL)
+         glcpp_append_char(parser, out, ' ');
+   }
+   return success;
+}
+
+static bool
 glcpp_fast_process_identifier(glcpp_parser_t *parser,
                               struct string_buffer *out,
                               struct yyguts_t *yyg,
@@ -770,9 +834,16 @@ glcpp_fast_process_identifier(glcpp_parser_t *parser,
          if (entry) {
             parser->dont_use_fast_path = true;
             glcpp_fast_flush(parser, out, id_start, last_printed);
-            buf = id_start;
-            success = false;
-            *last_printed = id_start;
+            /* Our last chance. Try substitute trivial macro like non-macro
+             * identifier or single integer. Otherwise we have to fallback.
+             */
+            if (!glcpp_fast_try_print_trivial_macro(entry->data, parser, out)) {
+               buf = id_start;
+               success = false;
+               *last_printed = id_start;
+            } else {
+               *last_printed = buf;
+            }
          }
       }
    }
-- 
2.7.4



More information about the mesa-dev mailing list