xref: /aosp_15_r20/art/runtime/trace.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_TRACE_H_
18 #define ART_RUNTIME_TRACE_H_
19 
20 #include <bitset>
21 #include <map>
22 #include <memory>
23 #include <ostream>
24 #include <set>
25 #include <string>
26 #include <unordered_map>
27 #include <vector>
28 
29 #include "base/atomic.h"
30 #include "base/locks.h"
31 #include "base/macros.h"
32 #include "base/mutex.h"
33 #include "base/os.h"
34 #include "base/safe_map.h"
35 #include "class_linker.h"
36 #include "instrumentation.h"
37 #include "runtime_globals.h"
38 #include "thread_pool.h"
39 
40 namespace unix_file {
41 class FdFile;
42 }  // namespace unix_file
43 
44 namespace art HIDDEN {
45 
46 class ArtField;
47 class ArtMethod;
48 class DexFile;
49 class ShadowFrame;
50 class Thread;
51 
52 struct MethodTraceRecord;
53 
54 using DexIndexBitSet = std::bitset<65536>;
55 
56 enum TracingMode {
57   kTracingInactive,
58   kMethodTracingActive,  // Trace activity synchronous with method progress.
59   kSampleProfilingActive,  // Trace activity captured by sampling thread.
60 };
61 std::ostream& operator<<(std::ostream& os, TracingMode rhs);
62 
63 // File format:
64 //     header
65 //     record 0
66 //     record 1
67 //     ...
68 //
69 // Header format:
70 //     u4  magic ('SLOW')
71 //     u2  version
72 //     u2  offset to data
73 //     u8  start date/time in usec
74 //     u2  record size in bytes (version >= 2 only)
75 //     ... padding to 32 bytes
76 //
77 // Record format v1:
78 //     u1  thread ID
79 //     u4  method ID | method action
80 //     u4  time delta since start, in usec
81 //
82 // Record format v2:
83 //     u2  thread ID
84 //     u4  method ID | method action
85 //     u4  time delta since start, in usec
86 //
87 // Record format v3:
88 //     u2  thread ID
89 //     u4  method ID | method action
90 //     u4  time delta since start, in usec
91 //     u4  wall time since start, in usec (when clock == "dual" only)
92 //
93 // 32 bits of microseconds is 70 minutes.
94 //
95 // All values are stored in little-endian order.
96 
97 enum TraceAction {
98     kTraceMethodEnter = 0x00,       // method entry
99     kTraceMethodExit = 0x01,        // method exit
100     kTraceUnroll = 0x02,            // method exited by exception unrolling
101     // 0x03 currently unused
102     kTraceMethodActionMask = 0x03,  // two bits
103 };
104 
105 enum class TraceOutputMode {
106     kFile,
107     kDDMS,
108     kStreaming
109 };
110 
111 // We need 3 entries to store 64-bit timestamp counter as two 32-bit values on 32-bit architectures.
112 static constexpr uint32_t kNumEntriesForWallClock =
113     (kRuntimePointerSize == PointerSize::k64) ? 2 : 3;
114 static constexpr uint32_t kNumEntriesForDualClock = kNumEntriesForWallClock + 1;
115 
116 // These define offsets in bytes for the individual fields of a trace entry. These are used by the
117 // JITed code when storing a trace entry.
118 static constexpr int32_t kMethodOffsetInBytes = 0;
119 static constexpr int32_t kTimestampOffsetInBytes = 1 * static_cast<uint32_t>(kRuntimePointerSize);
120 // On 32-bit architectures we store 64-bit timestamp as two 32-bit values.
121 // kHighTimestampOffsetInBytes is only relevant on 32-bit architectures.
122 static constexpr int32_t kHighTimestampOffsetInBytes =
123     2 * static_cast<uint32_t>(kRuntimePointerSize);
124 
125 static constexpr uintptr_t kMaskTraceAction = ~0b11;
126 
127 // Packet type encoding for the new method tracing format.
128 static constexpr int kThreadInfoHeaderV2 = 0;
129 static constexpr int kMethodInfoHeaderV2 = 1;
130 static constexpr int kEntryHeaderV2 = 2;
131 static constexpr int kSummaryHeaderV2 = 3;
132 
133 // Packet sizes for the new method tracing format.
134 static constexpr uint16_t kTraceHeaderLengthV2 = 32;
135 static constexpr uint16_t kTraceRecordSizeSingleClockV2 = 6;
136 static constexpr uint16_t kTraceRecordSizeDualClockV2 = kTraceRecordSizeSingleClockV2 + 2;
137 static constexpr uint16_t kEntryHeaderSizeV2 = 12;
138 
139 static constexpr uint16_t kTraceVersionSingleClockV2 = 4;
140 static constexpr uint16_t kTraceVersionDualClockV2 = 5;
141 
142 // TODO(mythria): Consider adding checks to guard agaist OOB access for Append*LE methods.
143 // Currently the onus is on the callers to ensure there is sufficient space in the buffer.
144 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append2LE(uint8_t * buf,uint16_t val)145 static inline void Append2LE(uint8_t* buf, uint16_t val) {
146   *buf++ = static_cast<uint8_t>(val);
147   *buf++ = static_cast<uint8_t>(val >> 8);
148 }
149 
150 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append3LE(uint8_t * buf,uint16_t val)151 static inline void Append3LE(uint8_t* buf, uint16_t val) {
152   *buf++ = static_cast<uint8_t>(val);
153   *buf++ = static_cast<uint8_t>(val >> 8);
154   *buf++ = static_cast<uint8_t>(val >> 16);
155 }
156 
157 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append4LE(uint8_t * buf,uint32_t val)158 static inline void Append4LE(uint8_t* buf, uint32_t val) {
159   *buf++ = static_cast<uint8_t>(val);
160   *buf++ = static_cast<uint8_t>(val >> 8);
161   *buf++ = static_cast<uint8_t>(val >> 16);
162   *buf++ = static_cast<uint8_t>(val >> 24);
163 }
164 
165 // TODO: put this somewhere with the big-endian equivalent used by JDWP.
Append8LE(uint8_t * buf,uint64_t val)166 static inline void Append8LE(uint8_t* buf, uint64_t val) {
167   *buf++ = static_cast<uint8_t>(val);
168   *buf++ = static_cast<uint8_t>(val >> 8);
169   *buf++ = static_cast<uint8_t>(val >> 16);
170   *buf++ = static_cast<uint8_t>(val >> 24);
171   *buf++ = static_cast<uint8_t>(val >> 32);
172   *buf++ = static_cast<uint8_t>(val >> 40);
173   *buf++ = static_cast<uint8_t>(val >> 48);
174   *buf++ = static_cast<uint8_t>(val >> 56);
175 }
176 
177 class TraceWriterThreadPool : public ThreadPool {
178  public:
Create(const char * name)179   static TraceWriterThreadPool* Create(const char* name) {
180     TraceWriterThreadPool* pool = new TraceWriterThreadPool(name);
181     pool->CreateThreads();
182     return pool;
183   }
184 
185   uintptr_t* FinishTaskAndClaimBuffer(size_t tid);
186 
187  private:
TraceWriterThreadPool(const char * name)188   explicit TraceWriterThreadPool(const char* name)
189       : ThreadPool(name,
190                    /* num_threads= */ 1,
191                    /* create_peers= */ false,
192                    /* worker_stack_size= */ ThreadPoolWorker::kDefaultStackSize) {}
193 };
194 
195 class TraceWriter {
196  public:
197   TraceWriter(File* trace_file,
198               TraceOutputMode output_mode,
199               TraceClockSource clock_source,
200               size_t buffer_size,
201               int num_trace_buffers,
202               int trace_format_version,
203               uint32_t clock_overhead_ns);
204 
205   // This encodes all the events in the per-thread trace buffer and writes it to the trace file /
206   // buffer. This acquires streaming lock to prevent any other threads writing concurrently. It is
207   // required to serialize these since each method is encoded with a unique id which is assigned
208   // when the method is seen for the first time in the recoreded events. So we need to serialize
209   // these flushes across threads.
210   void FlushBuffer(Thread* thread, bool is_sync, bool free_buffer)
211       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!trace_writer_lock_);
212 
213   // This is called when the per-thread buffer is full and a new entry needs to be recorded. This
214   // returns a pointer to the new buffer where the entries should be recorded.
215   // In streaming mode, we just flush the per-thread buffer. The buffer is flushed asynchronously
216   // on a thread pool worker. This creates a new buffer and updates the per-thread buffer pointer
217   // and returns a pointer to the newly created buffer.
218   // In non-streaming mode, buffers from all threads are flushed to see if there's enough room
219   // in the centralized buffer before recording new entries. We just flush these buffers
220   // synchronously and reuse the existing buffer. Since this mode is mostly deprecated we want to
221   // keep the implementation simple here.
222   uintptr_t* PrepareBufferForNewEntries(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_)
223       REQUIRES(!trace_writer_lock_);
224 
225   // Creates a summary packet which includes some meta information like number of events, clock
226   // overhead, trace version in human readable form. This is used to dump the summary at the end
227   // of tracing..
228   std::string CreateSummary(int flags) REQUIRES(!trace_writer_lock_)
229       REQUIRES_SHARED(Locks::mutator_lock_);
230   // Flushes all per-thread buffer and also write a summary entry.
231   void FinishTracing(int flags, bool flush_entries) REQUIRES(!trace_writer_lock_)
232       REQUIRES_SHARED(Locks::mutator_lock_);
233 
234   void PreProcessTraceForMethodInfos(uintptr_t* buffer,
235                                      size_t num_entries,
236                                      std::unordered_map<ArtMethod*, std::string>& method_infos)
237       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!trace_writer_lock_);
238 
239   // Flush buffer to the file (for streaming) or to the common buffer (for non-streaming). In
240   // non-streaming case it returns false if all the contents couldn't be flushed.
241   void FlushBuffer(uintptr_t* buffer,
242                    size_t num_entries,
243                    size_t tid,
244                    const std::unordered_map<ArtMethod*, std::string>& method_infos)
245       REQUIRES(!trace_writer_lock_);
246 
247   // This is called when we see the first entry from the thread to record the information about the
248   // thread.
249   void RecordThreadInfo(Thread* thread) REQUIRES(!trace_writer_lock_);
250 
251   // Records information about all methods in the newly loaded class in the buffer. If the buffer
252   // doesn't have enough space to record the entry, then it adds a task to flush the buffer
253   // contents and uses a new buffer to record the information.
254   // buffer is the pointer to buffer that is used to record method info and the offset is the
255   // offset in the buffer to start recording method info. If *buffer is nullptr then a new one is
256   // allocated and buffer is updated to point to the newly allocated one.
257   void RecordMethodInfoV2(mirror::Class* klass, uint8_t** buffer, size_t* offset)
258       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!trace_writer_lock_);
259 
HasOverflow()260   bool HasOverflow() { return overflow_; }
GetOutputMode()261   TraceOutputMode GetOutputMode() { return trace_output_mode_; }
GetBufferSize()262   size_t GetBufferSize() { return buffer_size_; }
263 
264   // Performs the initialization for the buffer pool. It marks all buffers as free by storing 0
265   // as the owner tid. This also allocates the buffer pool.
266   void InitializeTraceBuffers();
267 
268   // Releases the trace buffer and signals any waiting threads about a free buffer.
269   void ReleaseBuffer(int index);
270 
271   // Release the trace buffer of the thread. This is called to release the buffer without flushing
272   // the entries. See a comment in ThreadList::Unregister for more detailed explanation.
273   void ReleaseBufferForThread(Thread* self);
274 
275   // Tries to find a free buffer (which has owner of 0) from the pool. If there are no free buffers
276   // then it just waits for a free buffer. To prevent any deadlocks, we only wait if the number of
277   // pending tasks are greater than the number of waiting threads. Allocates a new buffer if it
278   // isn't safe to wait.
279   uintptr_t* AcquireTraceBuffer(size_t tid) REQUIRES_SHARED(Locks::mutator_lock_)
280       REQUIRES(!trace_writer_lock_);
281 
282   // Returns the index corresponding to the start of the current_buffer. We allocate one large
283   // buffer and assign parts of it for each thread.
284   int GetMethodTraceIndex(uintptr_t* current_buffer);
285 
GetTraceFormatVersion()286   int GetTraceFormatVersion() { return trace_format_version_; }
287 
288   // Ensures that there are no threads suspended waiting for a free buffer. It signals threads
289   // waiting for a free buffer and waits for all the threads to respond to the signal.
290   void StopTracing();
291 
292   // Adds a task to write method info to the file. The buffer is already in the
293   // right format and it just adds a new task which takes the ownership of the
294   // buffer and returns a new buffer that can be used. If release is set to true
295   // then it doesn't fetch a new buffer.
296   uint8_t* AddMethodInfoWriteTask(uint8_t* buffer, size_t offset, size_t tid, bool release)
297       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!trace_writer_lock_);
298 
299   // Writes buffer contents to the file.
300   void WriteToFile(uint8_t* buffer, size_t offset);
301 
302  private:
303   void ReadValuesFromRecord(uintptr_t* method_trace_entries,
304                             size_t record_index,
305                             MethodTraceRecord& record,
306                             bool has_thread_cpu_clock,
307                             bool has_wall_clock);
308 
309   void FlushEntriesFormatV2(uintptr_t* method_trace_entries,
310                             size_t tid,
311                             size_t num_records,
312                             size_t* current_index,
313                             uint8_t* init_buffer_ptr) REQUIRES(trace_writer_lock_);
314 
315   void FlushEntriesFormatV1(uintptr_t* method_trace_entries,
316                             size_t tid,
317                             const std::unordered_map<ArtMethod*, std::string>& method_infos,
318                             size_t end_offset,
319                             size_t* current_index,
320                             uint8_t* buffer_ptr) REQUIRES(trace_writer_lock_);
321   // Get a 32-bit id for the method and specify if the method hasn't been seen before. If this is
322   // the first time we see this method record information (like method name, declaring class etc.,)
323   // about the method.
324   std::pair<uint32_t, bool> GetMethodEncoding(ArtMethod* method) REQUIRES(trace_writer_lock_);
325   bool HasMethodEncoding(ArtMethod* method) REQUIRES(trace_writer_lock_);
326 
327   // Get a 16-bit id for the thread. We don't want to use thread ids directly since they can be
328   // more than 16-bit.
329   uint16_t GetThreadEncoding(pid_t thread_id) REQUIRES(trace_writer_lock_);
330 
331   // Get the information about the method.
332   std::string GetMethodLine(const std::string& method_line, uint32_t method_id);
333   std::string GetMethodInfoLine(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
334 
335   // Helper function to record method information when processing the events. These are used by
336   // streaming output mode. Non-streaming modes dump the methods and threads list at the end of
337   // tracing.
338   void RecordMethodInfoV1(const std::string& method_line, uint64_t method_id)
339       REQUIRES(trace_writer_lock_);
340 
341   // Encodes the trace event. This assumes that there is enough space reserved to encode the entry.
342   void EncodeEventEntry(uint8_t* ptr,
343                         uint16_t thread_id,
344                         uint32_t method_index,
345                         TraceAction action,
346                         uint32_t thread_clock_diff,
347                         uint32_t wall_clock_diff) REQUIRES(trace_writer_lock_);
348 
349   // Encodes the header for the events block. This assumes that there is enough space reserved to
350   // encode the entry.
351   void EncodeEventBlockHeader(uint8_t* ptr, uint32_t thread_id, uint32_t num_records)
352       REQUIRES(trace_writer_lock_);
353 
354   // Ensures there is sufficient space in the buffer to record the requested_size. If there is not
355   // enough sufficient space the current contents of the buffer are written to the file and
356   // current_index is reset to 0. This doesn't check if buffer_size is big enough to hold the
357   // requested size.
358   void EnsureSpace(uint8_t* buffer,
359                    size_t* current_index,
360                    size_t buffer_size,
361                    size_t required_size);
362 
363   // Flush tracing buffers from all the threads.
364   void FlushAllThreadBuffers() REQUIRES(!Locks::thread_list_lock_) REQUIRES(!trace_writer_lock_);
365 
366 
367   // Methods to output traced methods and threads.
368   void DumpMethodList(std::ostream& os) REQUIRES_SHARED(Locks::mutator_lock_)
369       REQUIRES(!trace_writer_lock_);
370   void DumpThreadList(std::ostream& os) REQUIRES(!Locks::thread_list_lock_, !trace_writer_lock_);
371 
372   // File to write trace data out to, null if direct to ddms.
373   std::unique_ptr<File> trace_file_;
374 
375   // The kind of output for this tracing.
376   const TraceOutputMode trace_output_mode_;
377 
378   // The clock source for this tracing.
379   const TraceClockSource clock_source_;
380 
381   // Map of thread ids and names. This is used only in non-streaming mode, since we have to dump
382   // information about all threads in one block. In streaming mode, thread info is recorded directly
383   // in the file when we see the first even from this thread.
384   SafeMap<uint16_t, std::string> threads_list_;
385 
386   // Map from ArtMethod* to index.
387   std::unordered_map<ArtMethod*, uint32_t> art_method_id_map_ GUARDED_BY(trace_writer_lock_);
388   uint32_t current_method_index_ = 0;
389 
390   // Map from thread_id to a 16-bit identifier.
391   std::unordered_map<pid_t, uint16_t> thread_id_map_ GUARDED_BY(trace_writer_lock_);
392   uint16_t current_thread_index_;
393 
394   // Buffer used when generating trace data from the raw entries.
395   // In streaming mode, the trace data is flushed to file when the per-thread buffer gets full.
396   // In non-streaming mode, this data is flushed at the end of tracing. If the buffer gets full
397   // we stop tracing and following trace events are ignored. The size of this buffer is
398   // specified by the user in non-streaming mode.
399   std::unique_ptr<uint8_t[]> buf_;
400 
401   // The cur_offset_ into the buf_. Accessed only in SuspendAll scope when flushing data from the
402   // thread local buffers to buf_.
403   size_t cur_offset_ GUARDED_BY(trace_writer_lock_);
404 
405   // Size of buf_.
406   const size_t buffer_size_;
407 
408   // Version of trace output
409   const int trace_format_version_;
410 
411   // Time trace was created.
412   const uint64_t start_time_;
413 
414   // Did we overflow the buffer recording traces?
415   bool overflow_;
416 
417   // Total number of records flushed to file.
418   size_t num_records_;
419 
420   // Clock overhead.
421   const uint32_t clock_overhead_ns_;
422 
423   std::vector<std::atomic<size_t>> owner_tids_;
424   std::unique_ptr<uintptr_t[]> trace_buffer_;
425 
426   Mutex buffer_pool_lock_;
427   ConditionVariable buffer_available_ GUARDED_BY(buffer_pool_lock_);
428   ConditionVariable num_waiters_zero_cond_ GUARDED_BY(buffer_pool_lock_);
429   std::atomic<size_t> num_waiters_for_buffer_;
430   std::atomic<bool> finish_tracing_ = false;
431 
432   // Lock to protect common data structures accessed from multiple threads like
433   // art_method_id_map_, thread_id_map_.
434   Mutex trace_writer_lock_;
435 
436   // Thread pool to flush the trace entries to file.
437   std::unique_ptr<TraceWriterThreadPool> thread_pool_;
438 };
439 
440 // Class for recording event traces. Trace data is either collected
441 // synchronously during execution (TracingMode::kMethodTracingActive),
442 // or by a separate sampling thread (TracingMode::kSampleProfilingActive).
443 class Trace final : public instrumentation::InstrumentationListener, public ClassLoadCallback {
444  public:
445   enum TraceFlag {
446     kTraceCountAllocs = 0x001,
447     kTraceClockSourceWallClock = 0x010,
448     kTraceClockSourceThreadCpu = 0x100,
449   };
450 
451   static const int kFormatV1 = 0;
452   static const int kFormatV2 = 1;
453   static const int kTraceFormatVersionFlagMask = 0b110;
454   static const int kTraceFormatVersionShift = 1;
455 
456   enum class TraceMode {
457     kMethodTracing,
458     kSampling
459   };
460 
461   // Temporary code for debugging b/342768977
462   static std::string GetDebugInformation();
463 
464   static void SetDefaultClockSource(TraceClockSource clock_source);
465 
466   static void Start(const char* trace_filename,
467                     size_t buffer_size,
468                     int flags,
469                     TraceOutputMode output_mode,
470                     TraceMode trace_mode,
471                     int interval_us)
472       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
473                !Locks::trace_lock_);
474   static void Start(int trace_fd,
475                     size_t buffer_size,
476                     int flags,
477                     TraceOutputMode output_mode,
478                     TraceMode trace_mode,
479                     int interval_us)
480       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
481                !Locks::trace_lock_);
482   static void Start(std::unique_ptr<unix_file::FdFile>&& file,
483                     size_t buffer_size,
484                     int flags,
485                     TraceOutputMode output_mode,
486                     TraceMode trace_mode,
487                     int interval_us)
488       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
489                !Locks::trace_lock_);
490   static void StartDDMS(size_t buffer_size,
491                         int flags,
492                         TraceMode trace_mode,
493                         int interval_us)
494       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_,
495                !Locks::trace_lock_);
496 
497   // Stop tracing. This will finish the trace and write it to file/send it via DDMS.
498   static void Stop()
499       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::trace_lock_);
500   // Abort tracing. This will just stop tracing and *not* write/send the collected data.
501   static void Abort()
502       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::trace_lock_);
503   static void Shutdown()
504       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::trace_lock_);
505 
506   static TracingMode GetMethodTracingMode() REQUIRES(!Locks::trace_lock_);
507 
508   // Flush the per-thread buffer. This is called when the thread is about to detach.
509   static void FlushThreadBuffer(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_)
510       REQUIRES(!Locks::trace_lock_) NO_THREAD_SAFETY_ANALYSIS;
511 
512   // Release per-thread buffer without flushing any entries. This is used when a new trace buffer is
513   // allocated while the thread is terminating. See ThreadList::Unregister for more details.
514   static void ReleaseThreadBuffer(Thread* thread)
515       REQUIRES(!Locks::trace_lock_) NO_THREAD_SAFETY_ANALYSIS;
516 
517   // Removes any listeners installed for method tracing. This is used in non-streaming case
518   // when we no longer record any events once the buffer is full. In other cases listeners are
519   // removed only when tracing stops. This is expected to be called in SuspendAll scope.
520   static void RemoveListeners() REQUIRES(Locks::mutator_lock_);
521 
522   void MeasureClockOverhead();
523   uint32_t GetClockOverheadNanoSeconds();
524 
525   void CompareAndUpdateStackTrace(Thread* thread, std::vector<ArtMethod*>* stack_trace)
526       REQUIRES_SHARED(Locks::mutator_lock_);
527 
528   // InstrumentationListener implementation.
529   void MethodEntered(Thread* thread, ArtMethod* method)
530       REQUIRES_SHARED(Locks::mutator_lock_) override;
531   void MethodExited(Thread* thread,
532                     ArtMethod* method,
533                     instrumentation::OptionalFrame frame,
534                     JValue& return_value) REQUIRES_SHARED(Locks::mutator_lock_) override;
535   void MethodUnwind(Thread* thread, ArtMethod* method, uint32_t dex_pc)
536       REQUIRES_SHARED(Locks::mutator_lock_) override;
537   void DexPcMoved(Thread* thread,
538                   Handle<mirror::Object> this_object,
539                   ArtMethod* method,
540                   uint32_t new_dex_pc) REQUIRES_SHARED(Locks::mutator_lock_) override;
541   void FieldRead(Thread* thread,
542                  Handle<mirror::Object> this_object,
543                  ArtMethod* method,
544                  uint32_t dex_pc,
545                  ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) override;
546   void FieldWritten(Thread* thread,
547                     Handle<mirror::Object> this_object,
548                     ArtMethod* method,
549                     uint32_t dex_pc,
550                     ArtField* field,
551                     const JValue& field_value) REQUIRES_SHARED(Locks::mutator_lock_) override;
552   void ExceptionThrown(Thread* thread, Handle<mirror::Throwable> exception_object)
553       REQUIRES_SHARED(Locks::mutator_lock_) override;
554   void ExceptionHandled(Thread* thread, Handle<mirror::Throwable> exception_object)
555       REQUIRES_SHARED(Locks::mutator_lock_) override;
556   void Branch(Thread* thread, ArtMethod* method, uint32_t dex_pc, int32_t dex_pc_offset)
557       REQUIRES_SHARED(Locks::mutator_lock_) override;
558   void WatchedFramePop(Thread* thread, const ShadowFrame& frame)
559       REQUIRES_SHARED(Locks::mutator_lock_) override;
560 
561   // ClassLoadCallback implementation
ClassLoad(Handle<mirror::Class> klass)562   void ClassLoad([[maybe_unused]] Handle<mirror::Class> klass)
563       REQUIRES_SHARED(Locks::mutator_lock_) override {}
564   void ClassPrepare(Handle<mirror::Class> temp_klass, Handle<mirror::Class> klass)
565       REQUIRES_SHARED(Locks::mutator_lock_) override;
566 
GetClockSource()567   TraceClockSource GetClockSource() { return clock_source_; }
568 
569   // Reuse an old stack trace if it exists, otherwise allocate a new one.
570   static std::vector<ArtMethod*>* AllocStackTrace();
571   // Clear and store an old stack trace for later use.
572   static void FreeStackTrace(std::vector<ArtMethod*>* stack_trace);
573 
574   static TraceOutputMode GetOutputMode() REQUIRES(!Locks::trace_lock_);
575   static TraceMode GetMode() REQUIRES(!Locks::trace_lock_);
576   static size_t GetBufferSize() REQUIRES(!Locks::trace_lock_);
577   static int GetFlags() REQUIRES(!Locks::trace_lock_);
578   static int GetIntervalInMillis() REQUIRES(!Locks::trace_lock_);
579 
580   // Used by class linker to prevent class unloading.
581   static bool IsTracingEnabled() REQUIRES(!Locks::trace_lock_);
582 
583   // Used by the profiler to see if there is any ongoing tracing.
584   static bool IsTracingEnabledLocked() REQUIRES(Locks::trace_lock_);
585 
586   // Callback for each class prepare event to record information about the newly created methods.
587   static void ClassPrepare(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
588 
GetTraceWriter()589   TraceWriter* GetTraceWriter() { return trace_writer_.get(); }
590 
591  private:
592   Trace(File* trace_file,
593         size_t buffer_size,
594         int flags,
595         TraceOutputMode output_mode,
596         TraceMode trace_mode);
597 
598   // The sampling interval in microseconds is passed as an argument.
599   static void* RunSamplingThread(void* arg) REQUIRES(!Locks::trace_lock_);
600 
601   static void StopTracing(bool flush_entries)
602       REQUIRES(!Locks::mutator_lock_, !Locks::thread_list_lock_, !Locks::trace_lock_)
603       // There is an annoying issue with static functions that create a new object and call into
604       // that object that causes them to not be able to tell that we don't currently hold the lock.
605       // This causes the negative annotations to incorrectly have a false positive. TODO: Figure out
606       // how to annotate this.
607       NO_THREAD_SAFETY_ANALYSIS;
608 
609   void ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint64_t* timestamp_counter);
610 
611   void LogMethodTraceEvent(Thread* thread,
612                            ArtMethod* method,
613                            TraceAction action,
614                            uint32_t thread_clock_diff,
615                            uint64_t timestamp_counter) REQUIRES_SHARED(Locks::mutator_lock_);
616 
617   // Singleton instance of the Trace or null when no method tracing is active.
618   static Trace* the_trace_ GUARDED_BY(Locks::trace_lock_);
619 
620   // The default profiler clock source.
621   static TraceClockSource default_clock_source_;
622 
623   // Sampling thread, non-zero when sampling.
624   static pthread_t sampling_pthread_;
625 
626   // Used to remember an unused stack trace to avoid re-allocation during sampling.
627   static std::unique_ptr<std::vector<ArtMethod*>> temp_stack_trace_;
628 
629   // Flags enabling extra tracing of things such as alloc counts.
630   const int flags_;
631 
632   // The tracing method.
633   const TraceMode trace_mode_;
634 
635   const TraceClockSource clock_source_;
636 
637   // Sampling profiler sampling interval.
638   int interval_us_;
639 
640   // A flag to indicate to the sampling thread whether to stop tracing
641   bool stop_tracing_;
642 
643   std::unique_ptr<TraceWriter> trace_writer_;
644 
645   DISALLOW_COPY_AND_ASSIGN(Trace);
646 };
647 
648 }  // namespace art
649 
650 #endif  // ART_RUNTIME_TRACE_H_
651