trace.cc revision 700a402244a1a423da4f3ba8032459f4b65fa18f
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 17e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "trace.h" 18e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 19a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include <sys/uio.h> 20a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 210abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "base/stl_util.h" 22761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 23e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "class_linker.h" 2462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h" 25a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "debugger.h" 264f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 27725a957985171d712d5c048cc3d00ff14968784bjeffhao#include "instrumentation.h" 28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 294f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/dex_cache.h" 312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 324f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 33a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "object_utils.h" 34a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao#include "os.h" 3500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 360abc72ebe356c32354b575c48189965a0edc7890Jeff Hao#include "ScopedLocalRef.h" 37e343b76af81a005ef64f5e75a555389fd9147dabjeffhao#include "thread.h" 3857b86d47b66322693a070185fadfb43cb9c12eabIan Rogers#include "thread_list.h" 39166db04e259ca51838c311891598664deeed85adIan Rogers#if !defined(ART_USE_PORTABLE_COMPILER) 40166db04e259ca51838c311891598664deeed85adIan Rogers#include "entrypoints/quick/quick_entrypoints.h" 41166db04e259ca51838c311891598664deeed85adIan Rogers#endif 422692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 432692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaonamespace art { 442692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 45e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// File format: 46e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// header 47e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// record 0 48e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// record 1 49e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// ... 50e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 51e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Header format: 52e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 magic ('SLOW') 53e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u2 version 54e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u2 offset to data 55e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u8 start date/time in usec 56e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u2 record size in bytes (version >= 2 only) 57e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// ... padding to 32 bytes 58e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 59e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v1: 60e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u1 thread ID 61e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 method ID | method action 62e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 time delta since start, in usec 63e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 64e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v2: 65e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u2 thread ID 66e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 method ID | method action 67e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 time delta since start, in usec 68e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 69e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// Record format v3: 70e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u2 thread ID 71e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 method ID | method action 72e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 time delta since start, in usec 73e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// u4 wall time since start, in usec (when clock == "dual" only) 74e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 75e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 32 bits of microseconds is 70 minutes. 76e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// 77e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes// All values are stored in little-endian order. 78e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 7962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersenum TraceAction { 807934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom kTraceMethodEnter = 0x00, // method entry 817934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom kTraceMethodExit = 0x01, // method exit 827934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom kTraceUnroll = 0x02, // method exited by exception unrolling 8362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // 0x03 currently unused 847934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom kTraceMethodActionMask = 0x03, // two bits 8562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}; 8662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 870abc72ebe356c32354b575c48189965a0edc7890Jeff Haoclass BuildStackTraceVisitor : public StackVisitor { 880abc72ebe356c32354b575c48189965a0edc7890Jeff Hao public: 890abc72ebe356c32354b575c48189965a0edc7890Jeff Hao explicit BuildStackTraceVisitor(Thread* thread) : StackVisitor(thread, NULL), 905ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao method_trace_(Trace::AllocStackTrace()) {} 910abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 92ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 93e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers mirror::ArtMethod* m = GetMethod(); 940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Ignore runtime frames (in particular callee save). 950abc72ebe356c32354b575c48189965a0edc7890Jeff Hao if (!m->IsRuntimeMethod()) { 960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao method_trace_->push_back(m); 970abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 980abc72ebe356c32354b575c48189965a0edc7890Jeff Hao return true; 990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 1000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 1010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Returns a stack trace where the topmost frame corresponds with the first element of the vector. 102e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>* GetStackTrace() const { 1030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao return method_trace_; 1040abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 1050abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 1060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao private: 107e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>* const method_trace_; 1080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao}; 1090abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 110a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const char kTraceTokenChar = '*'; 111a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceHeaderLength = 32; 112a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint32_t kTraceMagicValue = 0x574f4c53; 113a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionSingleClock = 2; 114a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic const uint16_t kTraceVersionDualClock = 3; 1157934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const uint16_t kTraceRecordSizeSingleClock = 10; // using v2 1167934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstromstatic const uint16_t kTraceRecordSizeDualClock = 14; // using v3 with two timestamps 117a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 118491ca9e75fad381468dd7f5fdbff56d1a9738dd7Brian CarlstromProfilerClockSource Trace::default_clock_source_ = kDefaultProfilerClockSource; 11962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 1200abc72ebe356c32354b575c48189965a0edc7890Jeff HaoTrace* volatile Trace::the_trace_ = NULL; 1210abc72ebe356c32354b575c48189965a0edc7890Jeff Haopthread_t Trace::sampling_pthread_ = 0U; 122700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogersstd::unique_ptr<std::vector<mirror::ArtMethod*>> Trace::temp_stack_trace_; 123e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 124ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromstatic mirror::ArtMethod* DecodeTraceMethodId(uint32_t tmid) { 125ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom return reinterpret_cast<mirror::ArtMethod*>(tmid & ~kTraceMethodActionMask); 126a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 127e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 12862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic TraceAction DecodeTraceAction(uint32_t tmid) { 12962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return static_cast<TraceAction>(tmid & kTraceMethodActionMask); 130a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 131a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 132ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method, 13362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers TraceAction action) { 134ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint32_t tmid = PointerToLowMemUInt32(method) | action; 13562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DCHECK_EQ(method, DecodeTraceMethodId(tmid)); 13662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return tmid; 137e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes} 138e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes 1395ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostd::vector<mirror::ArtMethod*>* Trace::AllocStackTrace() { 1405ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao if (temp_stack_trace_.get() != NULL) { 1415ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao return temp_stack_trace_.release(); 1425ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao } else { 1435ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao return new std::vector<mirror::ArtMethod*>(); 1445ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao } 1455ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 1465ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 1475ce4b178d2483df679e7f718e379305e5d42a300Jeff Haovoid Trace::FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace) { 1485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao stack_trace->clear(); 1495ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao temp_stack_trace_.reset(stack_trace); 1505ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 1515ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 15262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::SetDefaultClockSource(ProfilerClockSource clock_source) { 153e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#if defined(HAVE_POSIX_CLOCKS) 15462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers default_clock_source_ = clock_source; 155e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#else 15662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (clock_source != kProfilerClockSourceWall) { 1575ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao LOG(WARNING) << "Ignoring tracing request to use CPU time."; 15862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 159e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes#endif 160a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 161a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 16262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetTraceVersion(ProfilerClockSource clock_source) { 16362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return (clock_source == kProfilerClockSourceDual) ? kTraceVersionDualClock 16462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers : kTraceVersionSingleClock; 16562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 16662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 16762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic uint16_t GetRecordSize(ProfilerClockSource clock_source) { 16862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return (clock_source == kProfilerClockSourceDual) ? kTraceRecordSizeDualClock 16962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers : kTraceRecordSizeSingleClock; 17062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 17162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 17262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersbool Trace::UseThreadCpuClock() { 17362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return (clock_source_ == kProfilerClockSourceThreadCpu) || 17462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers (clock_source_ == kProfilerClockSourceDual); 17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 17662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 177e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesbool Trace::UseWallClock() { 17862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return (clock_source_ == kProfilerClockSourceWall) || 17962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers (clock_source_ == kProfilerClockSourceDual); 180a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 181a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 182e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughesstatic void MeasureClockOverhead(Trace* trace) { 183e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes if (trace->UseThreadCpuClock()) { 18457dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao Thread::Current()->GetCpuMicroTime(); 185a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 186e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes if (trace->UseWallClock()) { 187a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao MicroTime(); 188a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 189a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 190a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 1915ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao// Compute an average time taken to measure clocks. 1925ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostatic uint32_t GetClockOverheadNanoSeconds(Trace* trace) { 19357dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao Thread* self = Thread::Current(); 19457dac6ed61a0a25c14d4e2fabc84435578d42360Jeff Hao uint64_t start = self->GetCpuMicroTime(); 195a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 196a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao for (int i = 4000; i > 0; i--) { 197e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 198e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 199e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 200e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 201e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 202e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 203e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 204e119a3623ffbd55ff856d4eaac4dc4ef0c90a089Elliott Hughes MeasureClockOverhead(trace); 205a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 206a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 2075ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao uint64_t elapsed_us = self->GetCpuMicroTime() - start; 2085ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao return static_cast<uint32_t>(elapsed_us / 32); 209a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 210a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 211ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 212ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append2LE(uint8_t* buf, uint16_t val) { 2135ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 2145ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 215a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 216a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 217ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 218ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append4LE(uint8_t* buf, uint32_t val) { 2195ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 2205ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 2215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 16); 2225ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 24); 223a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 224a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 225ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes// TODO: put this somewhere with the big-endian equivalent used by JDWP. 226ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughesstatic void Append8LE(uint8_t* buf, uint64_t val) { 2275ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val); 2285ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 8); 2295ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 16); 2305ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 24); 2315ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 32); 2325ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 40); 2335ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 48); 2345ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao *buf++ = static_cast<uint8_t>(val >> 56); 235a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 236a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 2370abc72ebe356c32354b575c48189965a0edc7890Jeff Haostatic void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2380abc72ebe356c32354b575c48189965a0edc7890Jeff Hao BuildStackTraceVisitor build_trace_visitor(thread); 2390abc72ebe356c32354b575c48189965a0edc7890Jeff Hao build_trace_visitor.WalkStack(); 240e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace(); 2410abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Trace* the_trace = reinterpret_cast<Trace*>(arg); 2420abc72ebe356c32354b575c48189965a0edc7890Jeff Hao the_trace->CompareAndUpdateStackTrace(thread, stack_trace); 2430abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 2440abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 2455ce4b178d2483df679e7f718e379305e5d42a300Jeff Haostatic void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg) { 2465ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao thread->SetTraceClockBase(0); 2475ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao std::vector<mirror::ArtMethod*>* stack_trace = thread->GetStackTraceSample(); 2485ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao thread->SetStackTraceSample(NULL); 2495ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao delete stack_trace; 2505ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao} 2515ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao 2520abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid Trace::CompareAndUpdateStackTrace(Thread* thread, 253e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>* stack_trace) { 2540abc72ebe356c32354b575c48189965a0edc7890Jeff Hao CHECK_EQ(pthread_self(), sampling_pthread_); 2555ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao std::vector<mirror::ArtMethod*>* old_stack_trace = thread->GetStackTraceSample(); 2565ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao // Update the thread's stack trace sample. 2575ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao thread->SetStackTraceSample(stack_trace); 258c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao // Read timer clocks to use for all events in this trace. 259c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 260c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 261c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 2625ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao if (old_stack_trace == NULL) { 2635ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao // If there's no previous stack trace sample for this thread, log an entry event for all 2640abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // methods in the trace. 265e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers for (std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin(); 2660abc72ebe356c32354b575c48189965a0edc7890Jeff Hao rit != stack_trace->rend(); ++rit) { 267c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered, 268c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2690abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2700abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } else { 2710abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // If there's a previous stack trace for this thread, diff the traces and emit entry and exit 2720abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // events accordingly. 273e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin(); 274e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin(); 2750abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate bottom-up over both traces until there's a difference between them. 2760abc72ebe356c32354b575c48189965a0edc7890Jeff Hao while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) { 2770abc72ebe356c32354b575c48189965a0edc7890Jeff Hao old_rit++; 2780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao rit++; 2790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate top-down over the old trace until the point where they differ, emitting exit events. 281e2f77e7592842cad5a59e73535b8982c35e156caIan Rogers for (std::vector<mirror::ArtMethod*>::iterator old_it = old_stack_trace->begin(); 2820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao old_it != old_rit.base(); ++old_it) { 283c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited, 284c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2850abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2860abc72ebe356c32354b575c48189965a0edc7890Jeff Hao // Iterate bottom-up over the new trace from the point where they differ, emitting entry events. 2870abc72ebe356c32354b575c48189965a0edc7890Jeff Hao for (; rit != stack_trace->rend(); ++rit) { 288c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered, 289c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 2900abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2915ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao FreeStackTrace(old_stack_trace); 2920abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 2930abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 2940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 2950abc72ebe356c32354b575c48189965a0edc7890Jeff Haovoid* Trace::RunSamplingThread(void* arg) { 2960abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Runtime* runtime = Runtime::Current(); 297ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers intptr_t interval_us = reinterpret_cast<intptr_t>(arg); 2984044bdac490777cbc8a12d467bec675ef8aa6eb1Jeff Hao CHECK_GE(interval_us, 0); 2990abc72ebe356c32354b575c48189965a0edc7890Jeff Hao CHECK(runtime->AttachCurrentThread("Sampling Profiler", true, runtime->GetSystemThreadGroup(), 3000abc72ebe356c32354b575c48189965a0edc7890Jeff Hao !runtime->IsCompiler())); 3010abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 3020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao while (true) { 30323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao usleep(interval_us); 3045ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao ATRACE_BEGIN("Profile sampling"); 3050abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Thread* self = Thread::Current(); 3060abc72ebe356c32354b575c48189965a0edc7890Jeff Hao Trace* the_trace; 3070abc72ebe356c32354b575c48189965a0edc7890Jeff Hao { 3080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao MutexLock mu(self, *Locks::trace_lock_); 3090abc72ebe356c32354b575c48189965a0edc7890Jeff Hao the_trace = the_trace_; 3100abc72ebe356c32354b575c48189965a0edc7890Jeff Hao if (the_trace == NULL) { 3110abc72ebe356c32354b575c48189965a0edc7890Jeff Hao break; 3120abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3130abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3140abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 3150abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetThreadList()->SuspendAll(); 3160abc72ebe356c32354b575c48189965a0edc7890Jeff Hao { 3170abc72ebe356c32354b575c48189965a0edc7890Jeff Hao MutexLock mu(self, *Locks::thread_list_lock_); 3180abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetThreadList()->ForEach(GetSample, the_trace); 3190abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3200abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetThreadList()->ResumeAll(); 3215ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao ATRACE_END(); 3220abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 3230abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 3240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->DetachCurrentThread(); 3250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao return NULL; 3260abc72ebe356c32354b575c48189965a0edc7890Jeff Hao} 3270abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 32862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::Start(const char* trace_filename, int trace_fd, int buffer_size, int flags, 32923009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao bool direct_to_ddms, bool sampling_enabled, int interval_us) { 33062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Thread* self = Thread::Current(); 33162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 33262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(self, *Locks::trace_lock_); 33362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (the_trace_ != NULL) { 33462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace already in progress, ignoring this request"; 33562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return; 33662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 337e343b76af81a005ef64f5e75a555389fd9147dabjeffhao } 33862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 33962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->SuspendAll(); 340a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 3412692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Open trace file if not going directly to ddms. 342700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers std::unique_ptr<File> trace_file; 343a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (!direct_to_ddms) { 344a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (trace_fd < 0) { 3457571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom trace_file.reset(OS::CreateEmptyFile(trace_filename)); 346a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 34762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers trace_file.reset(new File(trace_fd, "tracefile")); 348761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes trace_file->DisableAutoClose(); 349a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 35062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (trace_file.get() == NULL) { 351b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'"; 35262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->ResumeAll(); 35362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ScopedObjectAccess soa(self); 35462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("Unable to open trace file '%s'", trace_filename); 355a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao return; 356a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 357a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 358a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 3592692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Create Trace object. 36062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 36162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(self, *Locks::trace_lock_); 362df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom if (the_trace_ != NULL) { 36362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace already in progress, ignoring this request"; 36462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 36523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao the_trace_ = new Trace(trace_file.release(), buffer_size, flags, sampling_enabled); 3660791adc2249366c50684935a4c42ba5e58bc3746jeffhao 36762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Enable count of allocs if specified in the flags. 36862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if ((flags && kTraceCountAllocs) != 0) { 36962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->SetStatsEnabled(true); 37062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 3712692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 37223009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao 37323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao 37423009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao if (sampling_enabled) { 37523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao CHECK_PTHREAD_CALL(pthread_create, (&sampling_pthread_, NULL, &RunSamplingThread, 37623009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao reinterpret_cast<void*>(interval_us)), 37723009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao "Sampling profiler thread"); 3780abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } else { 3790abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetInstrumentation()->AddListener(the_trace_, 3800abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodEntered | 3810abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodExited | 3820abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodUnwind); 383138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz runtime->GetInstrumentation()->EnableMethodTracing(); 3840abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 38562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 38662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 38762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->ResumeAll(); 3882692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 3892692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 3902692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::Stop() { 39162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime* runtime = Runtime::Current(); 39262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->SuspendAll(); 39362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Trace* the_trace = NULL; 3940abc72ebe356c32354b575c48189965a0edc7890Jeff Hao pthread_t sampling_pthread = 0U; 39562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers { 39662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(Thread::Current(), *Locks::trace_lock_); 39762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (the_trace_ == NULL) { 39862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Trace stop requested, but no trace currently running"; 39962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 40062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers the_trace = the_trace_; 40162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers the_trace_ = NULL; 4020abc72ebe356c32354b575c48189965a0edc7890Jeff Hao sampling_pthread = sampling_pthread_; 4030abc72ebe356c32354b575c48189965a0edc7890Jeff Hao sampling_pthread_ = 0U; 40462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 4052692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao } 40662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (the_trace != NULL) { 40762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers the_trace->FinishTracing(); 4080abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 40923009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao if (the_trace->sampling_enabled_) { 4105ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); 4115ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao runtime->GetThreadList()->ForEach(ClearThreadStackTraceAndClockBase, NULL); 4125ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao } else { 413138dbfc3336e379d74d157086f69a0fbe830089bSebastien Hertz runtime->GetInstrumentation()->DisableMethodTracing(); 4140abc72ebe356c32354b575c48189965a0edc7890Jeff Hao runtime->GetInstrumentation()->RemoveListener(the_trace, 4150abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodEntered | 4160abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodExited | 4170abc72ebe356c32354b575c48189965a0edc7890Jeff Hao instrumentation::Instrumentation::kMethodUnwind); 4180abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 41962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers delete the_trace; 42062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 42162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers runtime->GetThreadList()->ResumeAll(); 4220abc72ebe356c32354b575c48189965a0edc7890Jeff Hao 42323009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao if (sampling_pthread != 0U) { 4240abc72ebe356c32354b575c48189965a0edc7890Jeff Hao CHECK_PTHREAD_CALL(pthread_join, (sampling_pthread, NULL), "sampling thread shutdown"); 4250abc72ebe356c32354b575c48189965a0edc7890Jeff Hao } 4262692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao} 4272692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao 428b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhaovoid Trace::Shutdown() { 42964caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao if (GetMethodTracingMode() != kTracingInactive) { 43062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Stop(); 431b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao } 432b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao} 433b5e81858a47dd7ed051135f6982fbc4e13d0f309jeffhao 43464caa7dcf46ed6139b766dbe77fbd7353899417fJeff HaoTracingMode Trace::GetMethodTracingMode() { 43562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MutexLock mu(Thread::Current(), *Locks::trace_lock_); 43664caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao if (the_trace_ == NULL) { 43764caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao return kTracingInactive; 43864caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao } else if (the_trace_->sampling_enabled_) { 43964caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao return kSampleProfilingActive; 44064caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao } else { 44164caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao return kMethodTracingActive; 44264caa7dcf46ed6139b766dbe77fbd7353899417fJeff Hao } 44362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 444a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 44523009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff HaoTrace::Trace(File* trace_file, int buffer_size, int flags, bool sampling_enabled) 44662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags), 44723009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao sampling_enabled_(sampling_enabled), clock_source_(default_clock_source_), 44823009dca63c1699e28bfeaa8b45ca48fa0e86aceJeff Hao buffer_size_(buffer_size), start_time_(MicroTime()), cur_offset_(0), overflow_(false) { 449a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Set up the beginning of the trace. 45062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint16_t trace_version = GetTraceVersion(clock_source_); 4512692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao memset(buf_.get(), 0, kTraceHeaderLength); 4522692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append4LE(buf_.get(), kTraceMagicValue); 45362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(buf_.get() + 4, trace_version); 4542692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append2LE(buf_.get() + 6, kTraceHeaderLength); 4552692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao Append8LE(buf_.get() + 8, start_time_); 45662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (trace_version >= kTraceVersionDualClock) { 45762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint16_t record_size = GetRecordSize(clock_source_); 45862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(buf_.get() + 16, record_size); 459a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 460a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 4612692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao // Update current offset. 4622692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao cur_offset_ = kTraceHeaderLength; 46362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 46462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 46562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersstatic void DumpBuf(uint8_t* buf, size_t buf_size, ProfilerClockSource clock_source) 46662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 46762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* ptr = buf + kTraceHeaderLength; 46862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* end = buf + buf_size; 469a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 47062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers while (ptr < end) { 47162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24); 472ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method = DecodeTraceMethodId(tmid); 47362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers TraceAction action = DecodeTraceAction(tmid); 47462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action); 47562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ptr += GetRecordSize(clock_source); 47662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 477e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 478e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 4792692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhaovoid Trace::FinishTracing() { 480a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Compute elapsed time. 481a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao uint64_t elapsed = MicroTime() - start_time_; 482a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 483a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao size_t final_offset = cur_offset_; 4845ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao uint32_t clock_overhead_ns = GetClockOverheadNanoSeconds(this); 485a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 4860791adc2249366c50684935a4c42ba5e58bc3746jeffhao if ((flags_ & kTraceCountAllocs) != 0) { 4870791adc2249366c50684935a4c42ba5e58bc3746jeffhao Runtime::Current()->SetStatsEnabled(false); 4880791adc2249366c50684935a4c42ba5e58bc3746jeffhao } 4890791adc2249366c50684935a4c42ba5e58bc3746jeffhao 490ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom std::set<mirror::ArtMethod*> visited_methods; 49162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers GetVisitedMethods(final_offset, &visited_methods); 492a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 493a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao std::ostringstream os; 494a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 495a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cversion\n", kTraceTokenChar); 49662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers os << StringPrintf("%d\n", GetTraceVersion(clock_source_)); 497a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("data-file-overflow=%s\n", overflow_ ? "true" : "false"); 498a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseThreadCpuClock()) { 499a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseWallClock()) { 500a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=dual\n"); 501a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 502a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=thread-cpu\n"); 503a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 504a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 505a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("clock=wall\n"); 506a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 507ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers os << StringPrintf("elapsed-time-usec=%" PRIu64 "\n", elapsed); 50862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers size_t num_records = (final_offset - kTraceHeaderLength) / GetRecordSize(clock_source_); 50962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers os << StringPrintf("num-method-calls=%zd\n", num_records); 5105ce4b178d2483df679e7f718e379305e5d42a300Jeff Hao os << StringPrintf("clock-call-overhead-nsec=%d\n", clock_overhead_ns); 511a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("vm=art\n"); 5120791adc2249366c50684935a4c42ba5e58bc3746jeffhao if ((flags_ & kTraceCountAllocs) != 0) { 5130791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("alloc-count=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_OBJECTS)); 5140791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("alloc-size=%d\n", Runtime::Current()->GetStat(KIND_ALLOCATED_BYTES)); 5150791adc2249366c50684935a4c42ba5e58bc3746jeffhao os << StringPrintf("gc-count=%d\n", Runtime::Current()->GetStat(KIND_GC_INVOCATIONS)); 5160791adc2249366c50684935a4c42ba5e58bc3746jeffhao } 517a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cthreads\n", kTraceTokenChar); 518a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao DumpThreadList(os); 519a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cmethods\n", kTraceTokenChar); 52062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DumpMethodList(os, visited_methods); 521a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao os << StringPrintf("%cend\n", kTraceTokenChar); 522a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 523a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao std::string header(os.str()); 5242692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao if (trace_file_.get() == NULL) { 5257b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes iovec iov[2]; 526a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao iov[0].iov_base = reinterpret_cast<void*>(const_cast<char*>(header.c_str())); 527a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao iov[0].iov_len = header.length(); 5282692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao iov[1].iov_base = buf_.get(); 529a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao iov[1].iov_len = final_offset; 530a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Dbg::DdmSendChunkV(CHUNK_TYPE("MPSE"), iov, 2); 53162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const bool kDumpTraceInfo = false; 53262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (kDumpTraceInfo) { 53362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(INFO) << "Trace sent:\n" << header; 53462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DumpBuf(buf_.get(), final_offset, clock_source_); 53562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 536a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } else { 537a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (!trace_file_->WriteFully(header.c_str(), header.length()) || 5382692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao !trace_file_->WriteFully(buf_.get(), final_offset)) { 5397b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes std::string detail(StringPrintf("Trace data write failed: %s", strerror(errno))); 5407b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes PLOG(ERROR) << detail; 54162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("%s", detail.c_str()); 542a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 543a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 544e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} 545e343b76af81a005ef64f5e75a555389fd9147dabjeffhao 54662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::DexPcMoved(Thread* thread, mirror::Object* this_object, 547ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t new_dex_pc) { 54862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // We're not recorded to listen to this kind of event, so complain. 54962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc; 55062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers}; 55162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 5523f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Trace::FieldRead(Thread* /*thread*/, mirror::Object* this_object, 5533f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field) 5543f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 5553f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz // We're not recorded to listen to this kind of event, so complain. 5563f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz LOG(ERROR) << "Unexpected field read event in tracing " << PrettyMethod(method) << " " << dex_pc; 5573f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 5583f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 5593f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertzvoid Trace::FieldWritten(Thread* /*thread*/, mirror::Object* this_object, 5603f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz mirror::ArtMethod* method, uint32_t dex_pc, mirror::ArtField* field, 5613f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz const JValue& field_value) 5623f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 5633f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz // We're not recorded to listen to this kind of event, so complain. 5643f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz LOG(ERROR) << "Unexpected field write event in tracing " << PrettyMethod(method) << " " << dex_pc; 5653f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz} 5663f52eafe5577b8489f90dc8ed5981b3455206147Sebastien Hertz 56762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodEntered(Thread* thread, mirror::Object* this_object, 568ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t dex_pc) { 569c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 570c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 571c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 572c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodEntered, 573c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 57462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 57562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 57662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::MethodExited(Thread* thread, mirror::Object* this_object, 577ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t dex_pc, 57862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers const JValue& return_value) { 57962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UNUSED(return_value); 580c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 581c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 582c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 583c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodExited, 584c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 58562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 58662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 58751db44a194bafc3810a41164a8b39614f10e79dfSebastien Hertzvoid Trace::MethodUnwind(Thread* thread, mirror::Object* this_object, 588ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* method, uint32_t dex_pc) { 589c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff = 0; 590c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t wall_clock_diff = 0; 591c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao ReadClocks(thread, &thread_clock_diff, &wall_clock_diff); 592c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao LogMethodTraceEvent(thread, method, instrumentation::Instrumentation::kMethodUnwind, 593c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread_clock_diff, wall_clock_diff); 59462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 59562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 59662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::ExceptionCaught(Thread* thread, const ThrowLocation& throw_location, 597ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* catch_method, uint32_t catch_dex_pc, 59862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception_object) 59962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 60062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers LOG(ERROR) << "Unexpected exception caught event in tracing"; 60162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers} 602a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 603c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Haovoid Trace::ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff) { 604c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UseThreadCpuClock()) { 605c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint64_t clock_base = thread->GetTraceClockBase(); 606c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UNLIKELY(clock_base == 0)) { 607c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao // First event, record the base time in the map. 608c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint64_t time = thread->GetCpuMicroTime(); 609c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao thread->SetTraceClockBase(time); 610c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } else { 611c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao *thread_clock_diff = thread->GetCpuMicroTime() - clock_base; 612c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 613c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 614c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao if (UseWallClock()) { 615c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao *wall_clock_diff = MicroTime() - start_time_; 616c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao } 617c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao} 618c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao 619ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method, 620c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao instrumentation::Instrumentation::InstrumentationEvent event, 621c1ff4b79a5d81b849203cc1e1c4a91223e75cfd3Jeff Hao uint32_t thread_clock_diff, uint32_t wall_clock_diff) { 622a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Advance cur_offset_ atomically. 623a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao int32_t new_offset; 624a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao int32_t old_offset; 625a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao do { 626a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao old_offset = cur_offset_; 62762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers new_offset = old_offset + GetRecordSize(clock_source_); 628a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (new_offset > buffer_size_) { 629a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao overflow_ = true; 630a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao return; 631a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 632a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } while (android_atomic_release_cas(old_offset, new_offset, &cur_offset_) != 0); 633a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 63462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers TraceAction action = kTraceMethodEnter; 63562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers switch (event) { 63662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodEntered: 63762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceMethodEnter; 63862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 63962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodExited: 64062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceMethodExit; 64162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 64262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers case instrumentation::Instrumentation::kMethodUnwind: 64362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers action = kTraceUnroll; 64462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers break; 64562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers default: 64662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers UNIMPLEMENTED(FATAL) << "Unexpected event: " << event; 64762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 64862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 64962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint32_t method_value = EncodeTraceMethodAndAction(method, action); 650a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 651a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao // Write data 6522692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao uint8_t* ptr = buf_.get() + old_offset; 65362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Append2LE(ptr, thread->GetTid()); 654a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Append4LE(ptr + 2, method_value); 655a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao ptr += 6; 656a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 657a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseThreadCpuClock()) { 658a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Append4LE(ptr, thread_clock_diff); 659a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao ptr += 4; 660e343b76af81a005ef64f5e75a555389fd9147dabjeffhao } 661a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao if (UseWallClock()) { 662a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Append4LE(ptr, wall_clock_diff); 663a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 664a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 665a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 66662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogersvoid Trace::GetVisitedMethods(size_t buf_size, 667ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom std::set<mirror::ArtMethod*>* visited_methods) { 6682692b573a56cd63a3c8c8aa1636e3766b6d8c9c4jeffhao uint8_t* ptr = buf_.get() + kTraceHeaderLength; 66962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint8_t* end = buf_.get() + buf_size; 670a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 671a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao while (ptr < end) { 67262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24); 673ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* method = DecodeTraceMethodId(tmid); 67462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers visited_methods->insert(method); 67562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ptr += GetRecordSize(clock_source_); 676a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 677a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 678a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 67902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartiervoid Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods) { 68062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers MethodHelper mh; 68102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const auto& method : visited_methods) { 68262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mh.ChangeMethod(method); 6830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers os << StringPrintf("%p\t%s\t%s\t%s\t%s\n", method, 684a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao PrettyDescriptor(mh.GetDeclaringClassDescriptor()).c_str(), mh.GetName(), 685d91d6d6a80748f277fd938a412211e5af28913b1Ian Rogers mh.GetSignature().ToString().c_str(), mh.GetDeclaringClassSourceFile()); 686a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao } 687a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 688a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 689a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaostatic void DumpThread(Thread* t, void* arg) { 690ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes std::ostream& os = *reinterpret_cast<std::ostream*>(arg); 691ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes std::string name; 692ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes t->GetThreadName(name); 693ffb465f23d9549dd591e6aa62e9250523cb00233Elliott Hughes os << t->GetTid() << "\t" << name << "\n"; 694a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 695a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 696a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhaovoid Trace::DumpThreadList(std::ostream& os) { 69781d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Thread* self = Thread::Current(); 69881d425b0b232962441616f8b14f73620bffef5e5Ian Rogers Locks::thread_list_lock_->AssertNotHeld(self); 69981d425b0b232962441616f8b14f73620bffef5e5Ian Rogers MutexLock mu(self, *Locks::thread_list_lock_); 700a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os); 701a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao} 702a9ef3fd82bebc6370fc3ddbb094988feb6c83022jeffhao 703e343b76af81a005ef64f5e75a555389fd9147dabjeffhao} // namespace art 704