Optmize the structure MD_MARK for size.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/md4c/md4c.c b/md4c/md4c.c
index fa5a06b..abd0138 100644
--- a/md4c/md4c.c
+++ b/md4c/md4c.c
@@ -693,22 +693,24 @@ md_is_html_any(MD_CTX* ctx, const MD_LINE* lines, int n_lines, OFF beg, OFF max_
* Note that not all instances of these chars in the text imply creation of the
* structure. Only those which have (or may have, after we see more context)
* the special meaning.
+ *
+ * (Keep this struct as small as possible to fit as much of them into CPU
+ * cache line.)
*/
struct MD_MARK_tag {
- /* For unresolved openers, these two form the chain of open openers of
- * given type.
+ OFF beg;
+ OFF end;
+
+ /* For unresolved openers, 'prev' and 'next' form the chain of open openers
+ * of given type 'ch'.
*
* During resolving, we disconnect from the chain and point to the
* corresponding counterpart so opener points to its closer and vice versa.
*/
- int prev;
- int next;
-
- OFF beg;
- OFF end;
-
- MD_CHAR ch;
- unsigned char flags;
+ int prev : 24;
+ int ch : 8; /* Only ASCII chars can form a mark. */
+ int next : 24;
+ int flags : 8;
};
/* Mark flags. */
@@ -754,11 +756,11 @@ md_push_mark(MD_CTX* ctx)
#define PUSH_MARK(ch_, beg_, end_, flags_) \
do { \
PUSH_MARK_(); \
- mark->prev = -1; \
- mark->next = -1; \
- mark->ch = (ch_); \
mark->beg = (beg_); \
mark->end = (end_); \
+ mark->prev = -1; \
+ mark->next = -1; \
+ mark->ch = (char)(ch_); \
mark->flags = (flags_); \
} while(0)
@@ -833,8 +835,8 @@ md_rollback(MD_CTX* ctx, int opener_index, int closer_index)
MD_MARKCHAIN* chain;
switch(opener->ch) {
- case _T('`'): chain = &BACKTICK_OPENERS; break;
- case _T('<'): chain = &RAW_HTML_OPENERS; break;
+ case '`': chain = &BACKTICK_OPENERS; break;
+ case '<': chain = &RAW_HTML_OPENERS; break;
default: MD_UNREACHABLE(); break;
}
@@ -1065,7 +1067,7 @@ md_analyze_entity(MD_CTX* ctx, int mark_index)
if(mark_index + 1 >= ctx->n_marks)
return;
closer = &ctx->marks[mark_index+1];
- if(closer->ch != _T(';'))
+ if(closer->ch != ';')
return;
if(CH(opener->end) == _T('#')) {
@@ -1146,16 +1148,16 @@ md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int precedence_
/* Analyze the mark. */
switch(mark->ch) {
- case _T('`'):
+ case '`':
md_analyze_backtick(ctx, i);
break;
- case _T('<'):
- case _T('>'):
+ case '<':
+ case '>':
md_analyze_raw_html(ctx, i, lines, n_lines);
break;
- case _T('&'):
+ case '&':
md_analyze_entity(ctx, i);
break;
}
@@ -1224,18 +1226,18 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
/* If reached the mark, process it and move to next one. */
if(off >= mark->beg) {
switch(mark->ch) {
- case _T('\\'): /* Backslash escape. */
+ case '\\': /* Backslash escape. */
if(ISNEWLINE(mark->beg+1))
enforce_hardbreak = 1;
else
MD_TEXT(text_type, STR(mark->beg+1), 1);
break;
- case _T(' '): /* Non-trivial space. */
+ case ' ': /* Non-trivial space. */
MD_TEXT(text_type, _T(" "), 1);
break;
- case _T('`'): /* Code span. */
+ case '`': /* Code span. */
if(mark->flags & MD_MARK_OPENER) {
MD_ENTER_SPAN(MD_SPAN_CODE, NULL);
text_type = MD_TEXT_CODE;
@@ -1245,14 +1247,14 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
}
break;
- case _T('<'): /* Raw HTML. */
+ case '<': /* Raw HTML. */
text_type = MD_TEXT_HTML;
break;
- case _T('>'):
+ case '>':
text_type = MD_TEXT_NORMAL;
break;
- case _T('&'): /* Entity. */
+ case '&': /* Entity. */
MD_TEXT(MD_TEXT_ENTITY, STR(mark->beg), mark->end - mark->beg);
break;
}
@@ -1276,8 +1278,8 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
/* Inside code spans, new lines are transformed into single
* spaces. */
MD_ASSERT(prev_mark != NULL);
- MD_ASSERT(prev_mark->ch == _T('`') && (prev_mark->flags & MD_MARK_OPENER));
- MD_ASSERT(mark->ch == _T('`') && (mark->flags & MD_MARK_CLOSER));
+ MD_ASSERT(prev_mark->ch == '`' && (prev_mark->flags & MD_MARK_OPENER));
+ MD_ASSERT(mark->ch == '`' && (mark->flags & MD_MARK_CLOSER));
if(prev_mark->end < off && off < mark->beg)
MD_TEXT(MD_SPAN_CODE, _T(" "), 1);