Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jsprobes.cpp
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  * Copyright (C) 2007  Sun Microsystems, Inc. All Rights Reserved.
18  *
19  * Contributor(s):
20  *      Brendan Eich <brendan@mozilla.org>
21  *
22  * Alternatively, the contents of this file may be used under the terms of
23  * either of the GNU General Public License Version 2 or later (the "GPL"),
24  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25  * in which case the provisions of the GPL or the LGPL are applicable instead
26  * of those above. If you wish to allow use of your version of this file only
27  * under the terms of either the GPL or the LGPL, and not to allow others to
28  * use your version of this file under the terms of the MPL, indicate your
29  * decision by deleting the provisions above and replace them with the notice
30  * and other provisions required by the GPL or the LGPL. If you do not delete
31  * the provisions above, a recipient may use your version of this file under
32  * the terms of any one of the MPL, the GPL or the LGPL.
33  *
34  * ***** END LICENSE BLOCK ***** */
35
36 #include "jsapi.h"
37 #include "jsutil.h"
38 #include "jsatom.h"
39 #include "jscntxt.h"
40 #include "jsdbgapi.h"
41 #include "jsfun.h"
42 #include "jsinterp.h"
43 #include "jsobj.h"
44 #include "jsscript.h"
45 #include "jsstr.h"
46
47 #ifdef __APPLE__
48 #include "sharkctl.h"
49 #endif
50
51 #include "jsprobes.h"
52 #include <sys/types.h>
53
54 #define TYPEOF(cx,v)    (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
55
56 using namespace js;
57
58 const char Probes::nullName[] = "(null)";
59
60 const char *
61 Probes::FunctionClassname(const JSFunction *fun)
62 {
63     return (fun && !FUN_INTERPRETED(fun) && !(fun->flags & JSFUN_TRCINFO) && FUN_CLASP(fun))
64            ? (char *)FUN_CLASP(fun)->name
65            : nullName;
66 }
67
68 const char *
69 Probes::ScriptFilename(JSScript *script)
70 {
71     return (script && script->filename) ? (char *)script->filename : nullName;
72 }
73
74 int
75 Probes::FunctionLineNumber(JSContext *cx, const JSFunction *fun)
76 {
77     if (fun && FUN_INTERPRETED(fun))
78         return (int) JS_GetScriptBaseLineNumber(cx, FUN_SCRIPT(fun));
79
80     return 0;
81 }
82
83 /*
84  * This function is used to convert function arguments and return value (jsval)
85  * into the following based on each value's type tag:
86  *
87  *      jsval      returned
88  *      -------------------
89  *      STRING  -> void *
90  *      INT     -> int
91  *      DOUBLE  -> double *
92  *      BOOLEAN -> int
93  *      OBJECT  -> void *
94  *
95  * All are presented as void * for DTrace consumers to use, after shifting or
96  * masking out the JavaScript type bits. This allows D scripts to use ints and
97  * booleans directly and copyinstr() for string arguments, when types are known
98  * beforehand.
99  *
100  * This is used by the function-args and function-rval probes, which also
101  * provide raw (unmasked) jsvals should type info be useful from D scripts.
102  */
103 #if 0
104 static void *
105 jsprobes_jsvaltovoid(JSContext *cx, const js::Value &argval)
106 {
107     if (argval.isNull())
108         return (void *)JS_TYPE_STR(JSTYPE_NULL);
109
110     if (argval.isUndefined())
111         return (void *)JS_TYPE_STR(JSTYPE_VOID);
112
113     if (argval.isBoolean())
114         return (void *)argval.toBoolean();
115
116     if (argval.isNumber()) {
117         if (argval.isInt32())
118             return (void *)argval.toInt32();
119         // FIXME Now what?
120         //return (void *)argval.toDouble();
121     }
122
123     return argval.toGCThing();
124 }
125 #endif
126
127 const char *
128 Probes::FunctionName(JSContext *cx, const JSFunction *fun, JSAutoByteString *bytes)
129 {
130     if (!fun)
131         return nullName;
132
133     JSAtom *atom = fun->atom;
134     if (!atom) {
135         /*
136          * TODO: maybe do more work here to figure out the name of the property
137          * or variable that held the anonymous function that we're calling, if anyone
138          * cares; an easy workaround is to just give your anonymous functions names.
139          */
140         return nullName;
141     }
142
143     return bytes->encode(cx, ATOM_TO_STRING(atom)) ? bytes->ptr() : nullName;
144 }
145
146 #ifdef INCLUDE_MOZILLA_DTRACE
147 /*
148  * These functions call the DTrace macros for the JavaScript USDT probes.
149  * Originally this code was inlined in the JavaScript code; however since
150  * a number of operations are called, these have been placed into functions
151  * to reduce any negative compiler optimization effect that the addition of
152  * a number of usually unused lines of code would cause.
153  */
154 void
155 Probes::enterJSFunImpl(JSContext *cx, JSFunction *fun, JSScript *script)
156 {
157     JSAutoByteString funNameBytes;
158     JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(script), FunctionClassname(fun),
159                               FunctionName(cx, fun, &funNameBytes));
160 }
161
162 void
163 Probes::handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script)
164 {
165     JSAutoByteString funNameBytes;
166     JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(script), FunctionClassname(fun),
167                                FunctionName(cx, fun, &funNameBytes));
168 }
169
170 #endif
171
172 bool
173 Probes::startProfiling()
174 {
175 #ifdef MOZ_SHARK
176     if (Shark::Start())
177         return true;
178 #endif
179     return false;
180 }
181
182 void
183 Probes::stopProfiling()
184 {
185 #ifdef MOZ_SHARK
186     Shark::Stop();
187 #endif
188 }