/js/src/jsprobes.h
http://github.com/zpao/v8monkey · C Header · 825 lines · 499 code · 143 blank · 183 comment · 66 complexity · 03d69f7e2ec48b9b2ce5193899ccd0f8 MD5 · raw file
- /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=80:
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
- * June 12, 2009.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Corporation.
- *
- * Contributor(s):
- * Steve Fink <sfink@mozilla.org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- #ifndef _JSPROBES_H
- #define _JSPROBES_H
- #ifdef INCLUDE_MOZILLA_DTRACE
- #include "javascript-trace.h"
- #endif
- #include "jspubtd.h"
- #include "jsprvtd.h"
- #include "jsscript.h"
- #include "jsobj.h"
- #ifdef JS_METHODJIT
- #include "methodjit/MethodJIT.h"
- #endif
- namespace js {
- namespace mjit {
- struct NativeAddressInfo;
- struct JSActiveFrame;
- }
- namespace Probes {
- /*
- * Static probes
- *
- * The probe points defined in this file are scattered around the SpiderMonkey
- * source tree. The presence of Probes::someEvent() means that someEvent is
- * about to happen or has happened. To the extent possible, probes should be
- * inserted in all paths associated with a given event, regardless of the
- * active runmode (interpreter/traceJIT/methodJIT/ionJIT).
- *
- * When a probe fires, it is handled by any probe handling backends that have
- * been compiled in. By default, most probes do nothing or at least do nothing
- * expensive, so the presence of the probe should have negligible effect on
- * running time. (Probes in slow paths may do something by default, as long as
- * there is no noticeable slowdown.)
- *
- * For some probes, the mere existence of the probe is too expensive even if it
- * does nothing when called. For example, just having consistent information
- * available for a function call entry/exit probe causes the JITs to
- * de-optimize function calls. In those cases, the JITs may query at compile
- * time whether a probe is desired, and omit the probe invocation if not. If a
- * probe is runtime-disabled at compilation time, it is not guaranteed to fire
- * within a compiled function if it is later enabled.
- *
- * Not all backends handle all of the probes listed here.
- */
- /*
- * Internal use only: remember whether "profiling", whatever that means, is
- * currently active. Used for state management.
- */
- extern bool ProfilingActive;
- extern const char nullName[];
- extern const char anonymousName[];
- /* Called when first runtime is created for this process */
- JSBool startEngine();
- /* JSRuntime created, with currently valid fields */
- bool createRuntime(JSRuntime *rt);
- /* JSRuntime about to be destroyed */
- bool destroyRuntime(JSRuntime *rt);
- /* Total JS engine shutdown */
- bool shutdown();
- /*
- * Test whether we are tracking JS function call enter/exit. The JITs use this
- * to decide whether they can optimize in a way that would prevent probes from
- * firing.
- */
- bool callTrackingActive(JSContext *);
- /*
- * Test whether anything is looking for JIT native code registration events.
- * This information will not be collected otherwise.
- */
- bool wantNativeAddressInfo(JSContext *);
- /* Entering a JS function */
- bool enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
- /* About to leave a JS function */
- bool exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
- /* Executing a script */
- bool startExecution(JSContext *cx, JSScript *script);
- /* Script has completed execution */
- bool stopExecution(JSContext *cx, JSScript *script);
- /* Heap has been resized */
- bool resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
- /*
- * Object has been created. |obj| must exist (its class and size are read)
- */
- bool createObject(JSContext *cx, JSObject *obj);
- /* Resize events are being tracked. */
- bool objectResizeActive();
- /* Object has been resized */
- bool resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
- /*
- * Object is about to be finalized. |obj| must still exist (its class is
- * read)
- */
- bool finalizeObject(JSObject *obj);
- /*
- * String has been created.
- *
- * |string|'s content is not (yet) valid. |length| is the length of the string
- * and does not imply anything about the amount of storage consumed to store
- * the string. (It may be a short string, an external string, or a rope, and
- * the encoding is not taken into consideration.)
- */
- bool createString(JSContext *cx, JSString *string, size_t length);
- /*
- * String is about to be finalized
- *
- * |string| must still have a valid length.
- */
- bool finalizeString(JSString *string);
- /* Script is about to be compiled */
- bool compileScriptBegin(JSContext *cx, const char *filename, int lineno);
- /* Script has just finished compilation */
- bool compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno);
- /* About to make a call from JS into native code */
- bool calloutBegin(JSContext *cx, JSFunction *fun);
- /* Native code called by JS has terminated */
- bool calloutEnd(JSContext *cx, JSFunction *fun);
- /* Unimplemented */
- bool acquireMemory(JSContext *cx, void *address, size_t nbytes);
- bool releaseMemory(JSContext *cx, void *address, size_t nbytes);
- /*
- * Garbage collection probes
- *
- * GC timing is tricky and at the time of this writing is changing frequently.
- * GCStart/GCEnd are intended to bracket the entire garbage collection (either
- * global or single-compartment), but a separate thread may continue doing work
- * after GCEnd.
- *
- * Multiple compartments' GC will be interleaved during a global collection
- * (eg, compartment 1 starts, compartment 2 starts, compartment 1 ends, ...)
- */
- bool GCStart();
- bool GCEnd();
- bool GCStartMarkPhase();
- bool GCEndMarkPhase();
- bool GCStartSweepPhase();
- bool GCEndSweepPhase();
- /*
- * Various APIs for inserting custom probe points. These might be used to mark
- * when something starts and stops, or for various other purposes the user has
- * in mind. These are useful to export to JS so that JS code can mark
- * application-meaningful events and phases of execution.
- *
- * Not all backends support these.
- */
- bool CustomMark(JSString *string);
- bool CustomMark(const char *string);
- bool CustomMark(int marker);
- /* JIT code observation */
- enum JITReportGranularity {
- JITREPORT_GRANULARITY_NONE = 0,
- JITREPORT_GRANULARITY_FUNCTION = 1,
- JITREPORT_GRANULARITY_LINE = 2,
- JITREPORT_GRANULARITY_OP = 3
- };
- /*
- * Observer class for JIT code allocation/deallocation. Currently, this only
- * handles the method JIT, and does not get notifications when JIT code is
- * changed (patched) with no new allocation.
- */
- class JITWatcher {
- public:
- struct NativeRegion {
- mjit::JSActiveFrame *frame;
- JSScript *script;
- size_t inlinedOffset;
- jsbytecode *pc;
- jsbytecode *endpc;
- uintptr_t mainOffset;
- uintptr_t stubOffset;
- bool enter;
- };
- typedef Vector<NativeRegion, 0, RuntimeAllocPolicy> RegionVector;
- virtual JITReportGranularity granularityRequested() = 0;
- #ifdef JS_METHODJIT
- static bool CollectNativeRegions(RegionVector ®ions,
- JSRuntime *rt,
- mjit::JITChunk *jit,
- mjit::JSActiveFrame *outerFrame,
- mjit::JSActiveFrame **inlineFrames);
- virtual void registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
- mjit::JSActiveFrame *outerFrame,
- mjit::JSActiveFrame **inlineFrames,
- void *mainCodeAddress, size_t mainCodeSize,
- void *stubCodeAddress, size_t stubCodeSize) = 0;
- virtual void discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script,
- void* address) = 0;
- virtual void registerICCode(JSContext *cx,
- js::mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
- void *start, size_t size) = 0;
- #endif
- virtual void discardExecutableRegion(void *start, size_t size) = 0;
- };
- /*
- * Register a JITWatcher subclass to be informed of JIT code
- * allocation/deallocation.
- */
- bool
- addJITWatcher(JITWatcher *watcher);
- /*
- * Remove (and destroy) a registered JITWatcher. rt may be NULL. Returns false
- * if the watcher is not found.
- */
- bool
- removeJITWatcher(JSRuntime *rt, JITWatcher *watcher);
- /*
- * Remove (and destroy) all registered JITWatchers. rt may be NULL.
- */
- void
- removeAllJITWatchers(JSRuntime *rt);
- /*
- * Finest granularity of JIT information desired by all watchers.
- */
- JITReportGranularity
- JITGranularityRequested();
- #ifdef JS_METHODJIT
- /*
- * New method JIT code has been created
- */
- void
- registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
- mjit::JSActiveFrame *outerFrame,
- mjit::JSActiveFrame **inlineFrames,
- void *mainCodeAddress, size_t mainCodeSize,
- void *stubCodeAddress, size_t stubCodeSize);
- /*
- * Method JIT code is about to be discarded
- */
- void
- discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address);
- /*
- * IC code has been allocated within the given JITScript
- */
- void
- registerICCode(JSContext *cx,
- mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
- void *start, size_t size);
- #endif /* JS_METHODJIT */
- /*
- * A whole region of code has been deallocated, containing any number of ICs.
- * (ICs are unregistered in a batch, so individual ICs are not registered.)
- */
- void
- discardExecutableRegion(void *start, size_t size);
- /*
- * Internal: DTrace-specific functions to be called during Probes::enterJSFun
- * and Probes::exitJSFun. These will not be inlined, but the argument
- * marshalling required for these probe points is expensive enough that it
- * shouldn't really matter.
- */
- void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
- void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
- /*
- * Internal: ETW-specific probe functions
- */
- #ifdef MOZ_ETW
- // ETW Handlers
- bool ETWCreateRuntime(JSRuntime *rt);
- bool ETWDestroyRuntime(JSRuntime *rt);
- bool ETWShutdown();
- bool ETWCallTrackingActive(JSContext *cx);
- bool ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
- bool ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
- bool ETWCreateObject(JSContext *cx, JSObject *obj);
- bool ETWFinalizeObject(JSObject *obj);
- bool ETWResizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
- bool ETWCreateString(JSContext *cx, JSString *string, size_t length);
- bool ETWFinalizeString(JSString *string);
- bool ETWCompileScriptBegin(const char *filename, int lineno);
- bool ETWCompileScriptEnd(const char *filename, int lineno);
- bool ETWCalloutBegin(JSContext *cx, JSFunction *fun);
- bool ETWCalloutEnd(JSContext *cx, JSFunction *fun);
- bool ETWAcquireMemory(JSContext *cx, void *address, size_t nbytes);
- bool ETWReleaseMemory(JSContext *cx, void *address, size_t nbytes);
- bool ETWGCStart();
- bool ETWGCEnd();
- bool ETWGCStartMarkPhase();
- bool ETWGCEndMarkPhase();
- bool ETWGCStartSweepPhase();
- bool ETWGCEndSweepPhase();
- bool ETWCustomMark(JSString *string);
- bool ETWCustomMark(const char *string);
- bool ETWCustomMark(int marker);
- bool ETWStartExecution(JSContext *cx, JSScript *script);
- bool ETWStopExecution(JSContext *cx, JSScript *script);
- bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
- #endif
- } /* namespace Probes */
- /*
- * Many probe handlers are implemented inline for minimal performance impact,
- * especially important when no backends are enabled.
- */
- inline bool
- Probes::callTrackingActive(JSContext *cx)
- {
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
- return true;
- #endif
- #ifdef MOZ_TRACE_JSCALLS
- if (cx->functionCallback)
- return true;
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && ETWCallTrackingActive(cx))
- return true;
- #endif
- return false;
- }
- inline bool
- Probes::wantNativeAddressInfo(JSContext *cx)
- {
- return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
- JITGranularityRequested() >= JITREPORT_GRANULARITY_FUNCTION);
- }
- inline bool
- Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
- DTraceEnterJSFun(cx, fun, script);
- #endif
- #ifdef MOZ_TRACE_JSCALLS
- cx->doFunctionCallback(fun, script, counter);
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWEnterJSFun(cx, fun, script, counter))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::exitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
- DTraceExitJSFun(cx, fun, script);
- #endif
- #ifdef MOZ_TRACE_JSCALLS
- if (counter > 0)
- counter = -counter;
- cx->doFunctionCallback(fun, script, counter);
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWExitJSFun(cx, fun, script, counter))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWResizeHeap(compartment, oldSize, newSize))
- ok = false;
- #endif
- return ok;
- }
- #ifdef INCLUDE_MOZILLA_DTRACE
- static const char *ObjectClassname(JSObject *obj) {
- if (!obj)
- return "(null object)";
- Class *clasp = obj->getClass();
- if (!clasp)
- return "(null)";
- const char *class_name = clasp->name;
- if (!class_name)
- return "(null class name)";
- return class_name;
- }
- #endif
- inline bool
- Probes::createObject(JSContext *cx, JSObject *obj)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
- JAVASCRIPT_OBJECT_CREATE(ObjectClassname(obj), (uintptr_t)obj);
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCreateObject(cx, obj))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::finalizeObject(JSObject *obj)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED()) {
- Class *clasp = obj->getClass();
- /* the first arg is NULL - reserved for future use (filename?) */
- JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
- }
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWFinalizeObject(obj))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::objectResizeActive()
- {
- #ifdef MOZ_ETW
- if (ProfilingActive)
- return true;
- #endif
- return false;
- }
- inline bool
- Probes::resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWResizeObject(cx, obj, oldSize, newSize))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::createString(JSContext *cx, JSString *string, size_t length)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCreateString(cx, string, length))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::finalizeString(JSString *string)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWFinalizeString(string))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::compileScriptBegin(JSContext *cx, const char *filename, int lineno)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCompileScriptBegin(filename, lineno))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::compileScriptEnd(JSContext *cx, JSScript *script, const char *filename, int lineno)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCompileScriptEnd(filename, lineno))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::calloutBegin(JSContext *cx, JSFunction *fun)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCalloutBegin(cx, fun))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::calloutEnd(JSContext *cx, JSFunction *fun)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCalloutEnd(cx, fun))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::acquireMemory(JSContext *cx, void *address, size_t nbytes)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWAcquireMemory(cx, address, nbytes))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::releaseMemory(JSContext *cx, void *address, size_t nbytes)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWReleaseMemory(cx, address, nbytes))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCStart()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCStart())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCEnd()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCEnd())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCStartMarkPhase()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCStartMarkPhase())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCEndMarkPhase()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCEndMarkPhase())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCStartSweepPhase()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCStartSweepPhase())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::GCEndSweepPhase()
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWGCEndSweepPhase())
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::CustomMark(JSString *string)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCustomMark(string))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::CustomMark(const char *string)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCustomMark(string))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::CustomMark(int marker)
- {
- bool ok = true;
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWCustomMark(marker))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::startExecution(JSContext *cx, JSScript *script)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_EXECUTE_START_ENABLED())
- JAVASCRIPT_EXECUTE_START((script->filename ? (char *)script->filename : nullName),
- script->lineno);
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWStartExecution(cx, script))
- ok = false;
- #endif
- return ok;
- }
- inline bool
- Probes::stopExecution(JSContext *cx, JSScript *script)
- {
- bool ok = true;
- #ifdef INCLUDE_MOZILLA_DTRACE
- if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
- JAVASCRIPT_EXECUTE_DONE((script->filename ? (char *)script->filename : nullName),
- script->lineno);
- #endif
- #ifdef MOZ_ETW
- if (ProfilingActive && !ETWStopExecution(cx, script))
- ok = false;
- #endif
- return ok;
- }
- struct AutoFunctionCallProbe {
- JSContext * const cx;
- JSFunction *fun;
- JSScript *script;
- JS_DECL_USE_GUARD_OBJECT_NOTIFIER
- AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, JSScript *script
- JS_GUARD_OBJECT_NOTIFIER_PARAM)
- : cx(cx), fun(fun), script(script)
- {
- JS_GUARD_OBJECT_NOTIFIER_INIT;
- Probes::enterJSFun(cx, fun, script);
- }
- ~AutoFunctionCallProbe() {
- Probes::exitJSFun(cx, fun, script);
- }
- };
- } /* namespace js */
- /*
- * Internal functions for controlling various profilers. The profiler-specific
- * implementations of these are mostly in jsdbgapi.cpp.
- */
- #endif /* _JSPROBES_H */