Bug 1171842 - Use jump table instead of nested if statements for peeking compute function of style struct. r=dbaron

--HG--
extra : source : c16172954389dff27f9fee7d4bacc949de662a4c
This commit is contained in:
Xidorn Quan 2015-06-12 14:32:46 +12:00
parent 6508b24916
commit 7f4096ebd9
2 changed files with 13 additions and 78 deletions

View File

@ -9,33 +9,7 @@
#
# 1. To generate code for each inherited style struct.
# 2. To generate code for each reset style struct.
# 3. To generate a tree of nested if statements that can be used to run
# some code on each style struct.
#
# As an example, if we assume that we have only four style structs, the
# generated tree of nested if statements looks like this:
#
# if (STYLE_STRUCT_TEST < 4) {
# if (STYLE_STRUCT_TEST < 2) {
# if (STYLE_STRUCT_TEST == 0) {
# ... code for style struct with id 0 ...
# } else {
# ... code for style struct with id 1 ...
# }
# } else {
# if (STYLE_STRUCT_TEST == 2) {
# ... code for style struct with id 2 ...
# } else {
# ... code for style struct with id 3 ...
# }
# }
# }
#
# The TOPLEVELBRANCHES variable controls how widely we branch on the outermost
# if statement. In the example above, it splits the search space in 2, but with
# a larger number of style structs to test -- particularly when the number is
# closer to one power of two than the next higher one -- the average number of
# comparisons can be reduced by splitting the top level check into more than 2.
# 3. To generate the dependency of each style struct.
from __future__ import print_function
@ -77,9 +51,6 @@ STYLE_STRUCTS = [("INHERITED",) + x for x in [
("Column", "nullptr", NORMAL_DEP + LENGTH_DEP + COLOR_DEP),
]]
# How widely to branch on the outermost if statement.
TOPLEVELBRANCHES = 4
# ---- Generate nsStyleStructList.h ----
@ -116,42 +87,12 @@ for i in range(count):
"the following structs:", " ".join(unsolved_items), file=sys.stderr)
exit(1)
def nextPowerOf2(x):
return int(pow(2, math.ceil(math.log(x, 2))))
def printEntry(header, i):
print("STYLE_STRUCT_%s(%s, %s)" % STYLE_STRUCTS[i][:3], file=header)
for dep in STYLE_STRUCTS[i][3]:
print("STYLE_STRUCT_DEP(%s)" % (dep,), file=header)
print("STYLE_STRUCT_END()", file=header)
def printTestTree(header, min, max, depth, branches):
indent = " " * depth
if min == count - 1 and max >= count:
print(" STYLE_STRUCT_TEST_CODE(%sNS_ASSERTION(STYLE_STRUCT_TEST == %d, \"out of range\");)" % (indent, min), file=header)
printEntry(header, min)
elif max - min == 2:
print(" STYLE_STRUCT_TEST_CODE(%sif (STYLE_STRUCT_TEST == %d) {)" % (indent, min), file=header)
printEntry(header, min)
print(" STYLE_STRUCT_TEST_CODE(%s} else {)" % indent, file=header)
printEntry(header, min + 1)
print(" STYLE_STRUCT_TEST_CODE(%s})" % indent, file=header)
elif min < count:
mid = min + (max - min) / branches
print(" STYLE_STRUCT_TEST_CODE(%sif (STYLE_STRUCT_TEST < %d) {)" % (indent, mid), file=header)
printTestTree(header, min, mid, depth + 1, 2)
for branch in range(1, branches):
lo = min + branch * (max - min) / branches
hi = min + (branch + 1) * (max - min) / branches
if lo >= count:
break
if branch == branches - 1 or hi >= count:
print(" STYLE_STRUCT_TEST_CODE(%s} else {)" % indent, file=header)
else:
print(" STYLE_STRUCT_TEST_CODE(%s} else if (STYLE_STRUCT_TEST < %d) {)" % (indent, hi), file=header)
printTestTree(header, lo, hi, depth + 1, 2)
print(" STYLE_STRUCT_TEST_CODE(%s})" % indent, file=header)
HEADER = """/* THIS FILE IS AUTOGENERATED BY generate-stylestructlist.py - DO NOT EDIT */
// IWYU pragma: private, include "nsStyleStructFwd.h"
@ -189,12 +130,6 @@ HEADER = """/* THIS FILE IS AUTOGENERATED BY generate-stylestructlist.py - DO NO
#define UNDEF_STYLE_STRUCT_END
#endif
#ifdef STYLE_STRUCT_TEST
#define STYLE_STRUCT_TEST_CODE(c) c
#else
#define STYLE_STRUCT_TEST_CODE(c)
#endif
// The inherited structs are listed before the Reset structs.
// nsStyleStructID assumes this is the case, and callers other than
// nsStyleStructFwd.h that want the structs in id-order just define
@ -221,11 +156,10 @@ FOOTER = """
#undef STYLE_STRUCT_END
#undef UNDEF_STYLE_STRUCT_END
#endif
#undef STYLE_STRUCT_TEST_CODE
"""
def main(header):
print(HEADER, file=header)
printTestTree(header, 0, nextPowerOf2(count), 0, TOPLEVELBRANCHES)
for i in range(count):
printEntry(header, i)
print(FOOTER, file=header)

View File

@ -2387,18 +2387,19 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
return SetDefaultOnRoot(aSID, aContext);
}
// We need to compute the data from the information that the rules specified.
const void* res;
#define STYLE_STRUCT_TEST aSID
#define STYLE_STRUCT(name, checkdata_cb) \
res = Compute##name##Data(startStruct, &ruleData, aContext, \
highestNode, detail, ruleData.mCanStoreInRuleTree);
typedef const void* (nsRuleNode::*ComputeFunc)(void*, const nsRuleData*,
nsStyleContext*, nsRuleNode*,
RuleDetail, const bool);
static const ComputeFunc sComputeFuncs[] = {
#define STYLE_STRUCT(name, checkdata_cb) &nsRuleNode::Compute##name##Data,
#include "nsStyleStructList.h"
#undef STYLE_STRUCT
#undef STYLE_STRUCT_TEST
};
// Now return the result.
return res;
// We need to compute the data from the information that the rules specified.
return (this->*sComputeFuncs[aSID])(startStruct, &ruleData, aContext,
highestNode, detail,
ruleData.mCanStoreInRuleTree);
}
const void*