From e2d4bac51e15407ecd2572e493a4106c451fa10b Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 28 Apr 2023 11:48:53 +0100 Subject: [PATCH 1/2] DCL56-CPP: Improve performance Frequent use of getAChild*() was causing slow performance, as it attempted to specialize it for different contexts. We instead replace getAChild*() with a getAnInitializerExpr predicate, which uses explicit recursion which experimentally gave better performance. --- .../cpp/StaticInitialization.qll | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/cpp/common/src/codingstandards/cpp/StaticInitialization.qll b/cpp/common/src/codingstandards/cpp/StaticInitialization.qll index 0a8f5811e0..34c353726d 100644 --- a/cpp/common/src/codingstandards/cpp/StaticInitialization.qll +++ b/cpp/common/src/codingstandards/cpp/StaticInitialization.qll @@ -27,6 +27,15 @@ module StaticInitializationGraph { * - Create a `Node` instance for each injector type. */ + /** + * Gets an Expr directly or indirectly included in an initializer. + */ + private Expr getAnInitializerExpr(Initializer i) { + result = i.getExpr() + or + result = getAnInitializerExpr(i).getAChild() + } + newtype TNode = TInitializerNode(Initializer i) { // This is the initializer of a static storage duration variable @@ -48,7 +57,7 @@ module StaticInitializationGraph { } or TFunctionCallNode(FunctionCall fc) { // This is a function call that occurs in an initializer called during static initialization - exists(TInitializerNode(any(Initializer i | i.getExpr().getAChild*() = fc))) + exists(TInitializerNode(any(Initializer i | getAnInitializerExpr(i) = fc))) or // This is a function call that occurs in a function called during static initialization exists( @@ -56,13 +65,13 @@ module StaticInitializationGraph { f = fc.getEnclosingFunction() and // Not in an initializer of a local variable, where the desired flow is instead: // function -> initializer -> fc - not exists(Initializer i | i.getExpr().getAChild*() = fc) + not exists(Initializer i | getAnInitializerExpr(i) = fc) )) ) } or TVariableAccessNode(VariableAccess va) { // This is a variable that is accessed in an initializer called during static initialization - exists(TInitializerNode(any(Initializer i | i.getExpr().getAChild*() = va))) + exists(TInitializerNode(any(Initializer i | getAnInitializerExpr(i) = va))) or // This is a variable that is accessed in a function called during static initialization exists( @@ -70,7 +79,7 @@ module StaticInitializationGraph { f = va.getEnclosingFunction() and // Not in an initializer of a local variable, where the desired flow is instead: // function -> initializer -> va - not exists(Initializer i | i.getExpr().getAChild*() = va) + not exists(Initializer i | getAnInitializerExpr(i) = va) )) ) } @@ -149,9 +158,7 @@ module StaticInitializationGraph { or // Initializer steps exists(Initializer i | i = n1.(InitializerNode).getInitializer() | - i.getExpr().getAChild*() = n2.(FunctionCallNode).getFunctionCall() - or - i.getExpr().getAChild*() = n2.(VariableAccessNode).getVariableAccess() + getAnInitializerExpr(i) = n2.getExpr() ) or // FunctionCall steps @@ -169,7 +176,7 @@ module StaticInitializationGraph { f = n2.getExpr().getEnclosingFunction() and // But not in an initializer of a local variable, where the desired flow is instead: // function -> initializer -> expression - not exists(Initializer i | i.getExpr().getAChild*() = n2.getExpr()) + not exists(Initializer i | getAnInitializerExpr(i) = n2.getExpr()) or // `n2` is an initializer of a local scope variable within function `f` n2.(InitializerNode).getInitializer().getDeclaration().(LocalScopeVariable).getFunction() = f From 73cc3a4aad6c8d5cf6d7f67671a5bf27a2711240 Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Fri, 28 Apr 2023 12:01:25 +0100 Subject: [PATCH 2/2] Add change note --- change_notes/2023-04-28-dcl56-cpp-perf.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 change_notes/2023-04-28-dcl56-cpp-perf.md diff --git a/change_notes/2023-04-28-dcl56-cpp-perf.md b/change_notes/2023-04-28-dcl56-cpp-perf.md new file mode 100644 index 0000000000..61ce45b133 --- /dev/null +++ b/change_notes/2023-04-28-dcl56-cpp-perf.md @@ -0,0 +1 @@ + * `DCL56-CPP` - performance has been improved for databases with complex initializers. \ No newline at end of file