Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: src/perf-jit.cc

Issue 1993653003: Initial support for emitting unwinding information in perf jitdump. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Enable with --perf-prof-unwinding-info. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/perf-jit.h ('k') | src/ppc/assembler-ppc.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 10 matching lines...) Expand all
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "src/perf-jit.h" 28 #include "src/perf-jit.h"
29 29
30 #include "src/assembler.h" 30 #include "src/assembler.h"
31 #include "src/eh-frame.h"
31 #include "src/objects-inl.h" 32 #include "src/objects-inl.h"
32 33
33 #if V8_OS_LINUX 34 #if V8_OS_LINUX
34 #include <fcntl.h> 35 #include <fcntl.h>
35 #include <sys/mman.h> 36 #include <sys/mman.h>
36 #include <unistd.h> 37 #include <unistd.h>
37 #endif // V8_OS_LINUX 38 #endif // V8_OS_LINUX
38 39
39 namespace v8 { 40 namespace v8 {
40 namespace internal { 41 namespace internal {
41 42
42 #if V8_OS_LINUX 43 #if V8_OS_LINUX
43 44
44 struct PerfJitHeader { 45 struct PerfJitHeader {
45 uint32_t magic_; 46 uint32_t magic_;
46 uint32_t version_; 47 uint32_t version_;
47 uint32_t size_; 48 uint32_t size_;
48 uint32_t elf_mach_target_; 49 uint32_t elf_mach_target_;
49 uint32_t reserved_; 50 uint32_t reserved_;
50 uint32_t process_id_; 51 uint32_t process_id_;
51 uint64_t time_stamp_; 52 uint64_t time_stamp_;
52 uint64_t flags_; 53 uint64_t flags_;
53 54
54 static const uint32_t kMagic = 0x4A695444; 55 static const uint32_t kMagic = 0x4A695444;
55 static const uint32_t kVersion = 1; 56 static const uint32_t kVersion = 1;
56 }; 57 };
57 58
58 struct PerfJitBase { 59 struct PerfJitBase {
59 enum PerfJitEvent { kLoad = 0, kMove = 1, kDebugInfo = 2, kClose = 3 }; 60 enum PerfJitEvent {
61 kLoad = 0,
62 kMove = 1,
63 kDebugInfo = 2,
64 kClose = 3,
65 kUnwindingInfo = 4
66 };
60 67
61 uint32_t event_; 68 uint32_t event_;
62 uint32_t size_; 69 uint32_t size_;
63 uint64_t time_stamp_; 70 uint64_t time_stamp_;
64 }; 71 };
65 72
66 struct PerfJitCodeLoad : PerfJitBase { 73 struct PerfJitCodeLoad : PerfJitBase {
67 uint32_t process_id_; 74 uint32_t process_id_;
68 uint32_t thread_id_; 75 uint32_t thread_id_;
69 uint64_t vma_; 76 uint64_t vma_;
70 uint64_t code_address_; 77 uint64_t code_address_;
71 uint64_t code_size_; 78 uint64_t code_size_;
72 uint64_t code_id_; 79 uint64_t code_id_;
73 }; 80 };
74 81
75 struct PerfJitDebugEntry { 82 struct PerfJitDebugEntry {
76 uint64_t address_; 83 uint64_t address_;
77 int line_number_; 84 int line_number_;
78 int column_; 85 int column_;
79 // Followed by null-terminated name or \0xff\0 if same as previous. 86 // Followed by null-terminated name or \0xff\0 if same as previous.
80 }; 87 };
81 88
82 struct PerfJitCodeDebugInfo : PerfJitBase { 89 struct PerfJitCodeDebugInfo : PerfJitBase {
83 uint64_t address_; 90 uint64_t address_;
84 uint64_t entry_count_; 91 uint64_t entry_count_;
85 // Followed by entry_count_ instances of PerfJitDebugEntry. 92 // Followed by entry_count_ instances of PerfJitDebugEntry.
86 }; 93 };
87 94
95 struct PerfJitCodeUnwindingInfo : PerfJitBase {
96 uint64_t unwinding_size_;
97 uint64_t eh_frame_hdr_size_;
98 uint64_t mapped_size_;
99 // Followed by size_ - sizeof(PerfJitCodeUnwindingInfo) bytes of data.
100 };
101
88 const char PerfJitLogger::kFilenameFormatString[] = "./jit-%d.dump"; 102 const char PerfJitLogger::kFilenameFormatString[] = "./jit-%d.dump";
89 103
90 // Extra padding for the PID in the filename 104 // Extra padding for the PID in the filename
91 const int PerfJitLogger::kFilenameBufferPadding = 16; 105 const int PerfJitLogger::kFilenameBufferPadding = 16;
92 106
93 base::LazyRecursiveMutex PerfJitLogger::file_mutex_; 107 base::LazyRecursiveMutex PerfJitLogger::file_mutex_;
94 // The following static variables are protected by PerfJitLogger::file_mutex_. 108 // The following static variables are protected by PerfJitLogger::file_mutex_.
95 uint64_t PerfJitLogger::reference_count_ = 0; 109 uint64_t PerfJitLogger::reference_count_ = 0;
96 void* PerfJitLogger::marker_address_ = nullptr; 110 void* PerfJitLogger::marker_address_ = nullptr;
97 uint64_t PerfJitLogger::code_index_ = 0; 111 uint64_t PerfJitLogger::code_index_ = 0;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 // Debug info has to be emitted first. 211 // Debug info has to be emitted first.
198 if (FLAG_perf_prof_debug_info && shared != nullptr) { 212 if (FLAG_perf_prof_debug_info && shared != nullptr) {
199 LogWriteDebugInfo(code, shared); 213 LogWriteDebugInfo(code, shared);
200 } 214 }
201 215
202 const char* code_name = name; 216 const char* code_name = name;
203 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start()); 217 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start());
204 uint32_t code_size = code->is_crankshafted() ? code->safepoint_table_offset() 218 uint32_t code_size = code->is_crankshafted() ? code->safepoint_table_offset()
205 : code->instruction_size(); 219 : code->instruction_size();
206 220
221 // Unwinding info comes right after debug info.
222 if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(code);
223
207 static const char string_terminator[] = "\0"; 224 static const char string_terminator[] = "\0";
208 225
209 PerfJitCodeLoad code_load; 226 PerfJitCodeLoad code_load;
210 code_load.event_ = PerfJitCodeLoad::kLoad; 227 code_load.event_ = PerfJitCodeLoad::kLoad;
211 code_load.size_ = sizeof(code_load) + length + 1 + code_size; 228 code_load.size_ = sizeof(code_load) + length + 1 + code_size;
212 code_load.time_stamp_ = GetTimestamp(); 229 code_load.time_stamp_ = GetTimestamp();
213 code_load.process_id_ = 230 code_load.process_id_ =
214 static_cast<uint32_t>(base::OS::GetCurrentProcessId()); 231 static_cast<uint32_t>(base::OS::GetCurrentProcessId());
215 code_load.thread_id_ = static_cast<uint32_t>(base::OS::GetCurrentThreadId()); 232 code_load.thread_id_ = static_cast<uint32_t>(base::OS::GetCurrentThreadId());
216 code_load.vma_ = 0x0; // Our addresses are absolute. 233 code_load.vma_ = 0x0; // Our addresses are absolute.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 entry.address_ = reinterpret_cast<uint64_t>(it.rinfo()->pc()); 313 entry.address_ = reinterpret_cast<uint64_t>(it.rinfo()->pc());
297 entry.line_number_ = line_number; 314 entry.line_number_ = line_number;
298 entry.column_ = column_offset; 315 entry.column_ = column_offset;
299 LogWriteBytes(reinterpret_cast<const char*>(&entry), sizeof(entry)); 316 LogWriteBytes(reinterpret_cast<const char*>(&entry), sizeof(entry));
300 LogWriteBytes(name_string.get(), name_length + 1); 317 LogWriteBytes(name_string.get(), name_length + 1);
301 } 318 }
302 char padding_bytes[] = "\0\0\0\0\0\0\0\0"; 319 char padding_bytes[] = "\0\0\0\0\0\0\0\0";
303 LogWriteBytes(padding_bytes, padding); 320 LogWriteBytes(padding_bytes, padding);
304 } 321 }
305 322
323 void PerfJitLogger::LogWriteUnwindingInfo(Code* code) {
324 EhFrameHdr eh_frame_hdr(code);
325
326 PerfJitCodeUnwindingInfo unwinding_info_header;
327 unwinding_info_header.event_ = PerfJitCodeLoad::kUnwindingInfo;
328 unwinding_info_header.time_stamp_ = GetTimestamp();
329 unwinding_info_header.eh_frame_hdr_size_ = EhFrameHdr::kRecordSize;
330
331 if (code->has_unwinding_info()) {
332 unwinding_info_header.unwinding_size_ = code->unwinding_info_size();
333 unwinding_info_header.mapped_size_ = unwinding_info_header.unwinding_size_;
334 } else {
335 unwinding_info_header.unwinding_size_ = EhFrameHdr::kRecordSize;
336 unwinding_info_header.mapped_size_ = 0;
337 }
338
339 int content_size = static_cast<int>(sizeof(unwinding_info_header) +
340 unwinding_info_header.unwinding_size_);
341 int padding_size = RoundUp(content_size, 8) - content_size;
342 unwinding_info_header.size_ = content_size + padding_size;
343
344 LogWriteBytes(reinterpret_cast<const char*>(&unwinding_info_header),
345 sizeof(unwinding_info_header));
346
347 if (code->has_unwinding_info()) {
348 // The last EhFrameHdr::kRecordSize bytes were a placeholder for the header.
349 // Discard them and write the actual eh_frame_hdr (below).
350 DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize);
351 LogWriteBytes(reinterpret_cast<const char*>(code->unwinding_info_start()),
352 code->unwinding_info_size() - EhFrameHdr::kRecordSize);
353 }
354
355 LogWriteBytes(reinterpret_cast<const char*>(&eh_frame_hdr),
356 EhFrameHdr::kRecordSize);
357
358 char padding_bytes[] = "\0\0\0\0\0\0\0\0";
359 DCHECK_LT(padding_size, sizeof(padding_bytes));
360 LogWriteBytes(padding_bytes, padding_size);
361 }
362
306 void PerfJitLogger::CodeMoveEvent(AbstractCode* from, Address to) { 363 void PerfJitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
307 // Code relocation not supported. 364 // Code relocation not supported.
308 UNREACHABLE(); 365 UNREACHABLE();
309 } 366 }
310 367
311 void PerfJitLogger::LogWriteBytes(const char* bytes, int size) { 368 void PerfJitLogger::LogWriteBytes(const char* bytes, int size) {
312 size_t rv = fwrite(bytes, 1, size, perf_output_handle_); 369 size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
313 DCHECK(static_cast<size_t>(size) == rv); 370 DCHECK(static_cast<size_t>(size) == rv);
314 USE(rv); 371 USE(rv);
315 } 372 }
(...skipping 11 matching lines...) Expand all
327 header.time_stamp_ = 384 header.time_stamp_ =
328 static_cast<uint64_t>(base::OS::TimeCurrentMillis() * 1000.0); 385 static_cast<uint64_t>(base::OS::TimeCurrentMillis() * 1000.0);
329 header.flags_ = 0; 386 header.flags_ = 0;
330 387
331 LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header)); 388 LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
332 } 389 }
333 390
334 #endif // V8_OS_LINUX 391 #endif // V8_OS_LINUX
335 } // namespace internal 392 } // namespace internal
336 } // namespace v8 393 } // namespace v8
OLDNEW
« no previous file with comments | « src/perf-jit.h ('k') | src/ppc/assembler-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698