Bug 752461 - Hide click-to-play overlays when choosing "never activate plugins.....
[gecko.git] / js / src / jsprobes.h
blobc64daf4e2119f69703503ebbaec505edb7508901
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=80:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
17 * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
18 * June 12, 2009.
20 * The Initial Developer of the Original Code is
21 * the Mozilla Corporation.
23 * Contributor(s):
24 * Steve Fink <sfink@mozilla.org>
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.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef _JSPROBES_H
41 #define _JSPROBES_H
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"
51 #ifdef JS_METHODJIT
52 #include "methodjit/MethodJIT.h"
53 #endif
55 #include "vm/ObjectImpl-inl.h"
57 namespace js {
59 namespace mjit {
60 struct NativeAddressInfo;
61 struct JSActiveFrame;
64 namespace Probes {
67 * Static probes
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).
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.)
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.
89 * Not all backends handle all of the probes listed here.
93 * Internal use only: remember whether "profiling", whatever that means, is
94 * currently active. Used for state management.
96 extern bool ProfilingActive;
98 extern const char nullName[];
99 extern const char anonymousName[];
101 /* Called when first runtime is created for this process */
102 JSBool startEngine();
104 /* JSRuntime created, with currently valid fields */
105 bool createRuntime(JSRuntime *rt);
107 /* JSRuntime about to be destroyed */
108 bool destroyRuntime(JSRuntime *rt);
110 /* Total JS engine shutdown */
111 bool shutdown();
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.
118 bool callTrackingActive(JSContext *);
121 * Test whether anything is looking for JIT native code registration events.
122 * This information will not be collected otherwise.
124 bool wantNativeAddressInfo(JSContext *);
126 /* Entering a JS function */
127 bool enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
129 /* About to leave a JS function */
130 bool exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
132 /* Executing a script */
133 bool startExecution(JSContext *cx, JSScript *script);
135 /* Script has completed execution */
136 bool stopExecution(JSContext *cx, JSScript *script);
138 /* Heap has been resized */
139 bool resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
142 * Object has been created. |obj| must exist (its class and size are read)
144 bool createObject(JSContext *cx, JSObject *obj);
146 /* Resize events are being tracked. */
147 bool objectResizeActive();
149 /* Object has been resized */
150 bool resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
153 * Object is about to be finalized. |obj| must still exist (its class is
154 * read)
156 bool finalizeObject(JSObject *obj);
159 * String has been created.
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.)
166 bool createString(JSContext *cx, JSString *string, size_t length);
169 * String is about to be finalized
171 * |string| must still have a valid length.
173 bool finalizeString(JSString *string);
175 /* Script is about to be compiled */
176 bool compileScriptBegin(JSContext *cx, const char *filename, int lineno);
178 /* Script has just finished compilation */
179 bool compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno);
181 /* About to make a call from JS into native code */
182 bool calloutBegin(JSContext *cx, JSFunction *fun);
184 /* Native code called by JS has terminated */
185 bool calloutEnd(JSContext *cx, JSFunction *fun);
187 /* Unimplemented */
188 bool acquireMemory(JSContext *cx, void *address, size_t nbytes);
189 bool releaseMemory(JSContext *cx, void *address, size_t nbytes);
192 * Garbage collection probes
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.
199 * Multiple compartments' GC will be interleaved during a global collection
200 * (eg, compartment 1 starts, compartment 2 starts, compartment 1 ends, ...)
202 bool GCStart();
203 bool GCEnd();
205 bool GCStartMarkPhase();
206 bool GCEndMarkPhase();
208 bool GCStartSweepPhase();
209 bool GCEndSweepPhase();
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.
217 * Not all backends support these.
219 bool CustomMark(JSString *string);
220 bool CustomMark(const char *string);
221 bool CustomMark(int marker);
223 /* JIT code observation */
225 enum JITReportGranularity {
226 JITREPORT_GRANULARITY_NONE = 0,
227 JITREPORT_GRANULARITY_FUNCTION = 1,
228 JITREPORT_GRANULARITY_LINE = 2,
229 JITREPORT_GRANULARITY_OP = 3
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.
237 class JITWatcher {
238 public:
239 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;
250 typedef Vector<NativeRegion, 0, RuntimeAllocPolicy> RegionVector;
252 virtual JITReportGranularity granularityRequested() = 0;
254 #ifdef JS_METHODJIT
255 static bool CollectNativeRegions(RegionVector &regions,
256 JSRuntime *rt,
257 mjit::JITChunk *jit,
258 mjit::JSActiveFrame *outerFrame,
259 mjit::JSActiveFrame **inlineFrames);
261 virtual void registerMJITCode(JSContext *cx, js::mjit::JITChunk *chunk,
262 mjit::JSActiveFrame *outerFrame,
263 mjit::JSActiveFrame **inlineFrames,
264 void *mainCodeAddress, size_t mainCodeSize,
265 void *stubCodeAddress, size_t stubCodeSize) = 0;
267 virtual void discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, mjit::JITChunk *chunk,
268 void* address) = 0;
270 virtual void registerICCode(JSContext *cx,
271 js::mjit::JITChunk *chunk, JSScript *script, jsbytecode* pc,
272 void *start, size_t size) = 0;
273 #endif
275 virtual void discardExecutableRegion(void *start, size_t size) = 0;
279 * Register a JITWatcher subclass to be informed of JIT code
280 * allocation/deallocation.
282 bool
283 addJITWatcher(JITWatcher *watcher);
286 * Remove (and destroy) a registered JITWatcher. rt may be NULL. Returns false
287 * if the watcher is not found.
289 bool
290 removeJITWatcher(JSRuntime *rt, JITWatcher *watcher);
293 * Remove (and destroy) all registered JITWatchers. rt may be NULL.
295 void
296 removeAllJITWatchers(JSRuntime *rt);
299 * Finest granularity of JIT information desired by all watchers.
301 JITReportGranularity
302 JITGranularityRequested();
304 #ifdef JS_METHODJIT
306 * New method JIT code has been created
308 void
309 registerMJITCode(JSContext *cx, js::mjit::JITChunk *chunk,
310 mjit::JSActiveFrame *outerFrame,
311 mjit::JSActiveFrame **inlineFrames,
312 void *mainCodeAddress, size_t mainCodeSize,
313 void *stubCodeAddress, size_t stubCodeSize);
316 * Method JIT code is about to be discarded
318 void
319 discardMJITCode(FreeOp *fop, mjit::JITScript *jscr, mjit::JITChunk *chunk, void* address);
322 * IC code has been allocated within the given JITChunk
324 void
325 registerICCode(JSContext *cx,
326 mjit::JITChunk *chunk, JSScript *script, jsbytecode* pc,
327 void *start, size_t size);
328 #endif /* JS_METHODJIT */
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.)
334 void
335 discardExecutableRegion(void *start, size_t size);
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.
343 void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
344 void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
347 * Internal: ETW-specific probe functions
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
382 } /* namespace Probes */
385 * Many probe handlers are implemented inline for minimal performance impact,
386 * especially important when no backends are enabled.
389 inline bool
390 Probes::callTrackingActive(JSContext *cx)
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 return false;
407 inline bool
408 Probes::wantNativeAddressInfo(JSContext *cx)
410 return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
411 JITGranularityRequested() >= JITREPORT_GRANULARITY_FUNCTION);
414 inline bool
415 Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
417 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
430 return ok;
433 inline bool
434 Probes::exitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
436 bool ok = true;
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
452 return ok;
455 inline bool
456 Probes::resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
458 bool ok = true;
460 #ifdef MOZ_ETW
461 if (ProfilingActive && !ETWResizeHeap(compartment, oldSize, newSize))
462 ok = false;
463 #endif
465 return ok;
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;
480 #endif
482 inline bool
483 Probes::createObject(JSContext *cx, JSObject *obj)
485 bool ok = true;
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
496 return ok;
499 inline bool
500 Probes::finalizeObject(JSObject *obj)
502 bool ok = true;
504 #ifdef INCLUDE_MOZILLA_DTRACE
505 if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED()) {
506 Class *clasp = obj->getClass();
508 /* the first arg is NULL - reserved for future use (filename?) */
509 JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
511 #endif
512 #ifdef MOZ_ETW
513 if (ProfilingActive && !ETWFinalizeObject(obj))
514 ok = false;
515 #endif
517 return ok;
520 inline bool
521 Probes::objectResizeActive()
523 #ifdef MOZ_ETW
524 if (ProfilingActive)
525 return true;
526 #endif
528 return false;
531 inline bool
532 Probes::resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize)
534 bool ok = true;
536 #ifdef MOZ_ETW
537 if (ProfilingActive && !ETWResizeObject(cx, obj, oldSize, newSize))
538 ok = false;
539 #endif
541 return ok;
544 inline bool
545 Probes::createString(JSContext *cx, JSString *string, size_t length)
547 bool ok = true;
549 #ifdef MOZ_ETW
550 if (ProfilingActive && !ETWCreateString(cx, string, length))
551 ok = false;
552 #endif
554 return ok;
557 inline bool
558 Probes::finalizeString(JSString *string)
560 bool ok = true;
562 #ifdef MOZ_ETW
563 if (ProfilingActive && !ETWFinalizeString(string))
564 ok = false;
565 #endif
567 return ok;
570 inline bool
571 Probes::compileScriptBegin(JSContext *cx, const char *filename, int lineno)
573 bool ok = true;
575 #ifdef MOZ_ETW
576 if (ProfilingActive && !ETWCompileScriptBegin(filename, lineno))
577 ok = false;
578 #endif
580 return ok;
583 inline bool
584 Probes::compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno)
586 bool ok = true;
588 #ifdef MOZ_ETW
589 if (ProfilingActive && !ETWCompileScriptEnd(filename, lineno))
590 ok = false;
591 #endif
593 return ok;
596 inline bool
597 Probes::calloutBegin(JSContext *cx, JSFunction *fun)
599 bool ok = true;
601 #ifdef MOZ_ETW
602 if (ProfilingActive && !ETWCalloutBegin(cx, fun))
603 ok = false;
604 #endif
606 return ok;
609 inline bool
610 Probes::calloutEnd(JSContext *cx, JSFunction *fun)
612 bool ok = true;
614 #ifdef MOZ_ETW
615 if (ProfilingActive && !ETWCalloutEnd(cx, fun))
616 ok = false;
617 #endif
619 return ok;
622 inline bool
623 Probes::acquireMemory(JSContext *cx, void *address, size_t nbytes)
625 bool ok = true;
627 #ifdef MOZ_ETW
628 if (ProfilingActive && !ETWAcquireMemory(cx, address, nbytes))
629 ok = false;
630 #endif
632 return ok;
635 inline bool
636 Probes::releaseMemory(JSContext *cx, void *address, size_t nbytes)
638 bool ok = true;
640 #ifdef MOZ_ETW
641 if (ProfilingActive && !ETWReleaseMemory(cx, address, nbytes))
642 ok = false;
643 #endif
645 return ok;
648 inline bool
649 Probes::GCStart()
651 bool ok = true;
653 #ifdef MOZ_ETW
654 if (ProfilingActive && !ETWGCStart())
655 ok = false;
656 #endif
658 return ok;
661 inline bool
662 Probes::GCEnd()
664 bool ok = true;
666 #ifdef MOZ_ETW
667 if (ProfilingActive && !ETWGCEnd())
668 ok = false;
669 #endif
671 return ok;
674 inline bool
675 Probes::GCStartMarkPhase()
677 bool ok = true;
679 #ifdef MOZ_ETW
680 if (ProfilingActive && !ETWGCStartMarkPhase())
681 ok = false;
682 #endif
684 return ok;
687 inline bool
688 Probes::GCEndMarkPhase()
690 bool ok = true;
692 #ifdef MOZ_ETW
693 if (ProfilingActive && !ETWGCEndMarkPhase())
694 ok = false;
695 #endif
697 return ok;
700 inline bool
701 Probes::GCStartSweepPhase()
703 bool ok = true;
705 #ifdef MOZ_ETW
706 if (ProfilingActive && !ETWGCStartSweepPhase())
707 ok = false;
708 #endif
710 return ok;
713 inline bool
714 Probes::GCEndSweepPhase()
716 bool ok = true;
718 #ifdef MOZ_ETW
719 if (ProfilingActive && !ETWGCEndSweepPhase())
720 ok = false;
721 #endif
723 return ok;
726 inline bool
727 Probes::CustomMark(JSString *string)
729 bool ok = true;
731 #ifdef MOZ_ETW
732 if (ProfilingActive && !ETWCustomMark(string))
733 ok = false;
734 #endif
736 return ok;
739 inline bool
740 Probes::CustomMark(const char *string)
742 bool ok = true;
744 #ifdef MOZ_ETW
745 if (ProfilingActive && !ETWCustomMark(string))
746 ok = false;
747 #endif
749 return ok;
752 inline bool
753 Probes::CustomMark(int marker)
755 bool ok = true;
757 #ifdef MOZ_ETW
758 if (ProfilingActive && !ETWCustomMark(marker))
759 ok = false;
760 #endif
762 return ok;
765 inline bool
766 Probes::startExecution(JSContext *cx, JSScript *script)
768 bool ok = true;
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
780 return ok;
783 inline bool
784 Probes::stopExecution(JSContext *cx, JSScript *script)
786 bool ok = true;
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
798 return ok;
801 struct AutoFunctionCallProbe {
802 JSContext * const cx;
803 JSFunction *fun;
804 JSScript *script;
805 JS_DECL_USE_GUARD_OBJECT_NOTIFIER
807 AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, JSScript *script
808 JS_GUARD_OBJECT_NOTIFIER_PARAM)
809 : cx(cx), fun(fun), script(script)
811 JS_GUARD_OBJECT_NOTIFIER_INIT;
812 Probes::enterJSFun(cx, fun, script);
815 ~AutoFunctionCallProbe() {
816 Probes::exitJSFun(cx, fun, script);
820 } /* namespace js */
823 * Internal functions for controlling various profilers. The profiler-specific
824 * implementations of these are mostly in jsdbgapi.cpp.
827 #endif /* _JSPROBES_H */