Skip to content

Commit

Permalink
Remangler: don't construct a std::string for hashing and comparing id…
Browse files Browse the repository at this point in the history
…entifiers

This avoids memory allocations.
  • Loading branch information
eeckstein committed Mar 13, 2019
1 parent 3c73685 commit c6abbfa
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 28 deletions.
60 changes: 43 additions & 17 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,36 +38,62 @@ static void unreachable(const char *Message) {
std::abort();
}

static char getCharOfNodeText(Node *node, unsigned idx) {
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
return Mangle::translateOperatorChar(node->getText()[idx]);
default:
return node->getText()[idx];
}
}

bool SubstitutionEntry::identifierEquals(Node *lhs, Node *rhs) {
unsigned length = lhs->getText().size();
if (rhs->getText().size() != length)
return false;
// The fast path.
if (lhs->getKind() == rhs->getKind())
return lhs->getText() == rhs->getText();
// The slow path.
for (unsigned i = 0; i < length; ++i) {
if (getCharOfNodeText(lhs, i) != getCharOfNodeText(rhs, i))
return false;
}
return true;
}

void SubstitutionEntry::deepHash(Node *node) {
if (treatAsIdentifier) {
combineHash((size_t) Node::Kind::Identifier);
std::string tmp;
combineHash(getTextForSubstitution(node, tmp));
return;
assert(node->hasText());
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
for (char c : node->getText()) {
combineHash((unsigned char)translateOperatorChar(c));
}
return;
default:
break;
}
} else {
combineHash((size_t) node->getKind());
}
combineHash((size_t) node->getKind());
if (node->hasIndex()) {
combineHash(node->getIndex());
} else if (node->hasText()) {
combineHash(node->getText());
for (char c : node->getText()) {
combineHash((unsigned char) c);
}
}
for (Node *child : *node) {
deepHash(child);
}
}

StringRef SubstitutionEntry::getTextForSubstitution(Node *node, std::string &tmp) {
switch (node->getKind()) {
case Node::Kind::InfixOperator:
case Node::Kind::PrefixOperator:
case Node::Kind::PostfixOperator:
tmp = Mangle::translateOperator(node->getText());
return tmp;
default:
return node->getText();
}
}

bool SubstitutionEntry::deepEquals(Node *lhs, Node *rhs) const {
if (lhs->getKind() != rhs->getKind())
return false;
Expand Down
14 changes: 3 additions & 11 deletions lib/Demangling/RemanglerBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,27 +53,19 @@ class SubstitutionEntry {
if (lhs.treatAsIdentifier != rhs.treatAsIdentifier)
return false;
if (lhs.treatAsIdentifier) {
std::string tmp1, tmp2;
return (getTextForSubstitution(lhs.TheNode, tmp1) ==
getTextForSubstitution(rhs.TheNode, tmp2));
return identifierEquals(lhs.TheNode, rhs.TheNode);
}
return lhs.deepEquals(lhs.TheNode, rhs.TheNode);
}

static bool identifierEquals(Node *lhs, Node *rhs);

void combineHash(size_t newValue) {
StoredHash = 33 * StoredHash + newValue;
}

void combineHash(StringRef Text) {
for (char c : Text) {
combineHash((unsigned char) c);
}
}

void deepHash(Node *node);

static StringRef getTextForSubstitution(Node *node, std::string &tmp);

bool deepEquals(Node *lhs, Node *rhs) const;
};

Expand Down

0 comments on commit c6abbfa

Please sign in to comment.