| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "sampler.h" |
| 29 |
| 28 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ | 30 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ |
| 29 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \ | 31 || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \ |
| 30 || defined(__native_client__) | 32 || defined(__native_client__) |
| 31 | 33 |
| 32 #define USE_SIGNALS | 34 #define USE_SIGNALS |
| 33 | 35 |
| 34 #include <errno.h> | 36 #include <errno.h> |
| 35 #include <pthread.h> | 37 #include <pthread.h> |
| 36 #include <signal.h> | 38 #include <signal.h> |
| 37 #include <sys/time.h> | 39 #include <sys/time.h> |
| (...skipping 15 matching lines...) Expand all Loading... |
| 53 #include <mach/mach.h> | 55 #include <mach/mach.h> |
| 54 | 56 |
| 55 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 57 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
| 56 | 58 |
| 57 #include "win32-headers.h" | 59 #include "win32-headers.h" |
| 58 | 60 |
| 59 #endif | 61 #endif |
| 60 | 62 |
| 61 #include "v8.h" | 63 #include "v8.h" |
| 62 | 64 |
| 65 #include "cpu-profiler.h" |
| 66 #include "flags.h" |
| 63 #include "frames-inl.h" | 67 #include "frames-inl.h" |
| 64 #include "log.h" | 68 #include "log.h" |
| 65 #include "platform.h" | 69 #include "platform.h" |
| 66 #include "simulator.h" | 70 #include "simulator.h" |
| 67 #include "v8threads.h" | 71 #include "v8threads.h" |
| 68 | 72 |
| 69 | 73 |
| 70 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) | 74 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) |
| 71 | 75 |
| 72 // Not all versions of Android's C library provide ucontext_t. | 76 // Not all versions of Android's C library provide ucontext_t. |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 227 } |
| 224 | 228 |
| 225 HANDLE profiled_thread() { return profiled_thread_; } | 229 HANDLE profiled_thread() { return profiled_thread_; } |
| 226 | 230 |
| 227 private: | 231 private: |
| 228 HANDLE profiled_thread_; | 232 HANDLE profiled_thread_; |
| 229 }; | 233 }; |
| 230 #endif | 234 #endif |
| 231 | 235 |
| 232 | 236 |
| 233 class SampleHelper { | 237 #if defined(USE_SIMULATOR) |
| 238 class SimulatorHelper { |
| 234 public: | 239 public: |
| 235 inline TickSample* Init(Sampler* sampler, Isolate* isolate) { | 240 inline bool Init(Sampler* sampler, Isolate* isolate) { |
| 236 #if defined(USE_SIMULATOR) | |
| 237 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); | 241 ThreadId thread_id = sampler->platform_data()->profiled_thread_id(); |
| 238 Isolate::PerIsolateThreadData* per_thread_data = isolate-> | 242 Isolate::PerIsolateThreadData* per_thread_data = isolate-> |
| 239 FindPerThreadDataForThread(thread_id); | 243 FindPerThreadDataForThread(thread_id); |
| 240 if (!per_thread_data) return NULL; | 244 if (!per_thread_data) return false; |
| 241 simulator_ = per_thread_data->simulator(); | 245 simulator_ = per_thread_data->simulator(); |
| 242 // Check if there is active simulator before allocating TickSample. | 246 // Check if there is active simulator. |
| 243 if (!simulator_) return NULL; | 247 return simulator_ != NULL; |
| 244 #endif // USE_SIMULATOR | |
| 245 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent(); | |
| 246 if (sample == NULL) sample = &sample_obj; | |
| 247 return sample; | |
| 248 } | 248 } |
| 249 | 249 |
| 250 #if defined(USE_SIMULATOR) | 250 inline void FillRegisters(RegisterState* state) { |
| 251 inline void FillRegisters(TickSample* sample) { | |
| 252 #if V8_TARGET_ARCH_ARM | 251 #if V8_TARGET_ARCH_ARM |
| 253 sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); | 252 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
| 254 sample->sp = reinterpret_cast<Address>(simulator_->get_register( | 253 state->sp = reinterpret_cast<Address>(simulator_->get_register( |
| 255 Simulator::sp)); | 254 Simulator::sp)); |
| 256 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 255 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
| 257 Simulator::r11)); | 256 Simulator::r11)); |
| 258 #elif V8_TARGET_ARCH_A64 | 257 #elif V8_TARGET_ARCH_A64 |
| 259 if (simulator_->sp() == 0 || simulator_->fp() == 0) { | 258 if (simulator_->sp() == 0 || simulator_->fp() == 0) { |
| 260 // It possible that the simulator is interrupted while it is updating | 259 // It possible that the simulator is interrupted while it is updating |
| 261 // the sp or fp register. A64 simulator does this in two steps: | 260 // the sp or fp register. A64 simulator does this in two steps: |
| 262 // first setting it to zero and then setting it to the new value. | 261 // first setting it to zero and then setting it to the new value. |
| 263 // Bailout if sp/fp doesn't contain the new value. | 262 // Bailout if sp/fp doesn't contain the new value. |
| 264 return; | 263 return; |
| 265 } | 264 } |
| 266 sample->pc = reinterpret_cast<Address>(simulator_->pc()); | 265 state->pc = reinterpret_cast<Address>(simulator_->pc()); |
| 267 sample->sp = reinterpret_cast<Address>(simulator_->sp()); | 266 state->sp = reinterpret_cast<Address>(simulator_->sp()); |
| 268 sample->fp = reinterpret_cast<Address>(simulator_->fp()); | 267 state->fp = reinterpret_cast<Address>(simulator_->fp()); |
| 269 #elif V8_TARGET_ARCH_MIPS | 268 #elif V8_TARGET_ARCH_MIPS |
| 270 sample->pc = reinterpret_cast<Address>(simulator_->get_pc()); | 269 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); |
| 271 sample->sp = reinterpret_cast<Address>(simulator_->get_register( | 270 state->sp = reinterpret_cast<Address>(simulator_->get_register( |
| 272 Simulator::sp)); | 271 Simulator::sp)); |
| 273 sample->fp = reinterpret_cast<Address>(simulator_->get_register( | 272 state->fp = reinterpret_cast<Address>(simulator_->get_register( |
| 274 Simulator::fp)); | 273 Simulator::fp)); |
| 275 #endif | 274 #endif |
| 276 } | 275 } |
| 277 #endif // USE_SIMULATOR | |
| 278 | 276 |
| 279 private: | 277 private: |
| 280 #if defined(USE_SIMULATOR) | |
| 281 Simulator* simulator_; | 278 Simulator* simulator_; |
| 282 #endif | |
| 283 TickSample sample_obj; | |
| 284 }; | 279 }; |
| 280 #endif // USE_SIMULATOR |
| 285 | 281 |
| 286 | 282 |
| 287 #if defined(USE_SIGNALS) | 283 #if defined(USE_SIGNALS) |
| 288 | 284 |
| 289 class SignalHandler : public AllStatic { | 285 class SignalHandler : public AllStatic { |
| 290 public: | 286 public: |
| 291 static inline void EnsureInstalled() { | 287 static inline void EnsureInstalled() { |
| 292 if (signal_handler_installed_) return; | 288 if (signal_handler_installed_) return; |
| 293 struct sigaction sa; | 289 struct sigaction sa; |
| 294 sa.sa_sigaction = &HandleProfilerSignal; | 290 sa.sa_sigaction = &HandleProfilerSignal; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 return; | 330 return; |
| 335 } | 331 } |
| 336 if (v8::Locker::IsActive() && | 332 if (v8::Locker::IsActive() && |
| 337 !isolate->thread_manager()->IsLockedByCurrentThread()) { | 333 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
| 338 return; | 334 return; |
| 339 } | 335 } |
| 340 | 336 |
| 341 Sampler* sampler = isolate->logger()->sampler(); | 337 Sampler* sampler = isolate->logger()->sampler(); |
| 342 if (sampler == NULL || !sampler->IsActive()) return; | 338 if (sampler == NULL || !sampler->IsActive()) return; |
| 343 | 339 |
| 344 SampleHelper helper; | 340 RegisterState state; |
| 345 TickSample* sample = helper.Init(sampler, isolate); | |
| 346 if (sample == NULL) return; | |
| 347 | 341 |
| 348 #if defined(USE_SIMULATOR) | 342 #if defined(USE_SIMULATOR) |
| 349 helper.FillRegisters(sample); | 343 SimulatorHelper helper; |
| 344 if (!helper.Init(sampler, isolate)) return; |
| 345 helper.FillRegisters(&state); |
| 350 // It possible that the simulator is interrupted while it is updating | 346 // It possible that the simulator is interrupted while it is updating |
| 351 // the sp or fp register. A64 simulator does this in two steps: | 347 // the sp or fp register. A64 simulator does this in two steps: |
| 352 // first setting it to zero and then setting it to the new value. | 348 // first setting it to zero and then setting it to the new value. |
| 353 // Bailout if sp/fp doesn't contain the new value. | 349 // Bailout if sp/fp doesn't contain the new value. |
| 354 if (sample->sp == 0 || sample->fp == 0) return; | 350 if (state.sp == 0 || state.fp == 0) return; |
| 355 #else | 351 #else |
| 356 // Extracting the sample from the context is extremely machine dependent. | 352 // Extracting the sample from the context is extremely machine dependent. |
| 357 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); | 353 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); |
| 358 mcontext_t& mcontext = ucontext->uc_mcontext; | 354 mcontext_t& mcontext = ucontext->uc_mcontext; |
| 359 sample->state = isolate->current_vm_state(); | |
| 360 #if defined(__linux__) || defined(__ANDROID__) | 355 #if defined(__linux__) || defined(__ANDROID__) |
| 361 #if V8_HOST_ARCH_IA32 | 356 #if V8_HOST_ARCH_IA32 |
| 362 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); | 357 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); |
| 363 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); | 358 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); |
| 364 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); | 359 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); |
| 365 #elif V8_HOST_ARCH_X64 | 360 #elif V8_HOST_ARCH_X64 |
| 366 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); | 361 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); |
| 367 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); | 362 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); |
| 368 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); | 363 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); |
| 369 #elif V8_HOST_ARCH_ARM | 364 #elif V8_HOST_ARCH_ARM |
| 370 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ | 365 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \ |
| 371 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 366 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| 372 // Old GLibc ARM versions used a gregs[] array to access the register | 367 // Old GLibc ARM versions used a gregs[] array to access the register |
| 373 // values from mcontext_t. | 368 // values from mcontext_t. |
| 374 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); | 369 state.pc = reinterpret_cast<Address>(mcontext.gregs[R15]); |
| 375 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); | 370 state.sp = reinterpret_cast<Address>(mcontext.gregs[R13]); |
| 376 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); | 371 state.fp = reinterpret_cast<Address>(mcontext.gregs[R11]); |
| 377 #else | 372 #else |
| 378 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); | 373 state.pc = reinterpret_cast<Address>(mcontext.arm_pc); |
| 379 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); | 374 state.sp = reinterpret_cast<Address>(mcontext.arm_sp); |
| 380 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); | 375 state.fp = reinterpret_cast<Address>(mcontext.arm_fp); |
| 381 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && | 376 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) && |
| 382 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) | 377 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) |
| 383 #elif V8_HOST_ARCH_A64 | 378 #elif V8_HOST_ARCH_A64 |
| 384 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 379 sample->pc = reinterpret_cast<Address>(mcontext.pc); |
| 385 sample->sp = reinterpret_cast<Address>(mcontext.sp); | 380 sample->sp = reinterpret_cast<Address>(mcontext.sp); |
| 386 // FP is an alias for x29. | 381 // FP is an alias for x29. |
| 387 sample->fp = reinterpret_cast<Address>(mcontext.regs[29]); | 382 sample->fp = reinterpret_cast<Address>(mcontext.regs[29]); |
| 388 #elif V8_HOST_ARCH_MIPS | 383 #elif V8_HOST_ARCH_MIPS |
| 389 sample->pc = reinterpret_cast<Address>(mcontext.pc); | 384 state.pc = reinterpret_cast<Address>(mcontext.pc); |
| 390 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); | 385 state.sp = reinterpret_cast<Address>(mcontext.gregs[29]); |
| 391 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); | 386 state.fp = reinterpret_cast<Address>(mcontext.gregs[30]); |
| 392 #endif // V8_HOST_ARCH_* | 387 #endif // V8_HOST_ARCH_* |
| 393 #elif defined(__FreeBSD__) | 388 #elif defined(__FreeBSD__) |
| 394 #if V8_HOST_ARCH_IA32 | 389 #if V8_HOST_ARCH_IA32 |
| 395 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); | 390 state.pc = reinterpret_cast<Address>(mcontext.mc_eip); |
| 396 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); | 391 state.sp = reinterpret_cast<Address>(mcontext.mc_esp); |
| 397 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); | 392 state.fp = reinterpret_cast<Address>(mcontext.mc_ebp); |
| 398 #elif V8_HOST_ARCH_X64 | 393 #elif V8_HOST_ARCH_X64 |
| 399 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); | 394 state.pc = reinterpret_cast<Address>(mcontext.mc_rip); |
| 400 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); | 395 state.sp = reinterpret_cast<Address>(mcontext.mc_rsp); |
| 401 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); | 396 state.fp = reinterpret_cast<Address>(mcontext.mc_rbp); |
| 402 #elif V8_HOST_ARCH_ARM | 397 #elif V8_HOST_ARCH_ARM |
| 403 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); | 398 state.pc = reinterpret_cast<Address>(mcontext.mc_r15); |
| 404 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); | 399 state.sp = reinterpret_cast<Address>(mcontext.mc_r13); |
| 405 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); | 400 state.fp = reinterpret_cast<Address>(mcontext.mc_r11); |
| 406 #endif // V8_HOST_ARCH_* | 401 #endif // V8_HOST_ARCH_* |
| 407 #elif defined(__NetBSD__) | 402 #elif defined(__NetBSD__) |
| 408 #if V8_HOST_ARCH_IA32 | 403 #if V8_HOST_ARCH_IA32 |
| 409 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); | 404 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); |
| 410 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); | 405 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); |
| 411 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); | 406 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); |
| 412 #elif V8_HOST_ARCH_X64 | 407 #elif V8_HOST_ARCH_X64 |
| 413 sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); | 408 state.pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); |
| 414 sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); | 409 state.sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); |
| 415 sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); | 410 state.fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); |
| 416 #endif // V8_HOST_ARCH_* | 411 #endif // V8_HOST_ARCH_* |
| 417 #elif defined(__OpenBSD__) | 412 #elif defined(__OpenBSD__) |
| 418 USE(mcontext); | 413 USE(mcontext); |
| 419 #if V8_HOST_ARCH_IA32 | 414 #if V8_HOST_ARCH_IA32 |
| 420 sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); | 415 state.pc = reinterpret_cast<Address>(ucontext->sc_eip); |
| 421 sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); | 416 state.sp = reinterpret_cast<Address>(ucontext->sc_esp); |
| 422 sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); | 417 state.fp = reinterpret_cast<Address>(ucontext->sc_ebp); |
| 423 #elif V8_HOST_ARCH_X64 | 418 #elif V8_HOST_ARCH_X64 |
| 424 sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); | 419 state.pc = reinterpret_cast<Address>(ucontext->sc_rip); |
| 425 sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); | 420 state.sp = reinterpret_cast<Address>(ucontext->sc_rsp); |
| 426 sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); | 421 state.fp = reinterpret_cast<Address>(ucontext->sc_rbp); |
| 427 #endif // V8_HOST_ARCH_* | 422 #endif // V8_HOST_ARCH_* |
| 428 #elif defined(__sun) | 423 #elif defined(__sun) |
| 429 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); | 424 state.pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); |
| 430 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); | 425 state.sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); |
| 431 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); | 426 state.fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); |
| 432 #endif // __sun | 427 #endif // __sun |
| 433 #endif // USE_SIMULATOR | 428 #endif // USE_SIMULATOR |
| 434 | 429 sampler->SampleStack(state); |
| 435 sampler->SampleStack(sample); | |
| 436 sampler->Tick(sample); | |
| 437 #endif // __native_client__ | 430 #endif // __native_client__ |
| 438 } | 431 } |
| 439 | 432 |
| 440 #endif | 433 #endif |
| 441 | 434 |
| 442 | 435 |
| 443 class SamplerThread : public Thread { | 436 class SamplerThread : public Thread { |
| 444 public: | 437 public: |
| 445 static const int kSamplerThreadStackSize = 64 * KB; | 438 static const int kSamplerThreadStackSize = 64 * KB; |
| 446 | 439 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 void SampleContext(Sampler* sampler) { | 516 void SampleContext(Sampler* sampler) { |
| 524 if (!SignalHandler::Installed()) return; | 517 if (!SignalHandler::Installed()) return; |
| 525 pthread_t tid = sampler->platform_data()->vm_tid(); | 518 pthread_t tid = sampler->platform_data()->vm_tid(); |
| 526 pthread_kill(tid, SIGPROF); | 519 pthread_kill(tid, SIGPROF); |
| 527 } | 520 } |
| 528 | 521 |
| 529 #elif defined(__MACH__) | 522 #elif defined(__MACH__) |
| 530 | 523 |
| 531 void SampleContext(Sampler* sampler) { | 524 void SampleContext(Sampler* sampler) { |
| 532 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); | 525 thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); |
| 526 |
| 527 #if defined(USE_SIMULATOR) |
| 528 SimulatorHelper helper; |
| 533 Isolate* isolate = sampler->isolate(); | 529 Isolate* isolate = sampler->isolate(); |
| 534 | 530 if (!helper.Init(sampler, isolate)) return; |
| 535 SampleHelper helper; | 531 #endif |
| 536 TickSample* sample = helper.Init(sampler, isolate); | |
| 537 if (sample == NULL) return; | |
| 538 | 532 |
| 539 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; | 533 if (KERN_SUCCESS != thread_suspend(profiled_thread)) return; |
| 540 | 534 |
| 541 #if V8_HOST_ARCH_X64 | 535 #if V8_HOST_ARCH_X64 |
| 542 thread_state_flavor_t flavor = x86_THREAD_STATE64; | 536 thread_state_flavor_t flavor = x86_THREAD_STATE64; |
| 543 x86_thread_state64_t state; | 537 x86_thread_state64_t thread_state; |
| 544 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; | 538 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; |
| 545 #if __DARWIN_UNIX03 | 539 #if __DARWIN_UNIX03 |
| 546 #define REGISTER_FIELD(name) __r ## name | 540 #define REGISTER_FIELD(name) __r ## name |
| 547 #else | 541 #else |
| 548 #define REGISTER_FIELD(name) r ## name | 542 #define REGISTER_FIELD(name) r ## name |
| 549 #endif // __DARWIN_UNIX03 | 543 #endif // __DARWIN_UNIX03 |
| 550 #elif V8_HOST_ARCH_IA32 | 544 #elif V8_HOST_ARCH_IA32 |
| 551 thread_state_flavor_t flavor = i386_THREAD_STATE; | 545 thread_state_flavor_t flavor = i386_THREAD_STATE; |
| 552 i386_thread_state_t state; | 546 i386_thread_state_t thread_state; |
| 553 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; | 547 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT; |
| 554 #if __DARWIN_UNIX03 | 548 #if __DARWIN_UNIX03 |
| 555 #define REGISTER_FIELD(name) __e ## name | 549 #define REGISTER_FIELD(name) __e ## name |
| 556 #else | 550 #else |
| 557 #define REGISTER_FIELD(name) e ## name | 551 #define REGISTER_FIELD(name) e ## name |
| 558 #endif // __DARWIN_UNIX03 | 552 #endif // __DARWIN_UNIX03 |
| 559 #else | 553 #else |
| 560 #error Unsupported Mac OS X host architecture. | 554 #error Unsupported Mac OS X host architecture. |
| 561 #endif // V8_HOST_ARCH | 555 #endif // V8_HOST_ARCH |
| 562 | 556 |
| 563 if (thread_get_state(profiled_thread, | 557 if (thread_get_state(profiled_thread, |
| 564 flavor, | 558 flavor, |
| 565 reinterpret_cast<natural_t*>(&state), | 559 reinterpret_cast<natural_t*>(&thread_state), |
| 566 &count) == KERN_SUCCESS) { | 560 &count) == KERN_SUCCESS) { |
| 567 sample->state = isolate->current_vm_state(); | 561 RegisterState state; |
| 568 #if defined(USE_SIMULATOR) | 562 #if defined(USE_SIMULATOR) |
| 569 helper.FillRegisters(sample); | 563 helper.FillRegisters(&state); |
| 570 #else | 564 #else |
| 571 sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip)); | 565 state.pc = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(ip)); |
| 572 sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp)); | 566 state.sp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(sp)); |
| 573 sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp)); | 567 state.fp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(bp)); |
| 574 #endif // USE_SIMULATOR | 568 #endif // USE_SIMULATOR |
| 575 #undef REGISTER_FIELD | 569 #undef REGISTER_FIELD |
| 576 sampler->SampleStack(sample); | 570 sampler->SampleStack(state); |
| 577 sampler->Tick(sample); | |
| 578 } | 571 } |
| 579 thread_resume(profiled_thread); | 572 thread_resume(profiled_thread); |
| 580 } | 573 } |
| 581 | 574 |
| 582 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) | 575 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) |
| 583 | 576 |
| 584 void SampleContext(Sampler* sampler) { | 577 void SampleContext(Sampler* sampler) { |
| 585 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); | 578 HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); |
| 586 if (profiled_thread == NULL) return; | 579 if (profiled_thread == NULL) return; |
| 587 | 580 |
| 588 Isolate* isolate = sampler->isolate(); | 581 Isolate* isolate = sampler->isolate(); |
| 589 SampleHelper helper; | 582 #if defined(USE_SIMULATOR) |
| 590 TickSample* sample = helper.Init(sampler, isolate); | 583 SimulatorHelper helper; |
| 591 if (sample == NULL) return; | 584 if (!helper.Init(sampler, isolate)) return; |
| 585 #endif |
| 592 | 586 |
| 593 const DWORD kSuspendFailed = static_cast<DWORD>(-1); | 587 const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
| 594 if (SuspendThread(profiled_thread) == kSuspendFailed) return; | 588 if (SuspendThread(profiled_thread) == kSuspendFailed) return; |
| 595 sample->state = isolate->current_vm_state(); | |
| 596 | 589 |
| 597 // Context used for sampling the register state of the profiled thread. | 590 // Context used for sampling the register state of the profiled thread. |
| 598 CONTEXT context; | 591 CONTEXT context; |
| 599 memset(&context, 0, sizeof(context)); | 592 memset(&context, 0, sizeof(context)); |
| 600 context.ContextFlags = CONTEXT_FULL; | 593 context.ContextFlags = CONTEXT_FULL; |
| 601 if (GetThreadContext(profiled_thread, &context) != 0) { | 594 if (GetThreadContext(profiled_thread, &context) != 0) { |
| 595 RegisterState state; |
| 602 #if defined(USE_SIMULATOR) | 596 #if defined(USE_SIMULATOR) |
| 603 helper.FillRegisters(sample); | 597 helper.FillRegisters(&state); |
| 604 #else | 598 #else |
| 605 #if V8_HOST_ARCH_X64 | 599 #if V8_HOST_ARCH_X64 |
| 606 sample->pc = reinterpret_cast<Address>(context.Rip); | 600 state.pc = reinterpret_cast<Address>(context.Rip); |
| 607 sample->sp = reinterpret_cast<Address>(context.Rsp); | 601 state.sp = reinterpret_cast<Address>(context.Rsp); |
| 608 sample->fp = reinterpret_cast<Address>(context.Rbp); | 602 state.fp = reinterpret_cast<Address>(context.Rbp); |
| 609 #else | 603 #else |
| 610 sample->pc = reinterpret_cast<Address>(context.Eip); | 604 state.pc = reinterpret_cast<Address>(context.Eip); |
| 611 sample->sp = reinterpret_cast<Address>(context.Esp); | 605 state.sp = reinterpret_cast<Address>(context.Esp); |
| 612 sample->fp = reinterpret_cast<Address>(context.Ebp); | 606 state.fp = reinterpret_cast<Address>(context.Ebp); |
| 613 #endif | 607 #endif |
| 614 #endif // USE_SIMULATOR | 608 #endif // USE_SIMULATOR |
| 615 sampler->SampleStack(sample); | 609 sampler->SampleStack(state); |
| 616 sampler->Tick(sample); | |
| 617 } | 610 } |
| 618 ResumeThread(profiled_thread); | 611 ResumeThread(profiled_thread); |
| 619 } | 612 } |
| 620 | 613 |
| 621 #endif // USE_SIGNALS | 614 #endif // USE_SIGNALS |
| 622 | 615 |
| 623 | 616 |
| 624 // Protects the process wide state below. | 617 // Protects the process wide state below. |
| 625 static Mutex* mutex_; | 618 static Mutex* mutex_; |
| 626 static SamplerThread* instance_; | 619 static SamplerThread* instance_; |
| 627 | 620 |
| 628 const int interval_; | 621 const int interval_; |
| 629 List<Sampler*> active_samplers_; | 622 List<Sampler*> active_samplers_; |
| 630 | 623 |
| 631 DISALLOW_COPY_AND_ASSIGN(SamplerThread); | 624 DISALLOW_COPY_AND_ASSIGN(SamplerThread); |
| 632 }; | 625 }; |
| 633 | 626 |
| 634 | 627 |
| 635 Mutex* SamplerThread::mutex_ = NULL; | 628 Mutex* SamplerThread::mutex_ = NULL; |
| 636 SamplerThread* SamplerThread::instance_ = NULL; | 629 SamplerThread* SamplerThread::instance_ = NULL; |
| 637 | 630 |
| 638 | 631 |
| 639 // | 632 // |
| 640 // StackTracer implementation | 633 // StackTracer implementation |
| 641 // | 634 // |
| 642 DISABLE_ASAN void TickSample::Trace(Isolate* isolate) { | 635 DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
| 636 const RegisterState& regs) { |
| 643 ASSERT(isolate->IsInitialized()); | 637 ASSERT(isolate->IsInitialized()); |
| 638 pc = regs.pc; |
| 639 state = isolate->current_vm_state(); |
| 644 | 640 |
| 645 // Avoid collecting traces while doing GC. | 641 // Avoid collecting traces while doing GC. |
| 646 if (state == GC) return; | 642 if (state == GC) return; |
| 647 | 643 |
| 648 const Address js_entry_sp = | 644 const Address js_entry_sp = |
| 649 Isolate::js_entry_sp(isolate->thread_local_top()); | 645 Isolate::js_entry_sp(isolate->thread_local_top()); |
| 650 if (js_entry_sp == 0) { | 646 if (js_entry_sp == 0) { |
| 651 // Not executing JS now. | 647 // Not executing JS now. |
| 652 return; | 648 return; |
| 653 } | 649 } |
| 654 | 650 |
| 655 const Address callback = isolate->external_callback(); | 651 const Address callback = isolate->external_callback(); |
| 656 if (callback != NULL) { | 652 if (callback != NULL) { |
| 657 external_callback = callback; | 653 external_callback = callback; |
| 658 has_external_callback = true; | 654 has_external_callback = true; |
| 659 } else { | 655 } else { |
| 660 // Sample potential return address value for frameless invocation of | 656 // Sample potential return address value for frameless invocation of |
| 661 // stubs (we'll figure out later, if this value makes sense). | 657 // stubs (we'll figure out later, if this value makes sense). |
| 662 tos = Memory::Address_at(sp); | 658 tos = Memory::Address_at(regs.sp); |
| 663 has_external_callback = false; | 659 has_external_callback = false; |
| 664 } | 660 } |
| 665 | 661 |
| 666 SafeStackFrameIterator it(isolate, fp, sp, sp, js_entry_sp); | 662 SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp); |
| 663 top_frame_type = it.top_frame_type(); |
| 667 int i = 0; | 664 int i = 0; |
| 668 while (!it.done() && i < TickSample::kMaxFramesCount) { | 665 while (!it.done() && i < TickSample::kMaxFramesCount) { |
| 669 stack[i++] = it.frame()->pc(); | 666 stack[i++] = it.frame()->pc(); |
| 670 it.Advance(); | 667 it.Advance(); |
| 671 } | 668 } |
| 672 frames_count = i; | 669 frames_count = i; |
| 673 } | 670 } |
| 674 | 671 |
| 675 | 672 |
| 676 void Sampler::SetUp() { | 673 void Sampler::SetUp() { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 691 samples_taken_(0) { | 688 samples_taken_(0) { |
| 692 data_ = new PlatformData; | 689 data_ = new PlatformData; |
| 693 } | 690 } |
| 694 | 691 |
| 695 | 692 |
| 696 Sampler::~Sampler() { | 693 Sampler::~Sampler() { |
| 697 ASSERT(!IsActive()); | 694 ASSERT(!IsActive()); |
| 698 delete data_; | 695 delete data_; |
| 699 } | 696 } |
| 700 | 697 |
| 698 |
| 701 void Sampler::Start() { | 699 void Sampler::Start() { |
| 702 ASSERT(!IsActive()); | 700 ASSERT(!IsActive()); |
| 703 SetActive(true); | 701 SetActive(true); |
| 704 SamplerThread::AddActiveSampler(this); | 702 SamplerThread::AddActiveSampler(this); |
| 705 } | 703 } |
| 706 | 704 |
| 707 | 705 |
| 708 void Sampler::Stop() { | 706 void Sampler::Stop() { |
| 709 ASSERT(IsActive()); | 707 ASSERT(IsActive()); |
| 710 SamplerThread::RemoveActiveSampler(this); | 708 SamplerThread::RemoveActiveSampler(this); |
| 711 SetActive(false); | 709 SetActive(false); |
| 712 } | 710 } |
| 713 | 711 |
| 714 void Sampler::SampleStack(TickSample* sample) { | 712 |
| 715 sample->Trace(isolate_); | 713 void Sampler::SampleStack(const RegisterState& state) { |
| 714 TickSample* sample = isolate_->cpu_profiler()->TickSampleEvent(); |
| 715 TickSample sample_obj; |
| 716 if (sample == NULL) sample = &sample_obj; |
| 717 sample->Init(isolate_, state); |
| 716 if (++samples_taken_ < 0) samples_taken_ = 0; | 718 if (++samples_taken_ < 0) samples_taken_ = 0; |
| 719 Tick(sample); |
| 717 } | 720 } |
| 718 | 721 |
| 719 } } // namespace v8::internal | 722 } } // namespace v8::internal |
| OLD | NEW |