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