OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/libsampler/v8-sampler.h" | 5 #include "src/libsampler/v8-sampler.h" |
6 | 6 |
7 #if V8_OS_POSIX && !V8_OS_CYGWIN | 7 #if V8_OS_POSIX && !V8_OS_CYGWIN |
8 | 8 |
9 #define USE_SIGNALS | 9 #define USE_SIGNALS |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 | 40 |
41 #include "src/base/win32-headers.h" | 41 #include "src/base/win32-headers.h" |
42 | 42 |
43 #endif | 43 #endif |
44 | 44 |
45 #include <algorithm> | 45 #include <algorithm> |
46 #include <vector> | 46 #include <vector> |
47 #include <map> | 47 #include <map> |
48 | 48 |
49 #include "src/base/atomic-utils.h" | 49 #include "src/base/atomic-utils.h" |
| 50 #include "src/base/hashmap.h" |
50 #include "src/base/platform/platform.h" | 51 #include "src/base/platform/platform.h" |
51 #include "src/libsampler/hashmap.h" | |
52 | |
53 | 52 |
54 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) | 53 #if V8_OS_ANDROID && !defined(__BIONIC_HAVE_UCONTEXT_T) |
55 | 54 |
56 // Not all versions of Android's C library provide ucontext_t. | 55 // Not all versions of Android's C library provide ucontext_t. |
57 // Detect this and provide custom but compatible definitions. Note that these | 56 // Detect this and provide custom but compatible definitions. Note that these |
58 // follow the GLibc naming convention to access register values from | 57 // follow the GLibc naming convention to access register values from |
59 // mcontext_t. | 58 // mcontext_t. |
60 // | 59 // |
61 // See http://code.google.com/p/android/issues/detail?id=34784 | 60 // See http://code.google.com/p/android/issues/detail?id=34784 |
62 | 61 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 public: | 211 public: |
213 PlatformData() : vm_tid_(pthread_self()) {} | 212 PlatformData() : vm_tid_(pthread_self()) {} |
214 pthread_t vm_tid() const { return vm_tid_; } | 213 pthread_t vm_tid() const { return vm_tid_; } |
215 | 214 |
216 private: | 215 private: |
217 pthread_t vm_tid_; | 216 pthread_t vm_tid_; |
218 }; | 217 }; |
219 | 218 |
220 class SamplerManager { | 219 class SamplerManager { |
221 public: | 220 public: |
222 SamplerManager() : sampler_map_(HashMap::PointersMatch) {} | 221 SamplerManager() : sampler_map_(base::HashMap::PointersMatch) {} |
223 | 222 |
224 void AddSampler(Sampler* sampler) { | 223 void AddSampler(Sampler* sampler) { |
225 AtomicGuard atomic_guard(&samplers_access_counter_); | 224 AtomicGuard atomic_guard(&samplers_access_counter_); |
226 DCHECK(sampler->IsActive() || !sampler->IsRegistered()); | 225 DCHECK(sampler->IsActive() || !sampler->IsRegistered()); |
227 // Add sampler into map if needed. | 226 // Add sampler into map if needed. |
228 pthread_t thread_id = sampler->platform_data()->vm_tid(); | 227 pthread_t thread_id = sampler->platform_data()->vm_tid(); |
229 HashMap::Entry* entry = sampler_map_.LookupOrInsert(ThreadKey(thread_id), | 228 base::HashMap::Entry* entry = |
230 ThreadHash(thread_id)); | 229 sampler_map_.LookupOrInsert(ThreadKey(thread_id), |
| 230 ThreadHash(thread_id)); |
231 DCHECK(entry != nullptr); | 231 DCHECK(entry != nullptr); |
232 if (entry->value == nullptr) { | 232 if (entry->value == nullptr) { |
233 SamplerList* samplers = new SamplerList(); | 233 SamplerList* samplers = new SamplerList(); |
234 samplers->push_back(sampler); | 234 samplers->push_back(sampler); |
235 entry->value = samplers; | 235 entry->value = samplers; |
236 } else { | 236 } else { |
237 SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value); | 237 SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value); |
238 bool exists = false; | 238 bool exists = false; |
239 for (SamplerListIterator iter = samplers->begin(); | 239 for (SamplerListIterator iter = samplers->begin(); |
240 iter != samplers->end(); ++iter) { | 240 iter != samplers->end(); ++iter) { |
241 if (*iter == sampler) { | 241 if (*iter == sampler) { |
242 exists = true; | 242 exists = true; |
243 break; | 243 break; |
244 } | 244 } |
245 } | 245 } |
246 if (!exists) { | 246 if (!exists) { |
247 samplers->push_back(sampler); | 247 samplers->push_back(sampler); |
248 } | 248 } |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 void RemoveSampler(Sampler* sampler) { | 252 void RemoveSampler(Sampler* sampler) { |
253 AtomicGuard atomic_guard(&samplers_access_counter_); | 253 AtomicGuard atomic_guard(&samplers_access_counter_); |
254 DCHECK(sampler->IsActive() || sampler->IsRegistered()); | 254 DCHECK(sampler->IsActive() || sampler->IsRegistered()); |
255 // Remove sampler from map. | 255 // Remove sampler from map. |
256 pthread_t thread_id = sampler->platform_data()->vm_tid(); | 256 pthread_t thread_id = sampler->platform_data()->vm_tid(); |
257 void* thread_key = ThreadKey(thread_id); | 257 void* thread_key = ThreadKey(thread_id); |
258 uint32_t thread_hash = ThreadHash(thread_id); | 258 uint32_t thread_hash = ThreadHash(thread_id); |
259 HashMap::Entry* entry = sampler_map_.Lookup(thread_key, thread_hash); | 259 base::HashMap::Entry* entry = sampler_map_.Lookup(thread_key, thread_hash); |
260 DCHECK(entry != nullptr); | 260 DCHECK(entry != nullptr); |
261 SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value); | 261 SamplerList* samplers = reinterpret_cast<SamplerList*>(entry->value); |
262 for (SamplerListIterator iter = samplers->begin(); iter != samplers->end(); | 262 for (SamplerListIterator iter = samplers->begin(); iter != samplers->end(); |
263 ++iter) { | 263 ++iter) { |
264 if (*iter == sampler) { | 264 if (*iter == sampler) { |
265 samplers->erase(iter); | 265 samplers->erase(iter); |
266 break; | 266 break; |
267 } | 267 } |
268 } | 268 } |
269 if (samplers->empty()) { | 269 if (samplers->empty()) { |
270 sampler_map_.Remove(thread_key, thread_hash); | 270 sampler_map_.Remove(thread_key, thread_hash); |
271 delete samplers; | 271 delete samplers; |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 #if defined(USE_SIGNALS) | 275 #if defined(USE_SIGNALS) |
276 void DoSample(const v8::RegisterState& state) { | 276 void DoSample(const v8::RegisterState& state) { |
277 AtomicGuard atomic_guard(&SamplerManager::samplers_access_counter_, false); | 277 AtomicGuard atomic_guard(&SamplerManager::samplers_access_counter_, false); |
278 if (!atomic_guard.is_success()) return; | 278 if (!atomic_guard.is_success()) return; |
279 pthread_t thread_id = pthread_self(); | 279 pthread_t thread_id = pthread_self(); |
280 HashMap::Entry* entry = | 280 base::HashMap::Entry* entry = |
281 sampler_map_.Lookup(ThreadKey(thread_id), ThreadHash(thread_id)); | 281 sampler_map_.Lookup(ThreadKey(thread_id), ThreadHash(thread_id)); |
282 if (!entry) return; | 282 if (!entry) return; |
283 SamplerList& samplers = *static_cast<SamplerList*>(entry->value); | 283 SamplerList& samplers = *static_cast<SamplerList*>(entry->value); |
284 | 284 |
285 for (int i = 0; i < samplers.size(); ++i) { | 285 for (int i = 0; i < samplers.size(); ++i) { |
286 Sampler* sampler = samplers[i]; | 286 Sampler* sampler = samplers[i]; |
287 Isolate* isolate = sampler->isolate(); | 287 Isolate* isolate = sampler->isolate(); |
288 // We require a fully initialized and entered isolate. | 288 // We require a fully initialized and entered isolate. |
289 if (isolate == nullptr || !isolate->IsInUse()) continue; | 289 if (isolate == nullptr || !isolate->IsInUse()) continue; |
290 if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue; | 290 if (v8::Locker::IsActive() && !Locker::IsLocked(isolate)) continue; |
291 sampler->SampleStack(state); | 291 sampler->SampleStack(state); |
292 } | 292 } |
293 } | 293 } |
294 #endif | 294 #endif |
295 | 295 |
296 static SamplerManager* instance() { return instance_.Pointer(); } | 296 static SamplerManager* instance() { return instance_.Pointer(); } |
297 | 297 |
298 private: | 298 private: |
299 HashMap sampler_map_; | 299 base::HashMap sampler_map_; |
300 static AtomicMutex samplers_access_counter_; | 300 static AtomicMutex samplers_access_counter_; |
301 static base::LazyInstance<SamplerManager>::type instance_; | 301 static base::LazyInstance<SamplerManager>::type instance_; |
302 }; | 302 }; |
303 | 303 |
304 AtomicMutex SamplerManager::samplers_access_counter_; | 304 AtomicMutex SamplerManager::samplers_access_counter_; |
305 base::LazyInstance<SamplerManager>::type SamplerManager::instance_ = | 305 base::LazyInstance<SamplerManager>::type SamplerManager::instance_ = |
306 LAZY_INSTANCE_INITIALIZER; | 306 LAZY_INSTANCE_INITIALIZER; |
307 | 307 |
308 #elif V8_OS_WIN || V8_OS_CYGWIN | 308 #elif V8_OS_WIN || V8_OS_CYGWIN |
309 | 309 |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 #endif | 664 #endif |
665 SampleStack(state); | 665 SampleStack(state); |
666 } | 666 } |
667 ResumeThread(profiled_thread); | 667 ResumeThread(profiled_thread); |
668 } | 668 } |
669 | 669 |
670 #endif // USE_SIGNALS | 670 #endif // USE_SIGNALS |
671 | 671 |
672 } // namespace sampler | 672 } // namespace sampler |
673 } // namespace v8 | 673 } // namespace v8 |
OLD | NEW |