Improve AST cyclic detection performance (#3330)

This commit is contained in:
Paul Fultz II 2021-07-08 14:13:51 -05:00 committed by GitHub
parent 56924643be
commit 7e70a91613
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 18 deletions

View File

@ -1340,30 +1340,33 @@ std::string Token::stringifyList(bool varid) const
return stringifyList(varid, false, true, true, true, nullptr, nullptr);
}
static Token* checkAstCycle(Token* tok)
void Token::astParent(Token* tok)
{
std::set<const Token*> visited;
visitAstNodes(tok, [&](const Token* child) {
if (!visited.insert(child).second)
throw InternalError(child, "Internal error. AST cyclic dependency.");
return ChildrenToVisit::op1_and_op2;
});
while (tok->astParent()) {
if (!visited.insert(tok->astParent()).second) // #6838/#6726/#8352 avoid hang on garbage code
throw InternalError(tok, "Internal error. AST cyclic dependency.");
tok = tok->astParent();
const Token* tok2 = tok;
while (tok2) {
if (this == tok2)
throw InternalError(this, "Internal error. AST cyclic dependency.");
tok2 = tok2->astParent();
}
return tok;
// Clear children to avoid nodes referenced twice
if (this->astParent()) {
Token* parent = this->astParent();
if (parent->astOperand1() == this)
parent->mImpl->mAstOperand1 = nullptr;
if (parent->astOperand2() == this)
parent->mImpl->mAstOperand2 = nullptr;
}
mImpl->mAstParent = tok;
}
void Token::astOperand1(Token *tok)
{
if (mImpl->mAstOperand1)
mImpl->mAstOperand1->mImpl->mAstParent = nullptr;
mImpl->mAstOperand1->astParent(nullptr);
// goto parent operator
if (tok) {
tok = checkAstCycle(tok);
tok->mImpl->mAstParent = this;
tok = tok->astTop();
tok->astParent(this);
}
mImpl->mAstOperand1 = tok;
}
@ -1371,11 +1374,11 @@ void Token::astOperand1(Token *tok)
void Token::astOperand2(Token *tok)
{
if (mImpl->mAstOperand2)
mImpl->mAstOperand2->mImpl->mAstParent = nullptr;
mImpl->mAstOperand2->astParent(nullptr);
// goto parent operator
if (tok) {
tok = checkAstCycle(tok);
tok->mImpl->mAstParent = this;
tok = tok->astTop();
tok->astParent(this);
}
mImpl->mAstOperand2 = tok;
}

View File

@ -1278,6 +1278,7 @@ private:
public:
void astOperand1(Token *tok);
void astOperand2(Token *tok);
void astParent(Token* tok);
Token * astOperand1() {
return mImpl->mAstOperand1;