1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
From 97ba04bf95606b409b1b3035504a41c274ecffe2 Mon Sep 17 00:00:00 2001
From: Shu-yu Guo <shu@rfrn.org>
Date: Mon, 26 Jan 2015 18:26:25 -0800
Subject: [PATCH] Bug 1119579 - Don't GC while iterating compartments in
findAllGlobals. r=sfink, a=abillings
---
js/src/vm/Debugger.cpp | 56 ++++++++++++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 22 deletions(-)
diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
index 27e993d..a8decef 100644
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2825,37 +2825,49 @@ Debugger::findAllGlobals(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "findAllGlobals", args, dbg);
- RootedObject result(cx, NewDenseEmptyArray(cx));
- if (!result)
- return false;
+ AutoObjectVector globals(cx);
- for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
- if (c->options().invisibleToDebugger())
- continue;
+ {
+ // Accumulate the list of globals before wrapping them, because
+ // wrapping can GC and collect compartments from under us, while
+ // iterating.
- c->zone()->scheduledForDestruction = false;
+ for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
+ if (c->options().invisibleToDebugger())
+ continue;
- GlobalObject *global = c->maybeGlobal();
+ c->zone()->scheduledForDestruction = false;
- if (cx->runtime()->isSelfHostingGlobal(global))
- continue;
+ GlobalObject *global = c->maybeGlobal();
- if (global) {
- /*
- * We pulled |global| out of nowhere, so it's possible that it was
- * marked gray by XPConnect. Since we're now exposing it to JS code,
- * we need to mark it black.
- */
- JS::ExposeGCThingToActiveJS(global, JSTRACE_OBJECT);
+ if (cx->runtime()->isSelfHostingGlobal(global))
+ continue;
- RootedValue globalValue(cx, ObjectValue(*global));
- if (!dbg->wrapDebuggeeValue(cx, &globalValue))
- return false;
- if (!NewbornArrayPush(cx, result, globalValue))
- return false;
+ if (global) {
+ /*
+ * We pulled |global| out of nowhere, so it's possible that it was
+ * marked gray by XPConnect. Since we're now exposing it to JS code,
+ * we need to mark it black.
+ */
+ JS::ExposeGCThingToActiveJS(global, JSTRACE_OBJECT);
+ if (!globals.append(global))
+ return false;
+ }
}
}
+ RootedObject result(cx, NewDenseEmptyArray(cx));
+ if (!result)
+ return false;
+
+ for (size_t i = 0; i < globals.length(); i++) {
+ RootedValue globalValue(cx, ObjectValue(*globals[i]));
+ if (!dbg->wrapDebuggeeValue(cx, &globalValue))
+ return false;
+ if (!NewbornArrayPush(cx, result, globalValue))
+ return false;
+ }
+
args.rval().setObject(*result);
return true;
}
--
2.2.1
|