@@ -59,36 +59,6 @@ bool SubstitutionEntry::identifierEquals(Node *lhs, Node *rhs) {
59
59
return true ;
60
60
}
61
61
62
- void SubstitutionEntry::deepHash (Node *node) {
63
- if (treatAsIdentifier) {
64
- combineHash ((size_t ) Node::Kind::Identifier);
65
- assert (node->hasText ());
66
- switch (node->getKind ()) {
67
- case Node::Kind::InfixOperator:
68
- case Node::Kind::PrefixOperator:
69
- case Node::Kind::PostfixOperator:
70
- for (char c : node->getText ()) {
71
- combineHash ((unsigned char )translateOperatorChar (c));
72
- }
73
- return ;
74
- default :
75
- break ;
76
- }
77
- } else {
78
- combineHash ((size_t ) node->getKind ());
79
- }
80
- if (node->hasIndex ()) {
81
- combineHash (node->getIndex ());
82
- } else if (node->hasText ()) {
83
- for (char c : node->getText ()) {
84
- combineHash ((unsigned char ) c);
85
- }
86
- }
87
- for (Node *child : *node) {
88
- deepHash (child);
89
- }
90
- }
91
-
92
62
bool SubstitutionEntry::deepEquals (Node *lhs, Node *rhs) const {
93
63
if (lhs->getKind () != rhs->getKind ())
94
64
return false ;
@@ -114,10 +84,108 @@ bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const {
114
84
if (!deepEquals (*li, *ri))
115
85
return false ;
116
86
}
117
-
87
+
118
88
return true ;
119
89
}
120
90
91
+ static inline size_t combineHash (size_t currentHash, size_t newValue) {
92
+ return 33 * currentHash + newValue;
93
+ }
94
+
95
+ // / Calculate the hash for a node.
96
+ size_t RemanglerBase::hashForNode (Node *node,
97
+ bool treatAsIdentifier) {
98
+ size_t hash = 0 ;
99
+
100
+ if (treatAsIdentifier) {
101
+ hash = combineHash (hash, (size_t )Node::Kind::Identifier);
102
+ assert (node->hasText ());
103
+ switch (node->getKind ()) {
104
+ case Node::Kind::InfixOperator:
105
+ case Node::Kind::PrefixOperator:
106
+ case Node::Kind::PostfixOperator:
107
+ for (char c : node->getText ()) {
108
+ hash = combineHash (hash, (unsigned char )translateOperatorChar (c));
109
+ }
110
+ return hash;
111
+ default :
112
+ break ;
113
+ }
114
+ } else {
115
+ hash = combineHash (hash, (size_t ) node->getKind ());
116
+ }
117
+ if (node->hasIndex ()) {
118
+ hash = combineHash (hash, node->getIndex ());
119
+ } else if (node->hasText ()) {
120
+ for (char c : node->getText ()) {
121
+ hash = combineHash (hash, (unsigned char ) c);
122
+ }
123
+ }
124
+ for (Node *child : *node) {
125
+ SubstitutionEntry entry = entryForNode (child, treatAsIdentifier);
126
+ hash = combineHash (hash, entry.hash ());
127
+ }
128
+
129
+ return hash;
130
+ }
131
+
132
+ // / Rotate a size_t by N bits
133
+ static inline size_t rotate (size_t value, size_t shift) {
134
+ const size_t bits = sizeof (size_t ) * 8 ;
135
+ return (value >> shift) | (value << (bits - shift));
136
+ }
137
+
138
+ // / Compute a hash value from a node *pointer*.
139
+ // / Used for look-ups in HashHash. The numbers in here were determined
140
+ // / experimentally.
141
+ static inline size_t nodeHash (Node *node) {
142
+ // Multiply by a magic number
143
+ const size_t nodePrime = ((size_t )node) * 2043 ;
144
+
145
+ // We rotate by a different amount because the alignment of Node
146
+ // changes depending on the machine's pointer size
147
+ switch (sizeof (size_t )) {
148
+ case 4 :
149
+ return rotate (nodePrime, 11 );
150
+ case 8 :
151
+ return rotate (nodePrime, 12 );
152
+ case 16 :
153
+ return rotate (nodePrime, 13 );
154
+ default :
155
+ return rotate (nodePrime, 12 );
156
+ }
157
+ }
158
+
159
+ // / Construct a SubstitutionEntry for a given node.
160
+ // / This will look in the HashHash to see if we already know the hash
161
+ // / (which avoids recursive hashing on the Node tree).
162
+ SubstitutionEntry RemanglerBase::entryForNode (Node *node,
163
+ bool treatAsIdentifier) {
164
+ const size_t ident = treatAsIdentifier ? 4 : 0 ;
165
+ const size_t hash = nodeHash (node) + ident;
166
+
167
+ // Use linear probing with a limit
168
+ for (size_t n = 0 ; n < HashHashMaxProbes; ++n) {
169
+ const size_t ndx = (hash + n) & (HashHashCapacity - 1 );
170
+ SubstitutionEntry entry = HashHash[ndx];
171
+
172
+ if (entry.isEmpty ()) {
173
+ size_t entryHash = hashForNode (node, treatAsIdentifier);
174
+ entry.setNode (node, treatAsIdentifier, entryHash);
175
+ HashHash[ndx] = entry;
176
+ return entry;
177
+ } else if (entry.matches (node, treatAsIdentifier)) {
178
+ return entry;
179
+ }
180
+ }
181
+
182
+ // Hash table is full at this hash value
183
+ SubstitutionEntry entry;
184
+ size_t entryHash = hashForNode (node, treatAsIdentifier);
185
+ entry.setNode (node, treatAsIdentifier, entryHash);
186
+ return entry;
187
+ }
188
+
121
189
// Find a substitution and return its index.
122
190
// Returns -1 if no substitution is found.
123
191
int RemanglerBase::findSubstitution (const SubstitutionEntry &entry) {
@@ -356,7 +424,7 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry,
356
424
return true ;
357
425
358
426
// Go ahead and initialize the substitution entry.
359
- entry. setNode (node, treatAsIdentifier);
427
+ entry = entryForNode (node, treatAsIdentifier);
360
428
361
429
int Idx = findSubstitution (entry);
362
430
if (Idx < 0 )
0 commit comments