1 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=80:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 : * June 12, 2009.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * the Mozilla Corporation.
22 : *
23 : * Contributor(s):
24 : * Steve Fink <sfink@mozilla.org>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef _JSPROBES_H
41 : #define _JSPROBES_H
42 :
43 : #ifdef INCLUDE_MOZILLA_DTRACE
44 : #include "javascript-trace.h"
45 : #endif
46 : #include "jspubtd.h"
47 : #include "jsprvtd.h"
48 : #include "jsscript.h"
49 : #include "jsobj.h"
50 :
51 : #ifdef JS_METHODJIT
52 : #include "methodjit/MethodJIT.h"
53 : #endif
54 :
55 : #include "vm/ObjectImpl-inl.h"
56 :
57 : namespace js {
58 :
59 : namespace mjit {
60 : struct NativeAddressInfo;
61 : struct JSActiveFrame;
62 : }
63 :
64 : namespace Probes {
65 :
66 : /*
67 : * Static probes
68 : *
69 : * The probe points defined in this file are scattered around the SpiderMonkey
70 : * source tree. The presence of Probes::someEvent() means that someEvent is
71 : * about to happen or has happened. To the extent possible, probes should be
72 : * inserted in all paths associated with a given event, regardless of the
73 : * active runmode (interpreter/traceJIT/methodJIT/ionJIT).
74 : *
75 : * When a probe fires, it is handled by any probe handling backends that have
76 : * been compiled in. By default, most probes do nothing or at least do nothing
77 : * expensive, so the presence of the probe should have negligible effect on
78 : * running time. (Probes in slow paths may do something by default, as long as
79 : * there is no noticeable slowdown.)
80 : *
81 : * For some probes, the mere existence of the probe is too expensive even if it
82 : * does nothing when called. For example, just having consistent information
83 : * available for a function call entry/exit probe causes the JITs to
84 : * de-optimize function calls. In those cases, the JITs may query at compile
85 : * time whether a probe is desired, and omit the probe invocation if not. If a
86 : * probe is runtime-disabled at compilation time, it is not guaranteed to fire
87 : * within a compiled function if it is later enabled.
88 : *
89 : * Not all backends handle all of the probes listed here.
90 : */
91 :
92 : /*
93 : * Internal use only: remember whether "profiling", whatever that means, is
94 : * currently active. Used for state management.
95 : */
96 : extern bool ProfilingActive;
97 :
98 : extern const char nullName[];
99 : extern const char anonymousName[];
100 :
101 : /* Called when first runtime is created for this process */
102 : JSBool startEngine();
103 :
104 : /* JSRuntime created, with currently valid fields */
105 : bool createRuntime(JSRuntime *rt);
106 :
107 : /* JSRuntime about to be destroyed */
108 : bool destroyRuntime(JSRuntime *rt);
109 :
110 : /* Total JS engine shutdown */
111 : bool shutdown();
112 :
113 : /*
114 : * Test whether we are tracking JS function call enter/exit. The JITs use this
115 : * to decide whether they can optimize in a way that would prevent probes from
116 : * firing.
117 : */
118 : bool callTrackingActive(JSContext *);
119 :
120 : /*
121 : * Test whether anything is looking for JIT native code registration events.
122 : * This information will not be collected otherwise.
123 : */
124 : bool wantNativeAddressInfo(JSContext *);
125 :
126 : /* Entering a JS function */
127 : bool enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
128 :
129 : /* About to leave a JS function */
130 : bool exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
131 :
132 : /* Executing a script */
133 : bool startExecution(JSContext *cx, JSScript *script);
134 :
135 : /* Script has completed execution */
136 : bool stopExecution(JSContext *cx, JSScript *script);
137 :
138 : /* Heap has been resized */
139 : bool resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
140 :
141 : /*
142 : * Object has been created. |obj| must exist (its class and size are read)
143 : */
144 : bool createObject(JSContext *cx, JSObject *obj);
145 :
146 : /* Resize events are being tracked. */
147 : bool objectResizeActive();
148 :
149 : /* Object has been resized */
150 : bool resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
151 :
152 : /*
153 : * Object is about to be finalized. |obj| must still exist (its class is
154 : * read)
155 : */
156 : bool finalizeObject(JSObject *obj);
157 :
158 : /*
159 : * String has been created.
160 : *
161 : * |string|'s content is not (yet) valid. |length| is the length of the string
162 : * and does not imply anything about the amount of storage consumed to store
163 : * the string. (It may be a short string, an external string, or a rope, and
164 : * the encoding is not taken into consideration.)
165 : */
166 : bool createString(JSContext *cx, JSString *string, size_t length);
167 :
168 : /*
169 : * String is about to be finalized
170 : *
171 : * |string| must still have a valid length.
172 : */
173 : bool finalizeString(JSString *string);
174 :
175 : /* Script is about to be compiled */
176 : bool compileScriptBegin(JSContext *cx, const char *filename, int lineno);
177 :
178 : /* Script has just finished compilation */
179 : bool compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno);
180 :
181 : /* About to make a call from JS into native code */
182 : bool calloutBegin(JSContext *cx, JSFunction *fun);
183 :
184 : /* Native code called by JS has terminated */
185 : bool calloutEnd(JSContext *cx, JSFunction *fun);
186 :
187 : /* Unimplemented */
188 : bool acquireMemory(JSContext *cx, void *address, size_t nbytes);
189 : bool releaseMemory(JSContext *cx, void *address, size_t nbytes);
190 :
191 : /*
192 : * Garbage collection probes
193 : *
194 : * GC timing is tricky and at the time of this writing is changing frequently.
195 : * GCStart/GCEnd are intended to bracket the entire garbage collection (either
196 : * global or single-compartment), but a separate thread may continue doing work
197 : * after GCEnd.
198 : *
199 : * Multiple compartments' GC will be interleaved during a global collection
200 : * (eg, compartment 1 starts, compartment 2 starts, compartment 1 ends, ...)
201 : */
202 : bool GCStart();
203 : bool GCEnd();
204 :
205 : bool GCStartMarkPhase();
206 : bool GCEndMarkPhase();
207 :
208 : bool GCStartSweepPhase();
209 : bool GCEndSweepPhase();
210 :
211 : /*
212 : * Various APIs for inserting custom probe points. These might be used to mark
213 : * when something starts and stops, or for various other purposes the user has
214 : * in mind. These are useful to export to JS so that JS code can mark
215 : * application-meaningful events and phases of execution.
216 : *
217 : * Not all backends support these.
218 : */
219 : bool CustomMark(JSString *string);
220 : bool CustomMark(const char *string);
221 : bool CustomMark(int marker);
222 :
223 : /* JIT code observation */
224 :
225 : enum JITReportGranularity {
226 : JITREPORT_GRANULARITY_NONE = 0,
227 : JITREPORT_GRANULARITY_FUNCTION = 1,
228 : JITREPORT_GRANULARITY_LINE = 2,
229 : JITREPORT_GRANULARITY_OP = 3
230 : };
231 :
232 : /*
233 : * Observer class for JIT code allocation/deallocation. Currently, this only
234 : * handles the method JIT, and does not get notifications when JIT code is
235 : * changed (patched) with no new allocation.
236 : */
237 0 : class JITWatcher {
238 : public:
239 0 : struct NativeRegion {
240 : mjit::JSActiveFrame *frame;
241 : JSScript *script;
242 : size_t inlinedOffset;
243 : jsbytecode *pc;
244 : jsbytecode *endpc;
245 : uintptr_t mainOffset;
246 : uintptr_t stubOffset;
247 : bool enter;
248 : };
249 :
250 : typedef Vector<NativeRegion, 0, RuntimeAllocPolicy> RegionVector;
251 :
252 : virtual JITReportGranularity granularityRequested() = 0;
253 :
254 : #ifdef JS_METHODJIT
255 : static bool CollectNativeRegions(RegionVector ®ions,
256 : JSRuntime *rt,
257 : mjit::JITChunk *jit,
258 : mjit::JSActiveFrame *outerFrame,
259 : mjit::JSActiveFrame **inlineFrames);
260 :
261 : virtual void registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
262 : mjit::JSActiveFrame *outerFrame,
263 : mjit::JSActiveFrame **inlineFrames,
264 : void *mainCodeAddress, size_t mainCodeSize,
265 : void *stubCodeAddress, size_t stubCodeSize) = 0;
266 :
267 : virtual void discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, JSScript *script,
268 : void* address) = 0;
269 :
270 : virtual void registerICCode(JSContext *cx,
271 : js::mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
272 : void *start, size_t size) = 0;
273 : #endif
274 :
275 : virtual void discardExecutableRegion(void *start, size_t size) = 0;
276 : };
277 :
278 : /*
279 : * Register a JITWatcher subclass to be informed of JIT code
280 : * allocation/deallocation.
281 : */
282 : bool
283 : addJITWatcher(JITWatcher *watcher);
284 :
285 : /*
286 : * Remove (and destroy) a registered JITWatcher. rt may be NULL. Returns false
287 : * if the watcher is not found.
288 : */
289 : bool
290 : removeJITWatcher(JSRuntime *rt, JITWatcher *watcher);
291 :
292 : /*
293 : * Remove (and destroy) all registered JITWatchers. rt may be NULL.
294 : */
295 : void
296 : removeAllJITWatchers(JSRuntime *rt);
297 :
298 : /*
299 : * Finest granularity of JIT information desired by all watchers.
300 : */
301 : JITReportGranularity
302 : JITGranularityRequested();
303 :
304 : #ifdef JS_METHODJIT
305 : /*
306 : * New method JIT code has been created
307 : */
308 : void
309 : registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
310 : mjit::JSActiveFrame *outerFrame,
311 : mjit::JSActiveFrame **inlineFrames,
312 : void *mainCodeAddress, size_t mainCodeSize,
313 : void *stubCodeAddress, size_t stubCodeSize);
314 :
315 : /*
316 : * Method JIT code is about to be discarded
317 : */
318 : void
319 : discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, JSScript *script, void* address);
320 :
321 : /*
322 : * IC code has been allocated within the given JITScript
323 : */
324 : void
325 : registerICCode(JSContext *cx,
326 : mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
327 : void *start, size_t size);
328 : #endif /* JS_METHODJIT */
329 :
330 : /*
331 : * A whole region of code has been deallocated, containing any number of ICs.
332 : * (ICs are unregistered in a batch, so individual ICs are not registered.)
333 : */
334 : void
335 : discardExecutableRegion(void *start, size_t size);
336 :
337 : /*
338 : * Internal: DTrace-specific functions to be called during Probes::enterJSFun
339 : * and Probes::exitJSFun. These will not be inlined, but the argument
340 : * marshalling required for these probe points is expensive enough that it
341 : * shouldn't really matter.
342 : */
343 : void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
344 : void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
345 :
346 : /*
347 : * Internal: ETW-specific probe functions
348 : */
349 : #ifdef MOZ_ETW
350 : // ETW Handlers
351 : bool ETWCreateRuntime(JSRuntime *rt);
352 : bool ETWDestroyRuntime(JSRuntime *rt);
353 : bool ETWShutdown();
354 : bool ETWCallTrackingActive(JSContext *cx);
355 : bool ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
356 : bool ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
357 : bool ETWCreateObject(JSContext *cx, JSObject *obj);
358 : bool ETWFinalizeObject(JSObject *obj);
359 : bool ETWResizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
360 : bool ETWCreateString(JSContext *cx, JSString *string, size_t length);
361 : bool ETWFinalizeString(JSString *string);
362 : bool ETWCompileScriptBegin(const char *filename, int lineno);
363 : bool ETWCompileScriptEnd(const char *filename, int lineno);
364 : bool ETWCalloutBegin(JSContext *cx, JSFunction *fun);
365 : bool ETWCalloutEnd(JSContext *cx, JSFunction *fun);
366 : bool ETWAcquireMemory(JSContext *cx, void *address, size_t nbytes);
367 : bool ETWReleaseMemory(JSContext *cx, void *address, size_t nbytes);
368 : bool ETWGCStart();
369 : bool ETWGCEnd();
370 : bool ETWGCStartMarkPhase();
371 : bool ETWGCEndMarkPhase();
372 : bool ETWGCStartSweepPhase();
373 : bool ETWGCEndSweepPhase();
374 : bool ETWCustomMark(JSString *string);
375 : bool ETWCustomMark(const char *string);
376 : bool ETWCustomMark(int marker);
377 : bool ETWStartExecution(JSContext *cx, JSScript *script);
378 : bool ETWStopExecution(JSContext *cx, JSScript *script);
379 : bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
380 : #endif
381 :
382 : } /* namespace Probes */
383 :
384 : /*
385 : * Many probe handlers are implemented inline for minimal performance impact,
386 : * especially important when no backends are enabled.
387 : */
388 :
389 : inline bool
390 90972 : Probes::callTrackingActive(JSContext *cx)
391 : {
392 : #ifdef INCLUDE_MOZILLA_DTRACE
393 : if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
394 : return true;
395 : #endif
396 : #ifdef MOZ_TRACE_JSCALLS
397 : if (cx->functionCallback)
398 : return true;
399 : #endif
400 : #ifdef MOZ_ETW
401 : if (ProfilingActive && ETWCallTrackingActive(cx))
402 : return true;
403 : #endif
404 90972 : return false;
405 : }
406 :
407 : inline bool
408 93731 : Probes::wantNativeAddressInfo(JSContext *cx)
409 : {
410 : return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
411 93731 : JITGranularityRequested() >= JITREPORT_GRANULARITY_FUNCTION);
412 : }
413 :
414 : inline bool
415 21568128 : Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
416 : {
417 21568128 : bool ok = true;
418 : #ifdef INCLUDE_MOZILLA_DTRACE
419 : if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
420 : DTraceEnterJSFun(cx, fun, script);
421 : #endif
422 : #ifdef MOZ_TRACE_JSCALLS
423 : cx->doFunctionCallback(fun, script, counter);
424 : #endif
425 : #ifdef MOZ_ETW
426 : if (ProfilingActive && !ETWEnterJSFun(cx, fun, script, counter))
427 : ok = false;
428 : #endif
429 :
430 21568128 : return ok;
431 : }
432 :
433 : inline bool
434 22755559 : Probes::exitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
435 : {
436 22755559 : bool ok = true;
437 :
438 : #ifdef INCLUDE_MOZILLA_DTRACE
439 : if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
440 : DTraceExitJSFun(cx, fun, script);
441 : #endif
442 : #ifdef MOZ_TRACE_JSCALLS
443 : if (counter > 0)
444 : counter = -counter;
445 : cx->doFunctionCallback(fun, script, counter);
446 : #endif
447 : #ifdef MOZ_ETW
448 : if (ProfilingActive && !ETWExitJSFun(cx, fun, script, counter))
449 : ok = false;
450 : #endif
451 :
452 22755559 : return ok;
453 : }
454 :
455 : inline bool
456 3366654 : Probes::resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
457 : {
458 3366654 : bool ok = true;
459 :
460 : #ifdef MOZ_ETW
461 : if (ProfilingActive && !ETWResizeHeap(compartment, oldSize, newSize))
462 : ok = false;
463 : #endif
464 :
465 3366654 : return ok;
466 : }
467 :
468 : #ifdef INCLUDE_MOZILLA_DTRACE
469 : static const char *ObjectClassname(JSObject *obj) {
470 : if (!obj)
471 : return "(null object)";
472 : Class *clasp = obj->getClass();
473 : if (!clasp)
474 : return "(null)";
475 : const char *class_name = clasp->name;
476 : if (!class_name)
477 : return "(null class name)";
478 : return class_name;
479 : }
480 : #endif
481 :
482 : inline bool
483 24214851 : Probes::createObject(JSContext *cx, JSObject *obj)
484 : {
485 24214851 : bool ok = true;
486 :
487 : #ifdef INCLUDE_MOZILLA_DTRACE
488 : if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
489 : JAVASCRIPT_OBJECT_CREATE(ObjectClassname(obj), (uintptr_t)obj);
490 : #endif
491 : #ifdef MOZ_ETW
492 : if (ProfilingActive && !ETWCreateObject(cx, obj))
493 : ok = false;
494 : #endif
495 :
496 24214851 : return ok;
497 : }
498 :
499 : inline bool
500 30978300 : Probes::finalizeObject(JSObject *obj)
501 : {
502 30978300 : bool ok = true;
503 :
504 : #ifdef INCLUDE_MOZILLA_DTRACE
505 : if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED()) {
506 : Class *clasp = obj->getClass();
507 :
508 : /* the first arg is NULL - reserved for future use (filename?) */
509 : JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
510 : }
511 : #endif
512 : #ifdef MOZ_ETW
513 : if (ProfilingActive && !ETWFinalizeObject(obj))
514 : ok = false;
515 : #endif
516 :
517 30978300 : return ok;
518 : }
519 :
520 : inline bool
521 9044763 : Probes::objectResizeActive()
522 : {
523 : #ifdef MOZ_ETW
524 : if (ProfilingActive)
525 : return true;
526 : #endif
527 :
528 9044763 : return false;
529 : }
530 :
531 : inline bool
532 0 : Probes::resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize)
533 : {
534 0 : bool ok = true;
535 :
536 : #ifdef MOZ_ETW
537 : if (ProfilingActive && !ETWResizeObject(cx, obj, oldSize, newSize))
538 : ok = false;
539 : #endif
540 :
541 0 : return ok;
542 : }
543 :
544 : inline bool
545 99764681 : Probes::createString(JSContext *cx, JSString *string, size_t length)
546 : {
547 99764681 : bool ok = true;
548 :
549 : #ifdef MOZ_ETW
550 : if (ProfilingActive && !ETWCreateString(cx, string, length))
551 : ok = false;
552 : #endif
553 :
554 99764681 : return ok;
555 : }
556 :
557 : inline bool
558 : Probes::finalizeString(JSString *string)
559 : {
560 : bool ok = true;
561 :
562 : #ifdef MOZ_ETW
563 : if (ProfilingActive && !ETWFinalizeString(string))
564 : ok = false;
565 : #endif
566 :
567 : return ok;
568 : }
569 :
570 : inline bool
571 94838 : Probes::compileScriptBegin(JSContext *cx, const char *filename, int lineno)
572 : {
573 94838 : bool ok = true;
574 :
575 : #ifdef MOZ_ETW
576 : if (ProfilingActive && !ETWCompileScriptBegin(filename, lineno))
577 : ok = false;
578 : #endif
579 :
580 94838 : return ok;
581 : }
582 :
583 : inline bool
584 94838 : Probes::compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno)
585 : {
586 94838 : bool ok = true;
587 :
588 : #ifdef MOZ_ETW
589 : if (ProfilingActive && !ETWCompileScriptEnd(filename, lineno))
590 : ok = false;
591 : #endif
592 :
593 94838 : return ok;
594 : }
595 :
596 : inline bool
597 214660 : Probes::calloutBegin(JSContext *cx, JSFunction *fun)
598 : {
599 214660 : bool ok = true;
600 :
601 : #ifdef MOZ_ETW
602 : if (ProfilingActive && !ETWCalloutBegin(cx, fun))
603 : ok = false;
604 : #endif
605 :
606 214660 : return ok;
607 : }
608 :
609 : inline bool
610 214660 : Probes::calloutEnd(JSContext *cx, JSFunction *fun)
611 : {
612 214660 : bool ok = true;
613 :
614 : #ifdef MOZ_ETW
615 : if (ProfilingActive && !ETWCalloutEnd(cx, fun))
616 : ok = false;
617 : #endif
618 :
619 214660 : return ok;
620 : }
621 :
622 : inline bool
623 : Probes::acquireMemory(JSContext *cx, void *address, size_t nbytes)
624 : {
625 : bool ok = true;
626 :
627 : #ifdef MOZ_ETW
628 : if (ProfilingActive && !ETWAcquireMemory(cx, address, nbytes))
629 : ok = false;
630 : #endif
631 :
632 : return ok;
633 : }
634 :
635 : inline bool
636 : Probes::releaseMemory(JSContext *cx, void *address, size_t nbytes)
637 : {
638 : bool ok = true;
639 :
640 : #ifdef MOZ_ETW
641 : if (ProfilingActive && !ETWReleaseMemory(cx, address, nbytes))
642 : ok = false;
643 : #endif
644 :
645 : return ok;
646 : }
647 :
648 : inline bool
649 38427 : Probes::GCStart()
650 : {
651 38427 : bool ok = true;
652 :
653 : #ifdef MOZ_ETW
654 : if (ProfilingActive && !ETWGCStart())
655 : ok = false;
656 : #endif
657 :
658 38427 : return ok;
659 : }
660 :
661 : inline bool
662 38427 : Probes::GCEnd()
663 : {
664 38427 : bool ok = true;
665 :
666 : #ifdef MOZ_ETW
667 : if (ProfilingActive && !ETWGCEnd())
668 : ok = false;
669 : #endif
670 :
671 38427 : return ok;
672 : }
673 :
674 : inline bool
675 115362 : Probes::GCStartMarkPhase()
676 : {
677 115362 : bool ok = true;
678 :
679 : #ifdef MOZ_ETW
680 : if (ProfilingActive && !ETWGCStartMarkPhase())
681 : ok = false;
682 : #endif
683 :
684 115362 : return ok;
685 : }
686 :
687 : inline bool
688 115362 : Probes::GCEndMarkPhase()
689 : {
690 115362 : bool ok = true;
691 :
692 : #ifdef MOZ_ETW
693 : if (ProfilingActive && !ETWGCEndMarkPhase())
694 : ok = false;
695 : #endif
696 :
697 115362 : return ok;
698 : }
699 :
700 : inline bool
701 38427 : Probes::GCStartSweepPhase()
702 : {
703 38427 : bool ok = true;
704 :
705 : #ifdef MOZ_ETW
706 : if (ProfilingActive && !ETWGCStartSweepPhase())
707 : ok = false;
708 : #endif
709 :
710 38427 : return ok;
711 : }
712 :
713 : inline bool
714 38427 : Probes::GCEndSweepPhase()
715 : {
716 38427 : bool ok = true;
717 :
718 : #ifdef MOZ_ETW
719 : if (ProfilingActive && !ETWGCEndSweepPhase())
720 : ok = false;
721 : #endif
722 :
723 38427 : return ok;
724 : }
725 :
726 : inline bool
727 : Probes::CustomMark(JSString *string)
728 : {
729 : bool ok = true;
730 :
731 : #ifdef MOZ_ETW
732 : if (ProfilingActive && !ETWCustomMark(string))
733 : ok = false;
734 : #endif
735 :
736 : return ok;
737 : }
738 :
739 : inline bool
740 : Probes::CustomMark(const char *string)
741 : {
742 : bool ok = true;
743 :
744 : #ifdef MOZ_ETW
745 : if (ProfilingActive && !ETWCustomMark(string))
746 : ok = false;
747 : #endif
748 :
749 : return ok;
750 : }
751 :
752 : inline bool
753 : Probes::CustomMark(int marker)
754 : {
755 : bool ok = true;
756 :
757 : #ifdef MOZ_ETW
758 : if (ProfilingActive && !ETWCustomMark(marker))
759 : ok = false;
760 : #endif
761 :
762 : return ok;
763 : }
764 :
765 : inline bool
766 152647 : Probes::startExecution(JSContext *cx, JSScript *script)
767 : {
768 152647 : bool ok = true;
769 :
770 : #ifdef INCLUDE_MOZILLA_DTRACE
771 : if (JAVASCRIPT_EXECUTE_START_ENABLED())
772 : JAVASCRIPT_EXECUTE_START((script->filename ? (char *)script->filename : nullName),
773 : script->lineno);
774 : #endif
775 : #ifdef MOZ_ETW
776 : if (ProfilingActive && !ETWStartExecution(cx, script))
777 : ok = false;
778 : #endif
779 :
780 152647 : return ok;
781 : }
782 :
783 : inline bool
784 152647 : Probes::stopExecution(JSContext *cx, JSScript *script)
785 : {
786 152647 : bool ok = true;
787 :
788 : #ifdef INCLUDE_MOZILLA_DTRACE
789 : if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
790 : JAVASCRIPT_EXECUTE_DONE((script->filename ? (char *)script->filename : nullName),
791 : script->lineno);
792 : #endif
793 : #ifdef MOZ_ETW
794 : if (ProfilingActive && !ETWStopExecution(cx, script))
795 : ok = false;
796 : #endif
797 :
798 152647 : return ok;
799 : }
800 :
801 : struct AutoFunctionCallProbe {
802 : JSContext * const cx;
803 : JSFunction *fun;
804 : JSScript *script;
805 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
806 :
807 83570 : AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, JSScript *script
808 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
809 83570 : : cx(cx), fun(fun), script(script)
810 : {
811 83570 : JS_GUARD_OBJECT_NOTIFIER_INIT;
812 83570 : Probes::enterJSFun(cx, fun, script);
813 83570 : }
814 :
815 167140 : ~AutoFunctionCallProbe() {
816 83570 : Probes::exitJSFun(cx, fun, script);
817 83570 : }
818 : };
819 :
820 : } /* namespace js */
821 :
822 : /*
823 : * Internal functions for controlling various profilers. The profiler-specific
824 : * implementations of these are mostly in jsdbgapi.cpp.
825 : */
826 :
827 : #endif /* _JSPROBES_H */
|