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 |
#include "jsdtracef.h" |
48 |
#include <sys/types.h> |
49 |
|
50 |
#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v)) |
51 |
|
52 |
static char dempty[] = "<null>"; |
53 |
|
54 |
char * |
55 |
jsdtrace_funcclass_name(JSFunction *fun) |
56 |
{ |
57 |
return (!FUN_INTERPRETED(fun) && fun->u.n.clasp) |
58 |
? (char *)fun->u.n.clasp->name |
59 |
: dempty; |
60 |
} |
61 |
|
62 |
char * |
63 |
jsdtrace_filename(JSStackFrame *fp) |
64 |
{ |
65 |
while (fp && fp->script == NULL) |
66 |
fp = fp->down; |
67 |
return (fp && fp->script && fp->script->filename) |
68 |
? (char *)fp->script->filename |
69 |
: dempty; |
70 |
} |
71 |
|
72 |
int |
73 |
jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp) |
74 |
{ |
75 |
while (fp && fp->script == NULL) |
76 |
fp = fp->down; |
77 |
return (fp && fp->regs) |
78 |
? (int) js_PCToLineNumber(cx, fp->script, fp->regs->pc) |
79 |
: -1; |
80 |
} |
81 |
|
82 |
/* |
83 |
* This function is used to convert function arguments and return value (jsval) |
84 |
* into the following based on each value's type tag: |
85 |
* |
86 |
* jsval returned |
87 |
* ------------------- |
88 |
* STRING -> char * |
89 |
* INT -> int |
90 |
* DOUBLE -> double * |
91 |
* BOOLEAN -> int |
92 |
* OBJECT -> void * |
93 |
* |
94 |
* All are presented as void * for DTrace consumers to use, after shifting or |
95 |
* masking out the JavaScript type bits. This allows D scripts to use ints and |
96 |
* booleans directly and copyinstr() for string arguments, when types are known |
97 |
* beforehand. |
98 |
* |
99 |
* This is used by the function-args and function-rval probes, which also |
100 |
* provide raw (unmasked) jsvals should type info be useful from D scripts. |
101 |
*/ |
102 |
void * |
103 |
jsdtrace_jsvaltovoid(JSContext *cx, jsval argval) |
104 |
{ |
105 |
JSType type = TYPEOF(cx, argval); |
106 |
|
107 |
switch (type) { |
108 |
case JSTYPE_NULL: |
109 |
case JSTYPE_VOID: |
110 |
return (void *)JS_TYPE_STR(type); |
111 |
|
112 |
case JSTYPE_BOOLEAN: |
113 |
return (void *)JSVAL_TO_BOOLEAN(argval); |
114 |
|
115 |
case JSTYPE_STRING: |
116 |
return (void *)js_GetStringBytes(cx, JSVAL_TO_STRING(argval)); |
117 |
|
118 |
case JSTYPE_NUMBER: |
119 |
if (JSVAL_IS_INT(argval)) |
120 |
return (void *)JSVAL_TO_INT(argval); |
121 |
return JSVAL_TO_DOUBLE(argval); |
122 |
|
123 |
default: |
124 |
return JSVAL_TO_GCTHING(argval); |
125 |
} |
126 |
/* NOTREACHED */ |
127 |
} |
128 |
|
129 |
char * |
130 |
jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun) |
131 |
{ |
132 |
JSAtom *atom; |
133 |
JSFrameRegs *regs; |
134 |
JSScript *script; |
135 |
jsbytecode *pc; |
136 |
char *name; |
137 |
|
138 |
atom = fun->atom; |
139 |
if (!atom) { |
140 |
if (fp->fun != fun || !fp->down) |
141 |
return dempty; |
142 |
|
143 |
regs = fp->down->regs; |
144 |
if (!regs) |
145 |
return dempty; |
146 |
|
147 |
/* |
148 |
* An anonymous function called from an active script or interpreted |
149 |
* function: try to fetch the variable or property name by which the |
150 |
* anonymous function was invoked. |
151 |
*/ |
152 |
pc = regs->pc; |
153 |
script = fp->down->script; |
154 |
switch ((JSOp) *pc) { |
155 |
case JSOP_CALL: |
156 |
case JSOP_EVAL: |
157 |
JS_ASSERT(fp->argv == regs->sp - (int)GET_ARGC(pc)); |
158 |
|
159 |
/* |
160 |
* FIXME bug 422864: update this code to use the pc stack from the |
161 |
* decompiler. |
162 |
*/ |
163 |
break; |
164 |
default: ; |
165 |
} |
166 |
|
167 |
switch ((JSOp) *pc) { |
168 |
case JSOP_CALLNAME: |
169 |
case JSOP_CALLPROP: |
170 |
case JSOP_NAME: |
171 |
case JSOP_SETNAME: |
172 |
case JSOP_GETPROP: |
173 |
case JSOP_SETPROP: |
174 |
GET_ATOM_FROM_BYTECODE(script, pc, 0, atom); |
175 |
break; |
176 |
|
177 |
case JSOP_CALLELEM: |
178 |
case JSOP_GETELEM: |
179 |
case JSOP_SETELEM: |
180 |
case JSOP_CALLGVAR: |
181 |
case JSOP_GETGVAR: |
182 |
case JSOP_SETGVAR: |
183 |
case JSOP_CALLARG: |
184 |
case JSOP_CALLLOCAL: |
185 |
/* FIXME: try to recover a name from these ops. */ |
186 |
/* FALL THROUGH */ |
187 |
|
188 |
default: |
189 |
return dempty; |
190 |
} |
191 |
} |
192 |
|
193 |
name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom)); |
194 |
return name ? name : dempty; |
195 |
} |
196 |
|
197 |
/* |
198 |
* These functions call the DTrace macros for the JavaScript USDT probes. |
199 |
* Originally this code was inlined in the JavaScript code; however since |
200 |
* a number of operations are called, these have been placed into functions |
201 |
* to reduce any negative compiler optimization effect that the addition of |
202 |
* a number of usually unused lines of code would cause. |
203 |
*/ |
204 |
void |
205 |
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun) |
206 |
{ |
207 |
JAVASCRIPT_FUNCTION_ENTRY( |
208 |
jsdtrace_filename(fp), |
209 |
jsdtrace_funcclass_name(fun), |
210 |
jsdtrace_function_name(cx, fp, fun) |
211 |
); |
212 |
} |
213 |
|
214 |
void |
215 |
jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp, |
216 |
JSFunction *fun) |
217 |
{ |
218 |
JAVASCRIPT_FUNCTION_INFO( |
219 |
jsdtrace_filename(fp), |
220 |
jsdtrace_funcclass_name(fun), |
221 |
jsdtrace_function_name(cx, fp, fun), |
222 |
fp->script->lineno, |
223 |
jsdtrace_filename(dfp), |
224 |
jsdtrace_linenumber(cx, dfp) |
225 |
); |
226 |
} |
227 |
|
228 |
void |
229 |
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun) |
230 |
{ |
231 |
JAVASCRIPT_FUNCTION_ARGS( |
232 |
jsdtrace_filename(fp), |
233 |
jsdtrace_funcclass_name(fun), |
234 |
jsdtrace_function_name(cx, fp, fun), |
235 |
fp->argc, (void *)fp->argv, |
236 |
(fp->argc > 0) ? jsdtrace_jsvaltovoid(cx, fp->argv[0]) : 0, |
237 |
(fp->argc > 1) ? jsdtrace_jsvaltovoid(cx, fp->argv[1]) : 0, |
238 |
(fp->argc > 2) ? jsdtrace_jsvaltovoid(cx, fp->argv[2]) : 0, |
239 |
(fp->argc > 3) ? jsdtrace_jsvaltovoid(cx, fp->argv[3]) : 0, |
240 |
(fp->argc > 4) ? jsdtrace_jsvaltovoid(cx, fp->argv[4]) : 0 |
241 |
); |
242 |
} |
243 |
|
244 |
void |
245 |
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun) |
246 |
{ |
247 |
JAVASCRIPT_FUNCTION_RVAL( |
248 |
jsdtrace_filename(fp), |
249 |
jsdtrace_funcclass_name(fun), |
250 |
jsdtrace_function_name(cx, fp, fun), |
251 |
jsdtrace_linenumber(cx, fp), (void *)fp->rval, |
252 |
jsdtrace_jsvaltovoid(cx, fp->rval) |
253 |
); |
254 |
} |
255 |
|
256 |
void |
257 |
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun) |
258 |
{ |
259 |
JAVASCRIPT_FUNCTION_RETURN( |
260 |
jsdtrace_filename(fp), |
261 |
jsdtrace_funcclass_name(fun), |
262 |
jsdtrace_function_name(cx, fp, fun) |
263 |
); |
264 |
} |
265 |
|
266 |
void |
267 |
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp) |
268 |
{ |
269 |
JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name); |
270 |
} |
271 |
|
272 |
void |
273 |
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp) |
274 |
{ |
275 |
JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name); |
276 |
} |
277 |
|
278 |
void |
279 |
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj) |
280 |
{ |
281 |
JAVASCRIPT_OBJECT_CREATE( |
282 |
jsdtrace_filename(cx->fp), |
283 |
(char *)clasp->name, |
284 |
(uintptr_t)obj, |
285 |
jsdtrace_linenumber(cx, cx->fp) |
286 |
); |
287 |
} |
288 |
|
289 |
void |
290 |
jsdtrace_object_finalize(JSObject *obj) |
291 |
{ |
292 |
JSClass *clasp; |
293 |
|
294 |
clasp = LOCKED_OBJ_GET_CLASS(obj); |
295 |
|
296 |
/* the first arg is NULL - reserved for future use (filename?) */ |
297 |
JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj); |
298 |
} |
299 |
|
300 |
void |
301 |
jsdtrace_execute_start(JSScript *script) |
302 |
{ |
303 |
JAVASCRIPT_EXECUTE_START( |
304 |
script->filename ? (char *)script->filename : dempty, |
305 |
script->lineno |
306 |
); |
307 |
} |
308 |
|
309 |
void |
310 |
jsdtrace_execute_done(JSScript *script) |
311 |
{ |
312 |
JAVASCRIPT_EXECUTE_DONE( |
313 |
script->filename ? (char *)script->filename : dempty, |
314 |
script->lineno |
315 |
); |
316 |
} |