summaryrefslogtreecommitdiffstats
path: root/js/src/devtools/rootAnalysis/t/graph
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/devtools/rootAnalysis/t/graph
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/devtools/rootAnalysis/t/graph')
-rw-r--r--js/src/devtools/rootAnalysis/t/graph/source.cpp90
-rw-r--r--js/src/devtools/rootAnalysis/t/graph/test.py54
2 files changed, 144 insertions, 0 deletions
diff --git a/js/src/devtools/rootAnalysis/t/graph/source.cpp b/js/src/devtools/rootAnalysis/t/graph/source.cpp
new file mode 100644
index 0000000000..0adff8d532
--- /dev/null
+++ b/js/src/devtools/rootAnalysis/t/graph/source.cpp
@@ -0,0 +1,90 @@
+#define ANNOTATE(property) __attribute__((annotate(property)))
+
+extern void GC() ANNOTATE("GC Call");
+
+void GC() {
+ // If the implementation is too trivial, the function body won't be emitted at
+ // all.
+ asm("");
+}
+
+extern void g(int x);
+extern void h(int x);
+
+void f(int x) {
+ if (x % 3) {
+ GC();
+ g(x);
+ }
+ h(x);
+}
+
+void g(int x) {
+ if (x % 2) f(x);
+ h(x);
+}
+
+void h(int x) {
+ if (x) {
+ f(x - 1);
+ g(x - 1);
+ }
+}
+
+void leaf() { asm(""); }
+
+void nonrecursive_root() {
+ leaf();
+ leaf();
+ GC();
+}
+
+void self_recursive(int x) {
+ if (x) self_recursive(x - 1);
+}
+
+// Set up the graph
+//
+// n1 <--> n2 n4 <--> n5
+// \ /
+// --> n3 <---------
+// \
+// ---> n6 --> n7 <---> n8 --> n9
+//
+// So recursive roots are one of (n1, n2) plus one of (n4, n5).
+extern void n1(int x);
+extern void n2(int x);
+extern void n3(int x);
+extern void n4(int x);
+extern void n5(int x);
+extern void n6(int x);
+extern void n7(int x);
+extern void n8(int x);
+extern void n9(int x);
+
+void n1(int x) { n2(x); }
+
+void n2(int x) {
+ if (x) n1(x - 1);
+ n3(x);
+}
+
+void n4(int x) { n5(x); }
+
+void n5(int x) {
+ if (x) n4(x - 1);
+ n3(x);
+}
+
+void n3(int x) { n6(x); }
+
+void n6(int x) { n7(x); }
+
+void n7(int x) { n8(x); }
+
+void n8(int x) {
+ if (x) n7(x - 1);
+ n9(x);
+}
+
+void n9(int x) { asm(""); }
diff --git a/js/src/devtools/rootAnalysis/t/graph/test.py b/js/src/devtools/rootAnalysis/t/graph/test.py
new file mode 100644
index 0000000000..f78500f200
--- /dev/null
+++ b/js/src/devtools/rootAnalysis/t/graph/test.py
@@ -0,0 +1,54 @@
+# 'test' is provided by the calling script.
+# flake8: noqa: F821
+
+test.compile("source.cpp")
+test.run_analysis_script("gcTypes")
+
+info = test.load_typeInfo()
+
+gcFunctions = test.load_gcFunctions()
+
+f = "void f(int32)"
+g = "void g(int32)"
+h = "void h(int32)"
+
+assert f in gcFunctions
+assert g in gcFunctions
+assert h in gcFunctions
+assert "void leaf()" not in gcFunctions
+assert "void nonrecursive_root()" in gcFunctions
+
+callgraph = test.load_callgraph()
+assert callgraph.calleeGraph[f][g]
+assert callgraph.calleeGraph[f][h]
+assert callgraph.calleeGraph[g][f]
+assert callgraph.calleeGraph[g][h]
+
+node = ["void n{}(int32)".format(i) for i in range(10)]
+mnode = [callgraph.unmangledToMangled.get(f) for f in node]
+for src, dst in [
+ (1, 2),
+ (2, 1),
+ (4, 5),
+ (5, 4),
+ (2, 3),
+ (5, 3),
+ (3, 6),
+ (6, 7),
+ (7, 8),
+ (8, 7),
+ (8, 9),
+]:
+ assert callgraph.calleeGraph[node[src]][node[dst]]
+
+funcInfo = test.load_funcInfo()
+rroots = set(
+ [
+ callgraph.mangledToUnmangled[f]
+ for f in funcInfo
+ if funcInfo[f].get("recursive_root")
+ ]
+)
+assert len(set([node[1], node[2]]) & rroots) == 1
+assert len(set([node[4], node[5]]) & rroots) == 1
+assert len(rroots) == 4, "rroots = {}".format(rroots) # n1, n4, f, self_recursive