| 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 |