• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef SamplingTool_h
30 #define SamplingTool_h
31 
32 #include <wtf/Assertions.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/Threading.h>
35 
36 #include "Nodes.h"
37 #include "Opcode.h"
38 
39 namespace JSC {
40 
41     class CodeBlock;
42     class ExecState;
43     class Interpreter;
44     class ScopeNode;
45     struct Instruction;
46 
47     struct ScopeSampleRecord {
ScopeSampleRecordScopeSampleRecord48         ScopeSampleRecord(ScopeNode* scope)
49             : m_scope(scope)
50             , m_codeBlock(0)
51             , m_sampleCount(0)
52             , m_opcodeSampleCount(0)
53             , m_samples(0)
54             , m_size(0)
55         {
56         }
57 
~ScopeSampleRecordScopeSampleRecord58         ~ScopeSampleRecord()
59         {
60             if (m_samples)
61                 free(m_samples);
62         }
63 
64         void sample(CodeBlock*, Instruction*);
65 
66         RefPtr<ScopeNode> m_scope;
67         CodeBlock* m_codeBlock;
68         int m_sampleCount;
69         int m_opcodeSampleCount;
70         int* m_samples;
71         unsigned m_size;
72     };
73 
74     typedef WTF::HashMap<ScopeNode*, ScopeSampleRecord*> ScopeSampleRecordMap;
75 
76     class SamplingTool {
77     public:
78         friend class CallRecord;
79         friend class HostCallRecord;
80 
81 #if ENABLE(OPCODE_SAMPLING)
82         class CallRecord : Noncopyable {
83         public:
CallRecord(SamplingTool * samplingTool)84             CallRecord(SamplingTool* samplingTool)
85                 : m_samplingTool(samplingTool)
86                 , m_savedSample(samplingTool->m_sample)
87                 , m_savedCodeBlock(samplingTool->m_codeBlock)
88             {
89             }
90 
~CallRecord()91             ~CallRecord()
92             {
93                 m_samplingTool->m_sample = m_savedSample;
94                 m_samplingTool->m_codeBlock = m_savedCodeBlock;
95             }
96 
97         private:
98             SamplingTool* m_samplingTool;
99             intptr_t m_savedSample;
100             CodeBlock* m_savedCodeBlock;
101         };
102 
103         class HostCallRecord : public CallRecord {
104         public:
HostCallRecord(SamplingTool * samplingTool)105             HostCallRecord(SamplingTool* samplingTool)
106                 : CallRecord(samplingTool)
107             {
108                 samplingTool->m_sample |= 0x1;
109             }
110         };
111 #else
112         class CallRecord : Noncopyable {
113         public:
CallRecord(SamplingTool *)114             CallRecord(SamplingTool*)
115             {
116             }
117         };
118 
119         class HostCallRecord : public CallRecord {
120         public:
HostCallRecord(SamplingTool * samplingTool)121             HostCallRecord(SamplingTool* samplingTool)
122                 : CallRecord(samplingTool)
123             {
124             }
125         };
126 #endif
127 
SamplingTool(Interpreter * interpreter)128         SamplingTool(Interpreter* interpreter)
129             : m_interpreter(interpreter)
130             , m_running(false)
131             , m_codeBlock(0)
132             , m_sample(0)
133             , m_sampleCount(0)
134             , m_opcodeSampleCount(0)
135             , m_scopeSampleMap(new ScopeSampleRecordMap())
136         {
137             memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples));
138             memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions));
139         }
140 
~SamplingTool()141         ~SamplingTool()
142         {
143             deleteAllValues(*m_scopeSampleMap);
144         }
145 
146         void start(unsigned hertz=10000);
147         void stop();
148         void dump(ExecState*);
149 
150         void notifyOfScope(ScopeNode* scope);
151 
sample(CodeBlock * codeBlock,Instruction * vPC)152         void sample(CodeBlock* codeBlock, Instruction* vPC)
153         {
154             ASSERT(!(reinterpret_cast<intptr_t>(vPC) & 0x3));
155             m_codeBlock = codeBlock;
156             m_sample = reinterpret_cast<intptr_t>(vPC);
157         }
158 
codeBlockSlot()159         CodeBlock** codeBlockSlot() { return &m_codeBlock; }
sampleSlot()160         intptr_t* sampleSlot() { return &m_sample; }
161 
162         void* encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false)
163         {
164             ASSERT(!(reinterpret_cast<intptr_t>(vPC) & 0x3));
165             return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(vPC) | (static_cast<intptr_t>(inCTIFunction) << 1) | static_cast<intptr_t>(inHostFunction));
166         }
167 
168     private:
169         class Sample {
170         public:
Sample(volatile intptr_t sample,CodeBlock * volatile codeBlock)171             Sample(volatile intptr_t sample, CodeBlock* volatile codeBlock)
172                 : m_sample(sample)
173                 , m_codeBlock(codeBlock)
174             {
175             }
176 
isNull()177             bool isNull() { return !m_sample || !m_codeBlock; }
codeBlock()178             CodeBlock* codeBlock() { return m_codeBlock; }
vPC()179             Instruction* vPC() { return reinterpret_cast<Instruction*>(m_sample & ~0x3); }
inHostFunction()180             bool inHostFunction() { return m_sample & 0x1; }
inCTIFunction()181             bool inCTIFunction() { return m_sample & 0x2; }
182 
183         private:
184             intptr_t m_sample;
185             CodeBlock* m_codeBlock;
186         };
187 
188         static void* threadStartFunc(void*);
189         void run();
190 
191         Interpreter* m_interpreter;
192 
193         // Sampling thread state.
194         bool m_running;
195         unsigned m_hertz;
196         ThreadIdentifier m_samplingThread;
197 
198         // State tracked by the main thread, used by the sampling thread.
199         CodeBlock* m_codeBlock;
200         intptr_t m_sample;
201 
202         // Gathered sample data.
203         long long m_sampleCount;
204         long long m_opcodeSampleCount;
205         unsigned m_opcodeSamples[numOpcodeIDs];
206         unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs];
207 
208         Mutex m_scopeSampleMapMutex;
209         OwnPtr<ScopeSampleRecordMap> m_scopeSampleMap;
210     };
211 
212 } // namespace JSC
213 
214 #endif // SamplingTool_h
215