diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2017-11-13 17:19:32 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2017-11-30 16:12:55 +0000 |
commit | c03f79f3af806cdec5c938d267486d338eaaab5d (patch) | |
tree | 763949fc5edda34de287a19d4a04461f588e3987 /src/lib/corelib/buildgraph | |
parent | a5cc49f2c62cfd4094c6a8bccd7741ca9ee7e072 (diff) |
Remove as many dynamic_casts as possible
According to our benchmarker, this speeds up rule execution by three per
cent.
Change-Id: Iaf146ba6073b897d19e0fe470d7b0dc4a04d264c
Reviewed-by: Jake Petroules <jake.petroules@qt.io>
Diffstat (limited to 'src/lib/corelib/buildgraph')
-rw-r--r-- | src/lib/corelib/buildgraph/artifact.cpp | 5 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/artifact.h | 1 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/buildgraph.cpp | 21 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/buildgraphloader.cpp | 11 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/depscanner.cpp | 5 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/executor.cpp | 26 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/filedependency.h | 5 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/inputartifactscanner.cpp | 38 | ||||
-rw-r--r-- | src/lib/corelib/buildgraph/projectbuilddata.cpp | 43 |
9 files changed, 94 insertions, 61 deletions
diff --git a/src/lib/corelib/buildgraph/artifact.cpp b/src/lib/corelib/buildgraph/artifact.cpp index de9c5b7b6..b2ccdf55c 100644 --- a/src/lib/corelib/buildgraph/artifact.cpp +++ b/src/lib/corelib/buildgraph/artifact.cpp @@ -121,10 +121,9 @@ const TypeFilter<Artifact> Artifact::childArtifacts() const void Artifact::onChildDisconnected(BuildGraphNode *child) { - Artifact *childArtifact = dynamic_cast<Artifact *>(child); - if (!childArtifact) + if (child->type() != BuildGraphNode::ArtifactNodeType) return; - childrenAddedByScanner.remove(childArtifact); + childrenAddedByScanner.remove(static_cast<Artifact *>(child)); } void Artifact::load(PersistentPool &pool) diff --git a/src/lib/corelib/buildgraph/artifact.h b/src/lib/corelib/buildgraph/artifact.h index e08b4181e..fc75427d2 100644 --- a/src/lib/corelib/buildgraph/artifact.h +++ b/src/lib/corelib/buildgraph/artifact.h @@ -71,6 +71,7 @@ public: ~Artifact(); Type type() const { return ArtifactNodeType; } + FileType fileType() const override { return FileTypeArtifact; } void accept(BuildGraphVisitor *visitor); QString toString() const; diff --git a/src/lib/corelib/buildgraph/buildgraph.cpp b/src/lib/corelib/buildgraph/buildgraph.cpp index a7d7f9c8e..39687f623 100644 --- a/src/lib/corelib/buildgraph/buildgraph.cpp +++ b/src/lib/corelib/buildgraph/buildgraph.cpp @@ -376,7 +376,8 @@ void connect(BuildGraphNode *p, BuildGraphNode *c) { QBS_CHECK(p != c); qCDebug(lcBuildGraph) << "connect" << p->toString() << "->" << c->toString(); - if (Artifact *ac = dynamic_cast<Artifact *>(c)) { + if (c->type() == BuildGraphNode::ArtifactNodeType) { + Artifact * const ac = static_cast<Artifact *>(c); for (const Artifact *child : filterByType<Artifact>(p->children)) { if (child == ac) return; @@ -486,11 +487,14 @@ Artifact *lookupArtifact(const ResolvedProductConstPtr &product, = projectBuildData->lookupFiles(dirPath, fileName); for (QList<FileResourceBase *>::const_iterator it = lookupResults.constBegin(); it != lookupResults.constEnd(); ++it) { - Artifact *artifact = dynamic_cast<Artifact *>(*it); - if (artifact && (compareByName - ? artifact->product->uniqueName() == product->uniqueName() - : artifact->product == product)) + if ((*it)->fileType() != FileResourceBase::FileTypeArtifact) + continue; + Artifact *artifact = static_cast<Artifact *>(*it); + if (compareByName + ? artifact->product->uniqueName() == product->uniqueName() + : artifact->product == product) { return artifact; + } } return nullptr; } @@ -581,10 +585,11 @@ static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, QBS_CHECK(allProducts.contains(child->product.lock())); } - Artifact * const artifact = dynamic_cast<Artifact *>(node); + Artifact * const artifact = node->type() == BuildGraphNode::ArtifactNodeType + ? static_cast<Artifact *>(node) : nullptr; if (!artifact) { - RuleNode * const ruleNode = dynamic_cast<RuleNode *>(node); - QBS_CHECK(ruleNode); + QBS_CHECK(node->type() == BuildGraphNode::RuleNodeType); + RuleNode * const ruleNode = static_cast<RuleNode *>(node); QBS_CHECK(ruleNode->rule()); QBS_CHECK(ruleNode->rule()->product); QBS_CHECK(ruleNode->rule()->product == ruleNode->product.get()); diff --git a/src/lib/corelib/buildgraph/buildgraphloader.cpp b/src/lib/corelib/buildgraph/buildgraphloader.cpp index d459a1a10..a636bf6df 100644 --- a/src/lib/corelib/buildgraph/buildgraphloader.cpp +++ b/src/lib/corelib/buildgraph/buildgraphloader.cpp @@ -93,8 +93,10 @@ static void restoreBackPointers(const ResolvedProjectPtr &project) if (!product->buildData) continue; for (BuildGraphNode * const n : qAsConst(product->buildData->nodes)) { - if (Artifact *a = dynamic_cast<Artifact *>(n)) - project->topLevelProject()->buildData->insertIntoLookupTable(a); + if (n->type() == BuildGraphNode::ArtifactNodeType) { + project->topLevelProject()->buildData + ->insertIntoLookupTable(static_cast<Artifact *>(n)); + } } } @@ -436,9 +438,8 @@ void BuildGraphLoader::trackProjectChanges() .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); for (FileResourceBase * const f : qAsConst(m_objectsToDelete)) { - Artifact * const a = dynamic_cast<Artifact *>(f); - if (a) - a->product.reset(); // To help with the sanity checks. + if (f->fileType() == FileResourceBase::FileTypeArtifact) + static_cast<Artifact *>(f)->product.reset(); // To help with the sanity checks. } doSanityChecks(m_result.newlyResolvedProject, m_logger); } diff --git a/src/lib/corelib/buildgraph/depscanner.cpp b/src/lib/corelib/buildgraph/depscanner.cpp index 0efe4af47..d20c301f7 100644 --- a/src/lib/corelib/buildgraph/depscanner.cpp +++ b/src/lib/corelib/buildgraph/depscanner.cpp @@ -175,10 +175,9 @@ QStringList UserDependencyScanner::collectDependencies(FileResourceBase *file, c { Q_UNUSED(fileTags); // ### support user dependency scanners for file deps - Artifact *artifact = dynamic_cast<Artifact *>(file); - if (!artifact) + if (file->fileType() != FileResourceBase::FileTypeArtifact) return QStringList(); - return evaluate(artifact, m_scanner->scanScript); + return evaluate(static_cast<Artifact *>(file), m_scanner->scanScript); } bool UserDependencyScanner::recursive() const diff --git a/src/lib/corelib/buildgraph/executor.cpp b/src/lib/corelib/buildgraph/executor.cpp index 890e85abd..c109d9a01 100644 --- a/src/lib/corelib/buildgraph/executor.cpp +++ b/src/lib/corelib/buildgraph/executor.cpp @@ -231,8 +231,10 @@ void Executor::doBuild() const QList<FileResourceBase *> &files = m_project->buildData->lookupFiles(fileToConsider); for (const FileResourceBase * const file : files) { - const Artifact * const artifact = dynamic_cast<const Artifact *>(file); - if (artifact && m_productsToBuild.contains(artifact->product.lock())) { + if (file->fileType() != FileResourceBase::FileTypeArtifact) + continue; + const Artifact * const artifact = static_cast<const Artifact *>(file); + if (m_productsToBuild.contains(artifact->product.lock())) { m_tagsOfFilesToConsider.unite(artifact->fileTags()); m_productsOfFilesToConsider << artifact->product.lock(); } @@ -309,9 +311,11 @@ void Executor::updateLeaves(BuildGraphNode *node, NodeSet &seenNodes) // prepareBuildGraph() has been called, must be initialized. if (node->buildState == BuildGraphNode::Untouched) { node->buildState = BuildGraphNode::Buildable; - Artifact *artifact = dynamic_cast<Artifact *>(node); - if (artifact && artifact->artifactType == Artifact::SourceFile) - retrieveSourceFileTimestamp(artifact); + if (node->type() == BuildGraphNode::ArtifactNodeType) { + Artifact * const artifact = static_cast<Artifact *>(node); + if (artifact->artifactType == Artifact::SourceFile) + retrieveSourceFileTimestamp(artifact); + } } bool isLeaf = true; @@ -496,16 +500,16 @@ void Executor::executeRuleNode(RuleNode *ruleNode) Set<RuleNode *> parentRules; if (!result.createdNodes.empty()) { for (BuildGraphNode *parent : qAsConst(ruleNode->parents)) { - if (RuleNode *parentRule = dynamic_cast<RuleNode *>(parent)) - parentRules += parentRule; + if (parent->type() == BuildGraphNode::RuleNodeType) + parentRules += static_cast<RuleNode *>(parent); } } for (BuildGraphNode *node : qAsConst(result.createdNodes)) { qCDebug(lcExec) << "rule created" << node->toString(); Internal::connect(node, ruleNode); - Artifact *outputArtifact = dynamic_cast<Artifact *>(node); - if (!outputArtifact) + if (node->type() != BuildGraphNode::ArtifactNodeType) continue; + Artifact * const outputArtifact = static_cast<Artifact *>(node); if (outputArtifact->fileTags().intersects(product->fileTags)) product->buildData->roots += outputArtifact; @@ -776,7 +780,7 @@ void Executor::rescueOldBuildData(Artifact *artifact, bool *childrenAdded = 0) break; } const auto depFinder = [](const FileResourceBase *f) { - return dynamic_cast<const FileDependency *>(f); + return f->fileType() == FileResourceBase::FileTypeDependency; }; const auto depIt = std::find_if(depList.cbegin(), depList.cend(), depFinder); if (depIt == depList.cend()) { @@ -785,7 +789,7 @@ void Executor::rescueOldBuildData(Artifact *artifact, bool *childrenAdded = 0) << "not in the project's list of dependencies anymore."; break; } - artifact->fileDependencies.insert(dynamic_cast<FileDependency *>(*depIt)); + artifact->fileDependencies.insert(static_cast<FileDependency *>(*depIt)); } if (canRescue) { diff --git a/src/lib/corelib/buildgraph/filedependency.h b/src/lib/corelib/buildgraph/filedependency.h index b4ff93816..871667376 100644 --- a/src/lib/corelib/buildgraph/filedependency.h +++ b/src/lib/corelib/buildgraph/filedependency.h @@ -54,6 +54,9 @@ protected: public: ~FileResourceBase(); + enum FileType { FileTypeDependency, FileTypeArtifact }; + virtual FileType fileType() const = 0; + void setTimestamp(const FileTime &t); const FileTime ×tamp() const; void clearTimestamp() { m_timestamp.clear(); } @@ -79,6 +82,8 @@ class FileDependency : public FileResourceBase public: FileDependency(); ~FileDependency(); + + FileType fileType() const override { return FileTypeDependency; } }; } // namespace Internal diff --git a/src/lib/corelib/buildgraph/inputartifactscanner.cpp b/src/lib/corelib/buildgraph/inputartifactscanner.cpp index 13314eb52..177d1dfc8 100644 --- a/src/lib/corelib/buildgraph/inputartifactscanner.cpp +++ b/src/lib/corelib/buildgraph/inputartifactscanner.cpp @@ -79,14 +79,21 @@ static void resolveDepencency(const RawScannedDependency &dependency, Artifact *dependencyInOtherProduct = nullptr; for (FileResourceBase *lookupResult : project->topLevelProject() ->buildData->lookupFiles(absDirPath, dependency.fileName())) { - if ((fileDependencyArtifact = dynamic_cast<FileDependency *>(lookupResult))) - continue; - Artifact * const foundArtifact = dynamic_cast<Artifact *>(lookupResult); - if (foundArtifact->product == product) { - dependencyInProduct = foundArtifact; + switch (lookupResult->fileType()) { + case FileResourceBase::FileTypeDependency: + fileDependencyArtifact = static_cast<FileDependency *>(lookupResult); + break; + case FileResourceBase::FileTypeArtifact: { + Artifact * const foundArtifact = static_cast<Artifact *>(lookupResult); + if (foundArtifact->product == product) + dependencyInProduct = foundArtifact; + else + dependencyInOtherProduct = foundArtifact; break; } - dependencyInOtherProduct = foundArtifact; + } + if (dependencyInProduct) + break; } // prioritize found artifacts @@ -266,8 +273,10 @@ unresolved: resolved: handleDependency(resolvedDependency); if (artifactsToScan && resolvedDependency.file) { - if (Artifact *artifactDependency = dynamic_cast<Artifact *>(resolvedDependency.file)) { + if (resolvedDependency.file->fileType() == FileResourceBase::FileTypeArtifact) { // Do not scan an artifact that is not built yet: Its contents might still change. + Artifact * const artifactDependency + = static_cast<Artifact *>(resolvedDependency.file); if (artifactDependency->artifactType == Artifact::SourceFile || artifactDependency->buildState == BuildGraphNode::Built) { artifactsToScan->push_back(artifactDependency); @@ -286,9 +295,18 @@ void InputArtifactScanner::handleDependency(ResolvedDependency &dependency) QBS_CHECK(m_artifact->artifactType == Artifact::Generated); QBS_CHECK(product); - Artifact *artifactDependency = dynamic_cast<Artifact *>(dependency.file); - FileDependency *fileDependency - = artifactDependency ? 0 : dynamic_cast<FileDependency *>(dependency.file); + Artifact *artifactDependency = nullptr; + FileDependency *fileDependency = nullptr; + if (dependency.file) { + switch (dependency.file->fileType()) { + case FileResourceBase::FileTypeArtifact: + artifactDependency = static_cast<Artifact *>(dependency.file); + break; + case FileResourceBase::FileTypeDependency: + fileDependency = static_cast<FileDependency *>(dependency.file); + break; + } + } QBS_CHECK(!dependency.file || artifactDependency || fileDependency); if (!dependency.file) { diff --git a/src/lib/corelib/buildgraph/projectbuilddata.cpp b/src/lib/corelib/buildgraph/projectbuilddata.cpp index cb247d6ef..ba8ed801d 100644 --- a/src/lib/corelib/buildgraph/projectbuilddata.cpp +++ b/src/lib/corelib/buildgraph/projectbuilddata.cpp @@ -99,22 +99,23 @@ void ProjectBuildData::insertIntoLookupTable(FileResourceBase *fileres) { QList<FileResourceBase *> &lst = m_artifactLookupTable[fileres->fileName()][fileres->dirPath()]; - const auto * const artifact = dynamic_cast<Artifact *>(fileres); + const auto * const artifact = fileres->fileType() == FileResourceBase::FileTypeArtifact + ? static_cast<Artifact *>(fileres) : nullptr; if (artifact && artifact->artifactType == Artifact::Generated) { for (const auto *file : lst) { - const auto * const otherArtifact = dynamic_cast<const Artifact *>(file); - if (otherArtifact) { - ErrorInfo error; - error.append(Tr::tr("Conflicting artifacts for file path '%1'.") - .arg(artifact->filePath())); - error.append(Tr::tr("The first artifact comes from product '%1'.") - .arg(otherArtifact->product->fullDisplayName()), - otherArtifact->product->location); - error.append(Tr::tr("The second artifact comes from product '%1'.") - .arg(artifact->product->fullDisplayName()), - artifact->product->location); - throw error; - } + if (file->fileType() != FileResourceBase::FileTypeArtifact) + continue; + const auto * const otherArtifact = static_cast<const Artifact *>(file); + ErrorInfo error; + error.append(Tr::tr("Conflicting artifacts for file path '%1'.") + .arg(artifact->filePath())); + error.append(Tr::tr("The first artifact comes from product '%1'.") + .arg(otherArtifact->product->fullDisplayName()), + otherArtifact->product->location); + error.append(Tr::tr("The second artifact comes from product '%1'.") + .arg(artifact->product->fullDisplayName()), + artifact->product->location); + throw error; } } QBS_CHECK(!lst.contains(fileres)); @@ -164,13 +165,13 @@ static void disconnectArtifactParents(Artifact *artifact) qCDebug(lcBuildGraph) << "disconnect parents of" << relativeArtifactFileName(artifact); for (BuildGraphNode * const parent : qAsConst(artifact->parents)) { parent->children.remove(artifact); - Artifact *parentArtifact = dynamic_cast<Artifact *>(parent); - if (parentArtifact) { - QBS_CHECK(parentArtifact->transformer); - parentArtifact->childrenAddedByScanner.remove(artifact); - parentArtifact->transformer->inputs.remove(artifact); - parentArtifact->product->registerArtifactWithChangedInputs(parentArtifact); - } + if (parent->type() != BuildGraphNode::ArtifactNodeType) + continue; + Artifact * const parentArtifact = static_cast<Artifact *>(parent); + QBS_CHECK(parentArtifact->transformer); + parentArtifact->childrenAddedByScanner.remove(artifact); + parentArtifact->transformer->inputs.remove(artifact); + parentArtifact->product->registerArtifactWithChangedInputs(parentArtifact); } artifact->parents.clear(); |