summaryrefslogtreecommitdiffstats
path: root/js/public/experimental/PCCountProfiling.h
blob: 132d48bcae3f3dfe9cb41d93067c329838051c1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * Bytecode-level profiling support based on program counter offset within
 * functions and overall scripts.
 *
 * SpiderMonkey compiles functions and scripts into bytecode representation.
 * During execution, SpiderMonkey can keep a counter of how often each bytecode
 * (specifically, bytecodes that are the targets of jumps) is reached, to track
 * basic information about how many times any particular bytecode in a script
 * or function is executed.  These functions allow this counting to be started
 * and stopped, and the results of such counting to be examined.
 *
 * Accumulated counting data is tracked per "script" (where "script" is either
 * a JavaScript function from source text or a top-level script or module).
 * Accumulated PCCount data thus prevents the particular scripts that were
 * executed from being GC'd.  Once PCCount profiling has been stopped, you
 * should examine and then purge the accumulated data as soon as possible.
 *
 * Much of the data tracked here is pretty internal and may only have meaning if
 * you're familiar with bytecode and Ion details.  Hence why these APIs are
 * "experimental".
 */

#ifndef js_experimental_PCCountProfiling_h
#define js_experimental_PCCountProfiling_h

#include <stddef.h>  // size_t

#include "jstypes.h"  // JS_PUBLIC_API

struct JS_PUBLIC_API JSContext;
class JS_PUBLIC_API JSString;

namespace JS {

/**
 * Start PCCount-based profiling if it hasn't already been started.
 *
 * This discards previously-accumulated PCCount profiling data from a prior
 * PCCount profiling session.  It also discards all active JIT code (as such
 * code was compiled to *not* perform PCCount-based profiling), so a brief
 * performance hit to code execution can be expected after calling this.
 */
extern JS_PUBLIC_API void StartPCCountProfiling(JSContext* cx);

/**
 * Stop PCCount-based profiling if it has been started.
 *
 * Internally, this accumulates PCCount profiling results into an array of
 * (script, script count info) for future consumption.  If accumulation fails,
 * this array will just be empty.
 *
 * This also discard all active JIT code (as such code was compiled to perform
 * PCCount-based profiling), so a brief performance hit to code execution can be
 * expected after calling this.
 */
extern JS_PUBLIC_API void StopPCCountProfiling(JSContext* cx);

/**
 * Get a count of all scripts for which PCCount profiling data was accumulated,
 * after PCCount profiling has been stopped.
 *
 * As noted above, if an internal error occurred when profiling was stopped,
 * this function will return 0.
 */
extern JS_PUBLIC_API size_t GetPCCountScriptCount(JSContext* cx);

/**
 * Get a JSON string summarizing PCCount data for the given script, by index
 * within the internal array computed when PCCount profiling was stopped, of
 * length indicated by |JS::GetPCCountScriptCount|.
 *
 * The JSON string will encode an object of this form:
 *
 *   {
 *     "file": filename for the script,
 *     "line": line number within the script,
 *
 *     // OPTIONAL: only if this script is a function
 *     "name": function name
 *
 *     "totals":
 *       {
 *         "interp": sum of execution counts at all bytecode locations,
 *         "ion": sum of Ion activity counts,
 *       }
 *   }
 *
 * There is no inherent ordering to the (script, script count info) pairs within
 * the array.  Callers generally should expect to call this function in a loop
 * to get summaries for all executed scripts.
 */
extern JS_PUBLIC_API JSString* GetPCCountScriptSummary(JSContext* cx,
                                                       size_t script);

/**
 * Get a JSON string encoding detailed PCCount data for the given script, by
 * index within the internal array computed when PCCount profiling was stopped,
 * of length indicated by |JS::GetPCCountScriptCount|.
 *
 * The JSON string will encode an object of this form:
 *
 *   {
 *     "text": a string containg (possibly decompiled) source of the script,
 *     "line": line number within the script,
 *
 *     "opcodes":
 *       [
 *         // array elements of this form, corresponding to the script's
 *         // bytecodes
 *         {
 *           "id": offset of bytecode within script
 *           "line": line number for bytecode,
 *           "name": the name of the bytecode in question,
 *           "text": text of the expression being evaluated,
 *           "counts":
 *             {
 *               // OPTIONAL: only if the count is nonzero
 *               "interp": count of times executed,
 *             },
 *       ],
 *
 *     // OPTIONAL: only if the script is executed under Ion
 *     "ion":
 *       [
 *         // array of elements of this form, corresponding to Ion basic blocks
 *         {
 *           "id": Ion block id,
 *           "offset": Ion block offset,
 *           "successors":
 *             [
 *               // list of Ion block ids from which execution may proceed after
 *               // this one
 *             ],
 *           "hits": count of times this block was hit during execution,
 *           "code": a string containing the code in this Ion basic block,
 *         }
 *       ],
 *   }
 *
 * There is no inherent ordering to the (script, script count info) pairs within
 * the array.  Callers generally should expect to call this function in a loop
 * to get summaries for all executed scripts.
 */
extern JS_PUBLIC_API JSString* GetPCCountScriptContents(JSContext* cx,
                                                        size_t script);

/**
 * Purge all accumulated PCCount profiling data, particularly the internal array
 * that |JS::GetPCCountScript{Count,Summary,Contents}| exposes -- and all that
 * array's references to previously-executed scripts.
 */
extern JS_PUBLIC_API void PurgePCCounts(JSContext* cx);

}  // namespace JS

#endif  // js_experimental_PCCountProfiling_h