|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef js_TracingAPI_h |
|
8 #define js_TracingAPI_h |
|
9 |
|
10 #include "mozilla/NullPtr.h" |
|
11 |
|
12 #include "jspubtd.h" |
|
13 |
|
14 class JS_PUBLIC_API(JSTracer); |
|
15 |
|
16 namespace JS { |
|
17 template <typename T> class Heap; |
|
18 template <typename T> class TenuredHeap; |
|
19 } |
|
20 |
|
21 // Tracer callback, called for each traceable thing directly referenced by a |
|
22 // particular object or runtime structure. It is the callback responsibility |
|
23 // to ensure the traversal of the full object graph via calling eventually |
|
24 // JS_TraceChildren on the passed thing. In this case the callback must be |
|
25 // prepared to deal with cycles in the traversal graph. |
|
26 // |
|
27 // kind argument is one of JSTRACE_OBJECT, JSTRACE_STRING or a tag denoting |
|
28 // internal implementation-specific traversal kind. In the latter case the only |
|
29 // operations on thing that the callback can do is to call JS_TraceChildren or |
|
30 // JS_GetTraceThingInfo. |
|
31 // |
|
32 // If eagerlyTraceWeakMaps is true, when we trace a WeakMap visit all |
|
33 // of its mappings. This should be used in cases where the tracer |
|
34 // wants to use the existing liveness of entries. |
|
35 typedef void |
|
36 (* JSTraceCallback)(JSTracer *trc, void **thingp, JSGCTraceKind kind); |
|
37 |
|
38 // Callback that JSTraceOp implementation can provide to return a string |
|
39 // describing the reference traced with JS_CallTracer. |
|
40 typedef void |
|
41 (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize); |
|
42 |
|
43 enum WeakMapTraceKind { |
|
44 DoNotTraceWeakMaps = 0, |
|
45 TraceWeakMapValues = 1, |
|
46 TraceWeakMapKeysValues = 2 |
|
47 }; |
|
48 |
|
49 class JS_PUBLIC_API(JSTracer) |
|
50 { |
|
51 public: |
|
52 JSTracer(JSRuntime *rt, JSTraceCallback traceCallback, |
|
53 WeakMapTraceKind weakTraceKind = TraceWeakMapValues); |
|
54 |
|
55 // Set debugging information about a reference to a traceable thing to prepare |
|
56 // for the following call to JS_CallTracer. |
|
57 // |
|
58 // When printer is null, arg must be const char * or char * C string naming |
|
59 // the reference and index must be either (size_t)-1 indicating that the name |
|
60 // alone describes the reference or it must be an index into some array vector |
|
61 // that stores the reference. |
|
62 // |
|
63 // When printer callback is not null, the arg and index arguments are |
|
64 // available to the callback as debugPrintArg_ and debugPrintIndex_ fields |
|
65 // of JSTracer. |
|
66 // |
|
67 // The storage for name or callback's arguments needs to live only until |
|
68 // the following call to JS_CallTracer returns. |
|
69 void setTracingDetails(JSTraceNamePrinter printer, const void *arg, size_t index) { |
|
70 debugPrinter_ = printer; |
|
71 debugPrintArg_ = arg; |
|
72 debugPrintIndex_ = index; |
|
73 } |
|
74 |
|
75 void setTracingIndex(const char *name, size_t index) { |
|
76 setTracingDetails(nullptr, (void *)name, index); |
|
77 } |
|
78 |
|
79 void setTracingName(const char *name) { |
|
80 setTracingDetails(nullptr, (void *)name, size_t(-1)); |
|
81 } |
|
82 |
|
83 // Remove the currently set tracing details. |
|
84 void clearTracingDetails() { |
|
85 debugPrinter_ = nullptr; |
|
86 debugPrintArg_ = nullptr; |
|
87 } |
|
88 |
|
89 // Return true if tracing details are currently set. |
|
90 bool hasTracingDetails() const; |
|
91 |
|
92 // Get the string set with the most recent call to setTracingName or return |
|
93 // fallback if a name printer function has been installed. |
|
94 const char *tracingName(const char *fallback) const; |
|
95 |
|
96 // Build a description of this edge in the heap graph. This call may invoke |
|
97 // the debug printer, which may inspect arbitrary areas of the heap. |
|
98 const char *getTracingEdgeName(char *buffer, size_t bufferSize); |
|
99 |
|
100 // Access the currently active tracing details. |
|
101 JSTraceNamePrinter debugPrinter() const; |
|
102 const void *debugPrintArg() const; |
|
103 size_t debugPrintIndex() const; |
|
104 |
|
105 // Return the runtime set on the tracer. |
|
106 JSRuntime *runtime() const { return runtime_; } |
|
107 |
|
108 // Return the weak map tracing behavior set on this tracer. |
|
109 WeakMapTraceKind eagerlyTraceWeakMaps() const { return eagerlyTraceWeakMaps_; } |
|
110 |
|
111 // Update the trace callback. |
|
112 void setTraceCallback(JSTraceCallback traceCallback); |
|
113 |
|
114 #ifdef JS_GC_ZEAL |
|
115 // Sets the "real" location for a marked reference, when passing the address |
|
116 // directly is not feasable. This address is used for matching against the |
|
117 // store buffer when verifying the correctness of the entrees there. |
|
118 // |
|
119 // This is currently complicated by our need to nest calls for Values |
|
120 // stored as keys in hash tables. |
|
121 void setTracingLocation(void *location); |
|
122 void unsetTracingLocation(); |
|
123 void **tracingLocation(void **thingp); |
|
124 #else |
|
125 void setTracingLocation(void *location) {} |
|
126 void unsetTracingLocation() {} |
|
127 void **tracingLocation(void **thingp) { return nullptr; } |
|
128 #endif |
|
129 |
|
130 // We expose |callback| directly so that IS_GC_MARKING_TRACER can compare |
|
131 // it to GCMarker::GrayCallback. |
|
132 JSTraceCallback callback; |
|
133 |
|
134 private: |
|
135 JSRuntime *runtime_; |
|
136 JSTraceNamePrinter debugPrinter_; |
|
137 const void *debugPrintArg_; |
|
138 size_t debugPrintIndex_; |
|
139 WeakMapTraceKind eagerlyTraceWeakMaps_; |
|
140 #ifdef JS_GC_ZEAL |
|
141 void *realLocation_; |
|
142 #endif |
|
143 }; |
|
144 |
|
145 // The JS_Call*Tracer family of functions traces the given GC thing reference. |
|
146 // This performs the tracing action configured on the given JSTracer: |
|
147 // typically calling the JSTracer::callback or marking the thing as live. |
|
148 // |
|
149 // The argument to JS_Call*Tracer is an in-out param: when the function |
|
150 // returns, the garbage collector might have moved the GC thing. In this case, |
|
151 // the reference passed to JS_Call*Tracer will be updated to the object's new |
|
152 // location. Callers of this method are responsible for updating any state |
|
153 // that is dependent on the object's address. For example, if the object's |
|
154 // address is used as a key in a hashtable, then the object must be removed |
|
155 // and re-inserted with the correct hash. |
|
156 // |
|
157 extern JS_PUBLIC_API(void) |
|
158 JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name); |
|
159 |
|
160 extern JS_PUBLIC_API(void) |
|
161 JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name); |
|
162 |
|
163 extern JS_PUBLIC_API(void) |
|
164 JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name); |
|
165 |
|
166 extern JS_PUBLIC_API(void) |
|
167 JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name); |
|
168 |
|
169 extern JS_PUBLIC_API(void) |
|
170 JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name); |
|
171 |
|
172 extern JS_PUBLIC_API(void) |
|
173 JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name); |
|
174 |
|
175 extern JS_PUBLIC_API(void) |
|
176 JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name); |
|
177 |
|
178 extern JS_PUBLIC_API(void) |
|
179 JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name); |
|
180 |
|
181 extern JS_PUBLIC_API(void) |
|
182 JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name); |
|
183 |
|
184 extern JS_PUBLIC_API(void) |
|
185 JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name); |
|
186 |
|
187 extern JS_PUBLIC_API(void) |
|
188 JS_CallHeapFunctionTracer(JSTracer *trc, JS::Heap<JSFunction *> *funp, const char *name); |
|
189 |
|
190 template <typename HashSetEnum> |
|
191 inline void |
|
192 JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name) |
|
193 { |
|
194 JSObject *updated = key; |
|
195 trc->setTracingLocation(reinterpret_cast<void *>(&const_cast<JSObject *&>(key))); |
|
196 JS_CallObjectTracer(trc, &updated, name); |
|
197 if (updated != key) |
|
198 e.rekeyFront(key, updated); |
|
199 } |
|
200 |
|
201 // Trace an object that is known to always be tenured. No post barriers are |
|
202 // required in this case. |
|
203 extern JS_PUBLIC_API(void) |
|
204 JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name); |
|
205 |
|
206 extern JS_PUBLIC_API(void) |
|
207 JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind); |
|
208 |
|
209 extern JS_PUBLIC_API(void) |
|
210 JS_TraceRuntime(JSTracer *trc); |
|
211 |
|
212 extern JS_PUBLIC_API(void) |
|
213 JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, |
|
214 void *thing, JSGCTraceKind kind, bool includeDetails); |
|
215 |
|
216 #endif /* js_TracingAPI_h */ |