1 : #include "tests.h"
2 : #include "jsfun.h"
3 : #include "jscntxt.h"
4 :
5 : #include "jsobjinlines.h"
6 :
7 : #ifdef MOZ_TRACE_JSCALLS
8 :
9 : static int depth = 0;
10 : static int enters = 0;
11 : static int leaves = 0;
12 : static int interpreted = 0;
13 :
14 : static void
15 : funcTransition(const JSFunction *,
16 : const JSScript *,
17 : const JSContext *cx,
18 : int entering)
19 : {
20 : if (entering > 0) {
21 : ++depth;
22 : ++enters;
23 : ++interpreted;
24 : } else {
25 : --depth;
26 : ++leaves;
27 : }
28 : }
29 :
30 : static JSBool called2 = false;
31 :
32 : static void
33 : funcTransition2(const JSFunction *, const JSScript*, const JSContext*, int)
34 : {
35 : called2 = true;
36 : }
37 :
38 : static int overlays = 0;
39 : static JSFunctionCallback innerCallback = NULL;
40 : static void
41 : funcTransitionOverlay(const JSFunction *fun,
42 : const JSScript *script,
43 : const JSContext *cx,
44 : int entering)
45 : {
46 : (*innerCallback)(fun, script, cx, entering);
47 : overlays++;
48 : }
49 : #endif
50 :
51 4 : BEGIN_TEST(testFuncCallback_bug507012)
52 : {
53 : #ifdef MOZ_TRACE_JSCALLS
54 : // Call funcTransition() whenever a Javascript method is invoked
55 : JS_SetFunctionCallback(cx, funcTransition);
56 :
57 : EXEC("x = 0; function f (n) { if (n > 1) { f(n - 1); } }");
58 : interpreted = enters = leaves = depth = 0;
59 :
60 : // Check whether JS_Execute() tracking works
61 : EXEC("42");
62 : CHECK_EQUAL(enters, 1);
63 : CHECK_EQUAL(leaves, 1);
64 : CHECK_EQUAL(depth, 0);
65 : interpreted = enters = leaves = depth = 0;
66 :
67 : // Check whether the basic function tracking works
68 : EXEC("f(1)");
69 : CHECK_EQUAL(enters, 1+1);
70 : CHECK_EQUAL(leaves, 1+1);
71 : CHECK_EQUAL(depth, 0);
72 :
73 : // Can we switch to a different callback?
74 : enters = 777;
75 : JS_SetFunctionCallback(cx, funcTransition2);
76 : EXEC("f(1)");
77 : CHECK(called2);
78 : CHECK_EQUAL(enters, 777);
79 :
80 : // Check whether we can turn off function tracing
81 : JS_SetFunctionCallback(cx, NULL);
82 : EXEC("f(1)");
83 : CHECK_EQUAL(enters, 777);
84 : interpreted = enters = leaves = depth = 0;
85 :
86 : // Check nested invocations
87 : JS_SetFunctionCallback(cx, funcTransition);
88 : enters = leaves = depth = 0;
89 : EXEC("f(3)");
90 : CHECK_EQUAL(enters, 1+3);
91 : CHECK_EQUAL(leaves, 1+3);
92 : CHECK_EQUAL(depth, 0);
93 : interpreted = enters = leaves = depth = 0;
94 :
95 : // Check calls invoked while running on trace -- or now, perhaps on
96 : // IonMonkey's equivalent, if it ever starts to exist?
97 : EXEC("function g () { ++x; }");
98 : interpreted = enters = leaves = depth = 0;
99 : EXEC("for (i = 0; i < 5000; ++i) { g(); }");
100 : CHECK_EQUAL(enters, 1+5000);
101 : CHECK_EQUAL(leaves, 1+5000);
102 : CHECK_EQUAL(depth, 0);
103 :
104 : // Test nesting callbacks via JS_GetFunctionCallback()
105 : JS_SetFunctionCallback(cx, funcTransition);
106 : innerCallback = JS_GetFunctionCallback(cx);
107 : JS_SetFunctionCallback(cx, funcTransitionOverlay);
108 :
109 : EXEC("x = 0; function f (n) { if (n > 1) { f(n - 1); } }");
110 : interpreted = enters = leaves = depth = overlays = 0;
111 :
112 : EXEC("42.5");
113 : CHECK_EQUAL(enters, 1);
114 : CHECK_EQUAL(leaves, 1);
115 : CHECK_EQUAL(depth, 0);
116 : CHECK_EQUAL(overlays, enters + leaves);
117 : interpreted = enters = leaves = depth = overlays = 0;
118 : #endif
119 :
120 : // Uncomment this to validate whether you're hitting all runmodes (interp,
121 : // mjit, ...?) Unfortunately, that still doesn't cover all
122 : // transitions between the various runmodes, but it's a start.
123 : //JS_DumpAllProfiles(cx);
124 :
125 1 : return true;
126 : }
127 :
128 : // Make sure that the method jit is enabled.
129 : // We'll probably want to test in all modes.
130 : virtual
131 1 : JSContext *createContext()
132 : {
133 1 : JSContext *cx = JSAPITest::createContext();
134 1 : if (cx)
135 1 : JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_PCCOUNT);
136 1 : return cx;
137 : }
138 :
139 2 : END_TEST(testFuncCallback_bug507012)
|