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

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

Issue 2105943002: Expose TickSample and its APIs in v8-profiler.h (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 4 years, 5 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/profiler/tick-sample.h ('k') | test/cctest/test-cpu-profiler.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 2013 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/profiler/tick-sample.h" 5 #include "src/profiler/tick-sample.h"
6 6
7 #include "include/v8-profiler.h"
7 #include "src/frames-inl.h" 8 #include "src/frames-inl.h"
9 #include "src/msan.h"
10 #include "src/simulator.h"
8 #include "src/vm-state-inl.h" 11 #include "src/vm-state-inl.h"
9 12
10
11 namespace v8 { 13 namespace v8 {
12 namespace internal {
13 14
14 namespace { 15 namespace {
15 16
16 bool IsSamePage(byte* ptr1, byte* ptr2) { 17 bool IsSamePage(i::byte* ptr1, i::byte* ptr2) {
17 const uint32_t kPageSize = 4096; 18 const uint32_t kPageSize = 4096;
18 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1); 19 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
19 return (reinterpret_cast<uintptr_t>(ptr1) & mask) == 20 return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
20 (reinterpret_cast<uintptr_t>(ptr2) & mask); 21 (reinterpret_cast<uintptr_t>(ptr2) & mask);
21 } 22 }
22 23
23 // Check if the code at specified address could potentially be a 24 // Check if the code at specified address could potentially be a
24 // frame setup code. 25 // frame setup code.
25 bool IsNoFrameRegion(Address address) { 26 bool IsNoFrameRegion(i::Address address) {
26 struct Pattern { 27 struct Pattern {
27 int bytes_count; 28 int bytes_count;
28 byte bytes[8]; 29 i::byte bytes[8];
29 int offsets[4]; 30 int offsets[4];
30 }; 31 };
31 byte* pc = reinterpret_cast<byte*>(address); 32 i::byte* pc = reinterpret_cast<i::byte*>(address);
32 static Pattern patterns[] = { 33 static Pattern patterns[] = {
33 #if V8_HOST_ARCH_IA32 34 #if V8_HOST_ARCH_IA32
34 // push %ebp 35 // push %ebp
35 // mov %esp,%ebp 36 // mov %esp,%ebp
36 {3, {0x55, 0x89, 0xe5}, {0, 1, -1}}, 37 {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
37 // pop %ebp 38 // pop %ebp
38 // ret N 39 // ret N
39 {2, {0x5d, 0xc2}, {0, 1, -1}}, 40 {2, {0x5d, 0xc2}, {0, 1, -1}},
40 // pop %ebp 41 // pop %ebp
41 // ret 42 // ret
(...skipping 30 matching lines...) Expand all
72 } 73 }
73 } 74 }
74 return false; 75 return false;
75 } 76 }
76 77
77 } // namespace 78 } // namespace
78 79
79 // 80 //
80 // StackTracer implementation 81 // StackTracer implementation
81 // 82 //
82 DISABLE_ASAN void TickSample::Init(Isolate* isolate, 83 DISABLE_ASAN void TickSample::Init(Isolate* v8_isolate,
83 const v8::RegisterState& regs, 84 const RegisterState& regs,
84 RecordCEntryFrame record_c_entry_frame, 85 RecordCEntryFrame record_c_entry_frame,
85 bool update_stats) { 86 bool update_stats) {
86 timestamp = base::TimeTicks::HighResolutionNow();
87 this->update_stats = update_stats; 87 this->update_stats = update_stats;
88 88
89 SampleInfo info; 89 SampleInfo info;
90 if (GetStackSample(isolate, regs, record_c_entry_frame, 90 if (GetStackSample(v8_isolate, const_cast<RegisterState&>(regs),
91 reinterpret_cast<void**>(&stack[0]), kMaxFramesCount, 91 record_c_entry_frame, reinterpret_cast<void**>(&stack[0]),
92 &info)) { 92 kMaxFramesCount, &info)) {
93 state = info.vm_state; 93 state = info.vm_state;
94 pc = static_cast<Address>(regs.pc); 94 pc = regs.pc;
95 frames_count = static_cast<unsigned>(info.frames_count); 95 frames_count = static_cast<unsigned>(info.frames_count);
96 has_external_callback = info.external_callback_entry != nullptr; 96 has_external_callback = info.external_callback_entry != nullptr;
97 if (has_external_callback) { 97 if (has_external_callback) {
98 external_callback_entry = 98 external_callback_entry = info.external_callback_entry;
99 static_cast<Address>(info.external_callback_entry);
100 } else if (frames_count) { 99 } else if (frames_count) {
101 // sp register may point at an arbitrary place in memory, make 100 // sp register may point at an arbitrary place in memory, make
102 // sure MSAN doesn't complain about it. 101 // sure MSAN doesn't complain about it.
103 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(Address)); 102 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(void*));
104 // Sample potential return address value for frameless invocation of 103 // Sample potential return address value for frameless invocation of
105 // stubs (we'll figure out later, if this value makes sense). 104 // stubs (we'll figure out later, if this value makes sense).
106 tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp)); 105 tos = i::Memory::Address_at(reinterpret_cast<i::Address>(regs.sp));
107 } else { 106 } else {
108 tos = nullptr; 107 tos = nullptr;
109 } 108 }
110 } else { 109 } else {
111 // It is executing JS but failed to collect a stack trace. 110 // It is executing JS but failed to collect a stack trace.
112 // Mark the sample as spoiled. 111 // Mark the sample as spoiled.
113 timestamp = base::TimeTicks();
114 pc = nullptr; 112 pc = nullptr;
115 } 113 }
116 } 114 }
117 115
118 bool TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs, 116 bool TickSample::GetStackSample(Isolate* v8_isolate, const RegisterState& regs,
119 RecordCEntryFrame record_c_entry_frame, 117 RecordCEntryFrame record_c_entry_frame,
120 void** frames, size_t frames_limit, 118 void** frames, size_t frames_limit,
121 v8::SampleInfo* sample_info) { 119 v8::SampleInfo* sample_info) {
120 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
122 sample_info->frames_count = 0; 121 sample_info->frames_count = 0;
123 sample_info->vm_state = isolate->current_vm_state(); 122 sample_info->vm_state = isolate->current_vm_state();
124 sample_info->external_callback_entry = nullptr; 123 sample_info->external_callback_entry = nullptr;
125 if (sample_info->vm_state == GC) return true; 124 if (sample_info->vm_state == GC) return true;
126 125
127 Address js_entry_sp = isolate->js_entry_sp(); 126 i::Address js_entry_sp = isolate->js_entry_sp();
128 if (js_entry_sp == nullptr) return true; // Not executing JS now. 127 if (js_entry_sp == nullptr) return true; // Not executing JS now.
129 DCHECK(regs.sp); 128 DCHECK(regs.sp);
130 129
131 if (regs.pc && IsNoFrameRegion(static_cast<Address>(regs.pc))) { 130 if (regs.pc && IsNoFrameRegion(static_cast<i::Address>(regs.pc))) {
132 // Can't collect stack. 131 // Can't collect stack.
133 return false; 132 return false;
134 } 133 }
135 134
136 ExternalCallbackScope* scope = isolate->external_callback_scope(); 135 i::ExternalCallbackScope* scope = isolate->external_callback_scope();
137 Address handler = Isolate::handler(isolate->thread_local_top()); 136 i::Address handler = i::Isolate::handler(isolate->thread_local_top());
138 // If there is a handler on top of the external callback scope then 137 // If there is a handler on top of the external callback scope then
139 // we have already entrered JavaScript again and the external callback 138 // we have already entrered JavaScript again and the external callback
140 // is not the top function. 139 // is not the top function.
141 if (scope && scope->scope_address() < handler) { 140 if (scope && scope->scope_address() < handler) {
142 sample_info->external_callback_entry = 141 sample_info->external_callback_entry =
143 *scope->callback_entrypoint_address(); 142 *scope->callback_entrypoint_address();
144 } 143 }
145 144
146 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp), 145 i::SafeStackFrameIterator it(isolate, reinterpret_cast<i::Address>(regs.fp),
147 reinterpret_cast<Address>(regs.sp), js_entry_sp); 146 reinterpret_cast<i::Address>(regs.sp),
147 js_entry_sp);
148 size_t i = 0; 148 size_t i = 0;
149 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() && 149 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
150 (it.top_frame_type() == StackFrame::EXIT || 150 (it.top_frame_type() == internal::StackFrame::EXIT ||
151 it.top_frame_type() == StackFrame::BUILTIN_EXIT)) { 151 it.top_frame_type() == internal::StackFrame::BUILTIN_EXIT)) {
152 frames[i++] = isolate->c_function(); 152 frames[i++] = isolate->c_function();
153 } 153 }
154 while (!it.done() && i < frames_limit) { 154 while (!it.done() && i < frames_limit) {
155 if (it.frame()->is_interpreted()) { 155 if (it.frame()->is_interpreted()) {
156 // For interpreted frames use the bytecode array pointer as the pc. 156 // For interpreted frames use the bytecode array pointer as the pc.
157 InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame()); 157 i::InterpretedFrame* frame =
158 static_cast<i::InterpretedFrame*>(it.frame());
158 // Since the sampler can interrupt execution at any point the 159 // Since the sampler can interrupt execution at any point the
159 // bytecode_array might be garbage, so don't dereference it. 160 // bytecode_array might be garbage, so don't dereference it.
160 Address bytecode_array = 161 i::Address bytecode_array =
161 reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag; 162 reinterpret_cast<i::Address>(frame->GetBytecodeArray()) -
162 frames[i++] = bytecode_array + BytecodeArray::kHeaderSize + 163 i::kHeapObjectTag;
164 frames[i++] = bytecode_array + i::BytecodeArray::kHeaderSize +
163 frame->GetBytecodeOffset(); 165 frame->GetBytecodeOffset();
164 } else { 166 } else {
165 frames[i++] = it.frame()->pc(); 167 frames[i++] = it.frame()->pc();
166 } 168 }
167 it.Advance(); 169 it.Advance();
168 } 170 }
169 sample_info->frames_count = i; 171 sample_info->frames_count = i;
170 return true; 172 return true;
171 } 173 }
172 174
175 namespace internal {
176
177 void TickSample::Init(Isolate* isolate, const v8::RegisterState& state,
178 RecordCEntryFrame record_c_entry_frame,
179 bool update_stats) {
180 v8::TickSample::Init(reinterpret_cast<v8::Isolate*>(isolate), state,
181 record_c_entry_frame, update_stats);
182 if (pc == nullptr) return;
183 timestamp = base::TimeTicks::HighResolutionNow();
184 }
185
173 #if defined(USE_SIMULATOR) 186 #if defined(USE_SIMULATOR)
174 bool SimulatorHelper::FillRegisters(Isolate* isolate, 187 bool SimulatorHelper::FillRegisters(Isolate* isolate,
175 v8::RegisterState* state) { 188 v8::RegisterState* state) {
176 Simulator *simulator = isolate->thread_local_top()->simulator_; 189 Simulator* simulator = isolate->thread_local_top()->simulator_;
177 // Check if there is active simulator. 190 // Check if there is active simulator.
178 if (simulator == NULL) return false; 191 if (simulator == NULL) return false;
179 #if V8_TARGET_ARCH_ARM 192 #if V8_TARGET_ARCH_ARM
180 if (!simulator->has_bad_pc()) { 193 if (!simulator->has_bad_pc()) {
181 state->pc = reinterpret_cast<Address>(simulator->get_pc()); 194 state->pc = reinterpret_cast<Address>(simulator->get_pc());
182 } 195 }
183 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp)); 196 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
184 state->fp = reinterpret_cast<Address>(simulator->get_register( 197 state->fp =
185 Simulator::r11)); 198 reinterpret_cast<Address>(simulator->get_register(Simulator::r11));
186 #elif V8_TARGET_ARCH_ARM64 199 #elif V8_TARGET_ARCH_ARM64
187 state->pc = reinterpret_cast<Address>(simulator->pc()); 200 state->pc = reinterpret_cast<Address>(simulator->pc());
188 state->sp = reinterpret_cast<Address>(simulator->sp()); 201 state->sp = reinterpret_cast<Address>(simulator->sp());
189 state->fp = reinterpret_cast<Address>(simulator->fp()); 202 state->fp = reinterpret_cast<Address>(simulator->fp());
190 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 203 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
191 if (!simulator->has_bad_pc()) { 204 if (!simulator->has_bad_pc()) {
192 state->pc = reinterpret_cast<Address>(simulator->get_pc()); 205 state->pc = reinterpret_cast<Address>(simulator->get_pc());
193 } 206 }
194 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp)); 207 state->sp = reinterpret_cast<Address>(simulator->get_register(Simulator::sp));
195 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp)); 208 state->fp = reinterpret_cast<Address>(simulator->get_register(Simulator::fp));
(...skipping 23 matching lines...) Expand all
219 // it is not guaranteed to be atomic even when both host and target 232 // it is not guaranteed to be atomic even when both host and target
220 // are of same bitness. 233 // are of same bitness.
221 return false; 234 return false;
222 } 235 }
223 return true; 236 return true;
224 } 237 }
225 #endif // USE_SIMULATOR 238 #endif // USE_SIMULATOR
226 239
227 } // namespace internal 240 } // namespace internal
228 } // namespace v8 241 } // namespace v8
OLDNEW
« no previous file with comments | « src/profiler/tick-sample.h ('k') | test/cctest/test-cpu-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698