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

Side by Side Diff: src/profiler/tick-sample.cc

Issue 1952393002: Split TickSample and Sampler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 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
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/profiler/tick-sample.h"
6
7 #include "src/frames-inl.h"
8 #include "src/vm-state-inl.h"
9
10
11 namespace v8 {
12 namespace internal {
13
14 namespace {
15
16 bool IsSamePage(byte* ptr1, byte* ptr2) {
17 const uint32_t kPageSize = 4096;
18 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
19 return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
20 (reinterpret_cast<uintptr_t>(ptr2) & mask);
21 }
22
23
24 // Check if the code at specified address could potentially be a
25 // frame setup code.
26 bool IsNoFrameRegion(Address address) {
27 struct Pattern {
28 int bytes_count;
29 byte bytes[8];
30 int offsets[4];
31 };
32 byte* pc = reinterpret_cast<byte*>(address);
33 static Pattern patterns[] = {
34 #if V8_HOST_ARCH_IA32
35 // push %ebp
36 // mov %esp,%ebp
37 {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
38 // pop %ebp
39 // ret N
40 {2, {0x5d, 0xc2}, {0, 1, -1}},
41 // pop %ebp
42 // ret
43 {2, {0x5d, 0xc3}, {0, 1, -1}},
44 #elif V8_HOST_ARCH_X64
45 // pushq %rbp
46 // movq %rsp,%rbp
47 {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
48 // popq %rbp
49 // ret N
50 {2, {0x5d, 0xc2}, {0, 1, -1}},
51 // popq %rbp
52 // ret
53 {2, {0x5d, 0xc3}, {0, 1, -1}},
54 #endif
55 {0, {}, {}}
56 };
57 for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
58 for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
59 int offset = *offset_ptr;
60 if (!offset || IsSamePage(pc, pc - offset)) {
61 MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
62 if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
63 return true;
64 } else {
65 // It is not safe to examine bytes on another page as it might not be
66 // allocated thus causing a SEGFAULT.
67 // Check the pattern part that's on the same page and
68 // pessimistically assume it could be the entire pattern match.
69 MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
70 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
71 return true;
72 }
73 }
74 }
75 return false;
76 }
77
78 } // namespace
79
80
81 //
82 // StackTracer implementation
83 //
84 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
85 const v8::RegisterState& regs,
86 RecordCEntryFrame record_c_entry_frame,
87 bool update_stats) {
88 timestamp = base::TimeTicks::HighResolutionNow();
89 pc = reinterpret_cast<Address>(regs.pc);
90 state = isolate->current_vm_state();
91 this->update_stats = update_stats;
92
93 // Avoid collecting traces while doing GC.
94 if (state == GC) return;
95
96 Address js_entry_sp = isolate->js_entry_sp();
97 if (js_entry_sp == 0) return; // Not executing JS now.
98
99 if (pc && IsNoFrameRegion(pc)) {
100 // Can't collect stack. Mark the sample as spoiled.
101 timestamp = base::TimeTicks();
102 pc = 0;
103 return;
104 }
105
106 ExternalCallbackScope* scope = isolate->external_callback_scope();
107 Address handler = Isolate::handler(isolate->thread_local_top());
108 // If there is a handler on top of the external callback scope then
109 // we have already entrered JavaScript again and the external callback
110 // is not the top function.
111 if (scope && scope->scope_address() < handler) {
112 external_callback_entry = *scope->callback_entrypoint_address();
113 has_external_callback = true;
114 } else {
115 // sp register may point at an arbitrary place in memory, make
116 // sure MSAN doesn't complain about it.
117 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(Address));
118 // Sample potential return address value for frameless invocation of
119 // stubs (we'll figure out later, if this value makes sense).
120 tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
121 has_external_callback = false;
122 }
123
124 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
125 reinterpret_cast<Address>(regs.sp), js_entry_sp);
126 top_frame_type = it.top_frame_type();
127
128 SampleInfo info;
129 GetStackSample(isolate, regs, record_c_entry_frame,
130 reinterpret_cast<void**>(&stack[0]), kMaxFramesCount, &info);
131 frames_count = static_cast<unsigned>(info.frames_count);
132 if (!frames_count) {
133 // It is executing JS but failed to collect a stack trace.
134 // Mark the sample as spoiled.
135 timestamp = base::TimeTicks();
136 pc = 0;
137 }
138 }
139
140
141 void TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
142 RecordCEntryFrame record_c_entry_frame,
143 void** frames, size_t frames_limit,
144 v8::SampleInfo* sample_info) {
145 sample_info->frames_count = 0;
146 sample_info->vm_state = isolate->current_vm_state();
147 if (sample_info->vm_state == GC) return;
148
149 Address js_entry_sp = isolate->js_entry_sp();
150 if (js_entry_sp == 0) return; // Not executing JS now.
151
152 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
153 reinterpret_cast<Address>(regs.sp), js_entry_sp);
154 size_t i = 0;
155 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
156 it.top_frame_type() == StackFrame::EXIT) {
157 frames[i++] = isolate->c_function();
158 }
159 while (!it.done() && i < frames_limit) {
160 if (it.frame()->is_interpreted()) {
161 // For interpreted frames use the bytecode array pointer as the pc.
162 InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
163 // Since the sampler can interrupt execution at any point the
164 // bytecode_array might be garbage, so don't dereference it.
165 Address bytecode_array =
166 reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
167 frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
168 frame->GetBytecodeOffset();
169 } else {
170 frames[i++] = it.frame()->pc();
171 }
172 it.Advance();
173 }
174 sample_info->frames_count = i;
175 }
176
177
178 } // namespace internal
179 } // namespace v8
OLDNEW
« src/profiler/sampler.h ('K') | « src/profiler/tick-sample.h ('k') | src/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698