blob: 302b5f92962731995486d6451dca7d1298580761 [file] [log] [blame]
barraclough@apple.comf51cff32012-01-29 03:47:13 +00001/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "CodeProfiling.h"
28
29#include "CodeProfile.h"
eric@webkit.orgfa5d72e2012-03-21 23:18:20 +000030#include <wtf/MetaAllocator.h>
paroga@webkit.orgf839c952012-02-06 12:33:47 +000031
32#if HAVE(SIGNAL_H)
33#include <signal.h>
34#endif
barraclough@apple.comf51cff32012-01-29 03:47:13 +000035
achristensen@apple.com85f6ab52014-08-05 00:30:15 +000036#if OS(LINUX) || OS(DARWIN)
yuqiang.xian@intel.comaa9f8cc2012-02-17 07:10:12 +000037#include <sys/time.h>
38#endif
39
barraclough@apple.comf51cff32012-01-29 03:47:13 +000040namespace JSC {
41
42volatile CodeProfile* CodeProfiling::s_profileStack = 0;
43CodeProfiling::Mode CodeProfiling::s_mode = CodeProfiling::Disabled;
44WTF::MetaAllocatorTracker* CodeProfiling::s_tracker = 0;
45
fpizlo@apple.com6dab5392012-01-30 01:41:09 +000046#if COMPILER(CLANG)
47#pragma clang diagnostic push
48#pragma clang diagnostic ignored "-Wmissing-noreturn"
49#endif
50
mitz@apple.com37934feb2014-02-03 08:17:33 +000051#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
barraclough@apple.comf51cff32012-01-29 03:47:13 +000052// Helper function to start & stop the timer.
53// Presently we're using the wall-clock timer, since this seems to give the best results.
54static void setProfileTimer(unsigned usec)
55{
barraclough@apple.comf51cff32012-01-29 03:47:13 +000056 itimerval timer;
57 timer.it_value.tv_sec = 0;
58 timer.it_value.tv_usec = usec;
59 timer.it_interval.tv_sec = 0;
60 timer.it_interval.tv_usec = usec;
61 setitimer(ITIMER_REAL, &timer, 0);
barraclough@apple.comf51cff32012-01-29 03:47:13 +000062}
barraclough@apple.combd8628e2012-01-30 23:56:00 +000063#endif
barraclough@apple.comf51cff32012-01-29 03:47:13 +000064
fpizlo@apple.com6dab5392012-01-30 01:41:09 +000065#if COMPILER(CLANG)
66#pragma clang diagnostic pop
67#endif
68
mitz@apple.com37934feb2014-02-03 08:17:33 +000069#if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)
barraclough@apple.comf51cff32012-01-29 03:47:13 +000070static void profilingTimer(int, siginfo_t*, void* uap)
71{
72 mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
73 CodeProfiling::sample(reinterpret_cast<void*>(context->__ss.__rip),
74 reinterpret_cast<void**>(context->__ss.__rbp));
75}
yuqiang.xian@intel.comaa9f8cc2012-02-17 07:10:12 +000076#elif OS(LINUX) && CPU(X86)
77static void profilingTimer(int, siginfo_t*, void* uap)
78{
79 mcontext_t context = static_cast<ucontext_t*>(uap)->uc_mcontext;
80 CodeProfiling::sample(reinterpret_cast<void*>(context.gregs[REG_EIP]),
81 reinterpret_cast<void**>(context.gregs[REG_EBP]));
82}
barraclough@apple.comf51cff32012-01-29 03:47:13 +000083#endif
84
85// Callback triggered when the timer is fired.
86void CodeProfiling::sample(void* pc, void** framePointer)
87{
88 CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
89 if (profileStack)
90 profileStack->sample(pc, framePointer);
91}
92
93void CodeProfiling::notifyAllocator(WTF::MetaAllocator* allocator)
94{
95 // Check for JSC_CODE_PROFILING.
96 const char* codeProfilingMode = getenv("JSC_CODE_PROFILING");
97 if (!codeProfilingMode)
98 return;
99
100 // Check for a valid mode, currently "1", "2", or "3".
101 if (!codeProfilingMode[0] || codeProfilingMode[1])
102 return;
103 switch (*codeProfilingMode) {
104 case '1':
105 s_mode = Enabled;
106 break;
107 case '2':
108 s_mode = Verbose;
109 break;
110 case '3':
111 s_mode = VeryVerbose;
112 break;
113 default:
114 return;
115 }
116
117 ASSERT(enabled());
118 ASSERT(!s_tracker);
119 s_tracker = new WTF::MetaAllocatorTracker();
120 allocator->trackAllocations(s_tracker);
121}
122
123void* CodeProfiling::getOwnerUIDForPC(void* address)
124{
125 if (!s_tracker)
126 return 0;
127 WTF::MetaAllocatorHandle* handle = s_tracker->find(address);
128 if (!handle)
129 return 0;
130 return handle->ownerUID();
131}
132
133void CodeProfiling::begin(const SourceCode& source)
134{
135 // Push a new CodeProfile onto the stack for each script encountered.
136 CodeProfile* profileStack = const_cast<CodeProfile*>(s_profileStack);
137 bool alreadyProfiling = profileStack;
138 s_profileStack = profileStack = new CodeProfile(source, profileStack);
139
140 // Is the profiler already running - if so, the timer will already be set up.
141 if (alreadyProfiling)
142 return;
143
mitz@apple.com37934feb2014-02-03 08:17:33 +0000144#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
barraclough@apple.combd8628e2012-01-30 23:56:00 +0000145 // Regsiter a signal handler & itimer.
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000146 struct sigaction action;
yuqiang.xian@intel.comaa9f8cc2012-02-17 07:10:12 +0000147 action.sa_sigaction = reinterpret_cast<void (*)(int, siginfo_t *, void *)>(profilingTimer);
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000148 sigfillset(&action.sa_mask);
149 action.sa_flags = SA_SIGINFO;
150 sigaction(SIGALRM, &action, 0);
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000151 setProfileTimer(100);
barraclough@apple.combd8628e2012-01-30 23:56:00 +0000152#endif
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000153}
154
155void CodeProfiling::end()
156{
157 // Pop the current profiler off the stack.
158 CodeProfile* current = const_cast<CodeProfile*>(s_profileStack);
159 ASSERT(current);
160 s_profileStack = current->parent();
161
162 // Is this the outermost script being profiled? - if not, just return.
163 // We perform all output of profiles recursively from the outermost script,
164 // to minimize profiling overhead from skewing results.
165 if (s_profileStack)
166 return;
167
mitz@apple.com37934feb2014-02-03 08:17:33 +0000168#if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000169 // Stop profiling
170 setProfileTimer(0);
barraclough@apple.combd8628e2012-01-30 23:56:00 +0000171#endif
barraclough@apple.comf51cff32012-01-29 03:47:13 +0000172
173 current->report();
174 delete current;
175}
176
177}