From d56399343aedec105d280eb2627cb943326b0e31 Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Fri, 13 Sep 2024 09:44:05 +0200 Subject: [PATCH] Trying to speed up type handling A map of lists instead of a simple list --- .../de/fraunhofer/aisec/cpg/TranslationManager.kt | 4 +++- .../kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt | 11 ++++++----- .../de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt | 2 +- .../de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt | 3 ++- .../de/fraunhofer/aisec/cpg/passes/TypeResolver.kt | 4 ++-- .../cpg/passes/JavaExternalTypeHierarchyResolver.kt | 2 +- .../de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt | 2 ++ 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationManager.kt index 199f03fe91..db53365233 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationManager.kt @@ -314,7 +314,9 @@ private constructor( // and individual file scopes beneath it var newGlobalScope = globalCtx.scopeManager.globalScope var types = - globalCtx.typeManager.firstOrderTypes.union(globalCtx.typeManager.secondOrderTypes) + globalCtx.typeManager.firstOrderTypes.values + .flatten() + .union(globalCtx.typeManager.secondOrderTypes) types.forEach { if (it.scope is GlobalScope) { it.scope = newGlobalScope diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt index 8745e7944d..2f4bbb6a01 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt @@ -54,7 +54,7 @@ class TypeManager { MutableMap> = ConcurrentHashMap() - val firstOrderTypes: MutableSet = ConcurrentHashMap.newKeySet() + val firstOrderTypes = ConcurrentHashMap>() val secondOrderTypes: MutableSet = ConcurrentHashMap.newKeySet() /** @@ -197,9 +197,10 @@ class TypeManager { } if (t.isFirstOrderType) { + var types = firstOrderTypes.computeIfAbsent(t.name.toString()) { mutableListOf() } // Make sure we only ever return one unique object per type - if (!firstOrderTypes.add(t)) { - return firstOrderTypes.first { it == t && it is T } as T + if (!types.add(t)) { + return types.first { it == t && it is T } as T } else { log.trace( "Registering unique first order type {}{}", @@ -224,7 +225,7 @@ class TypeManager { /** Checks, whether a [Type] with the given [name] exists. */ fun typeExists(name: CharSequence): Boolean { - return firstOrderTypes.any { type: Type -> type.root.name == name } + return firstOrderTypes.values.flatten().any { type: Type -> type.root.name == name } } fun resolvePossibleTypedef(alias: Type, scopeManager: ScopeManager): Type { @@ -247,7 +248,7 @@ class TypeManager { return primitiveType } - return firstOrderTypes.firstOrNull { + return firstOrderTypes[fqn.toString()]?.firstOrNull { (it.typeOrigin == Type.Origin.RESOLVED || it.typeOrigin == Type.Origin.GUESSED) && it.root.name == fqn && if (generics != null) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt index a0a0fde85a..87a435c660 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt @@ -118,7 +118,7 @@ fun LanguageProvider.objectType( synchronized(c.typeManager.firstOrderTypes) { // We can try to look up the type by its name and return it, if it already exists. var type = - c.typeManager.firstOrderTypes.firstOrNull { + c.typeManager.firstOrderTypes[name.toString()]?.firstOrNull { it is ObjectType && it.name == name && it.scope == scope && diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt index 6a3d8707a3..f9c5b7cbe8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolver.kt @@ -1011,7 +1011,8 @@ fun TranslationContext.tryRecordInference( // update the type's record. Because types are only unique per scope, we potentially need to // update multiple type nodes, i.e., all type nodes whose FQN match the inferred record if (record != null) { - typeManager.firstOrderTypes + typeManager.firstOrderTypes.values + .flatten() .filter { it.name == record.name } .forEach { it.recordDeclaration = record } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeResolver.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeResolver.kt index df57786fd1..65d6d3f4f7 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeResolver.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/TypeResolver.kt @@ -122,7 +122,7 @@ open class TypeResolver(ctx: TranslationContext) : ComponentPass(ctx) { private fun handleNode(node: Node?) { if (node is RecordDeclaration) { - for (t in typeManager.firstOrderTypes) { + for (t in typeManager.firstOrderTypes.values.flatten()) { if (t.name == node.name && t is ObjectType) { // The node is the class of the type t t.recordDeclaration = node @@ -136,7 +136,7 @@ open class TypeResolver(ctx: TranslationContext) : ComponentPass(ctx) { } fun resolveFirstOrderTypes() { - for (type in typeManager.firstOrderTypes.sortedBy { it.name }) { + for (type in typeManager.firstOrderTypes.values.flatten().sortedBy { it.name }) { if (type is ObjectType && type.typeOrigin == Type.Origin.UNRESOLVED) { resolveType(type) } diff --git a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaExternalTypeHierarchyResolver.kt b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaExternalTypeHierarchyResolver.kt index 84a75a95b9..f3be085f0d 100644 --- a/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaExternalTypeHierarchyResolver.kt +++ b/cpg-language-java/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/JavaExternalTypeHierarchyResolver.kt @@ -71,7 +71,7 @@ class JavaExternalTypeHierarchyResolver(ctx: TranslationContext) : ComponentPass } // Iterate over all known types and add their (direct) supertypes. - for (t in typeManager.firstOrderTypes) { + for (t in typeManager.firstOrderTypes.values.flatten()) { val symbol = resolver.tryToSolveType(t.typeName) if (symbol.isSolved) { try { diff --git a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt index 79c60675a8..95a5d691b7 100644 --- a/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt +++ b/cpg-neo4j/src/main/kotlin/de/fraunhofer/aisec/cpg_vis_neo4j/Application.kt @@ -616,6 +616,8 @@ class Application : Callable { "Benchmark: analyzing code in " + (analyzingTime - startTime) / S_TO_MS_FACTOR + " s." ) + translationResult.benchmarkResults.print() + exportJsonFile?.let { exportToJson(translationResult, it) } if (!noNeo4j) { pushToNeo4j(translationResult)