]>
git.saurik.com Git - apple/javascriptcore.git/blob - tools/CodeProfiling.cpp
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "CodeProfiling.h"
29 #include "CodeProfile.h"
30 #include <wtf/MetaAllocator.h>
36 #if OS(LINUX) || OS(DARWIN)
42 volatile CodeProfile
* CodeProfiling::s_profileStack
= 0;
43 CodeProfiling::Mode
CodeProfiling::s_mode
= CodeProfiling::Disabled
;
44 WTF::MetaAllocatorTracker
* CodeProfiling::s_tracker
= 0;
47 #pragma clang diagnostic push
48 #pragma clang diagnostic ignored "-Wmissing-noreturn"
51 #if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
52 // Helper function to start & stop the timer.
53 // Presently we're using the wall-clock timer, since this seems to give the best results.
54 static void setProfileTimer(unsigned usec
)
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);
66 #pragma clang diagnostic pop
69 #if OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)
70 static void profilingTimer(int, siginfo_t
*, void* uap
)
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
));
76 #elif OS(LINUX) && CPU(X86)
77 static void profilingTimer(int, siginfo_t
*, void* uap
)
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
]));
85 // Callback triggered when the timer is fired.
86 void CodeProfiling::sample(void* pc
, void** framePointer
)
88 CodeProfile
* profileStack
= const_cast<CodeProfile
*>(s_profileStack
);
90 profileStack
->sample(pc
, framePointer
);
93 void CodeProfiling::notifyAllocator(WTF::MetaAllocator
* allocator
)
95 // Check for JSC_CODE_PROFILING.
96 const char* codeProfilingMode
= getenv("JSC_CODE_PROFILING");
97 if (!codeProfilingMode
)
100 // Check for a valid mode, currently "1", "2", or "3".
101 if (!codeProfilingMode
[0] || codeProfilingMode
[1])
103 switch (*codeProfilingMode
) {
111 s_mode
= VeryVerbose
;
119 s_tracker
= new WTF::MetaAllocatorTracker();
120 allocator
->trackAllocations(s_tracker
);
123 void* CodeProfiling::getOwnerUIDForPC(void* address
)
127 WTF::MetaAllocatorHandle
* handle
= s_tracker
->find(address
);
130 return handle
->ownerUID();
133 void CodeProfiling::begin(const SourceCode
& source
)
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
);
140 // Is the profiler already running - if so, the timer will already be set up.
141 if (alreadyProfiling
)
144 #if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))
145 // Regsiter a signal handler & itimer.
146 struct sigaction action
;
147 action
.sa_sigaction
= reinterpret_cast<void (*)(int, siginfo_t
*, void *)>(profilingTimer
);
148 sigfillset(&action
.sa_mask
);
149 action
.sa_flags
= SA_SIGINFO
;
150 sigaction(SIGALRM
, &action
, 0);
151 setProfileTimer(100);
155 void CodeProfiling::end()
157 // Pop the current profiler off the stack.
158 CodeProfile
* current
= const_cast<CodeProfile
*>(s_profileStack
);
160 s_profileStack
= current
->parent();
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.
168 #if (OS(DARWIN) && !PLATFORM(EFL) && !PLATFORM(GTK) && CPU(X86_64)) || (OS(LINUX) && CPU(X86))