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

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

Issue 2007343003: Move stack trace extraction code out of TickSample::Init (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: make MSAN happy 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/profiler/tick-sample.h ('k') | no next file » | 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 "src/frames-inl.h" 7 #include "src/frames-inl.h"
8 #include "src/vm-state-inl.h" 8 #include "src/vm-state-inl.h"
9 9
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 namespace { 14 namespace {
15 15
16 bool IsSamePage(byte* ptr1, byte* ptr2) { 16 bool IsSamePage(byte* ptr1, byte* ptr2) {
17 const uint32_t kPageSize = 4096; 17 const uint32_t kPageSize = 4096;
18 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1); 18 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
19 return (reinterpret_cast<uintptr_t>(ptr1) & mask) == 19 return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
20 (reinterpret_cast<uintptr_t>(ptr2) & mask); 20 (reinterpret_cast<uintptr_t>(ptr2) & mask);
21 } 21 }
22 22
23
24 // Check if the code at specified address could potentially be a 23 // Check if the code at specified address could potentially be a
25 // frame setup code. 24 // frame setup code.
26 bool IsNoFrameRegion(Address address) { 25 bool IsNoFrameRegion(Address address) {
27 struct Pattern { 26 struct Pattern {
28 int bytes_count; 27 int bytes_count;
29 byte bytes[8]; 28 byte bytes[8];
30 int offsets[4]; 29 int offsets[4];
31 }; 30 };
32 byte* pc = reinterpret_cast<byte*>(address); 31 byte* pc = reinterpret_cast<byte*>(address);
33 static Pattern patterns[] = { 32 static Pattern patterns[] = {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset)) 69 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
71 return true; 70 return true;
72 } 71 }
73 } 72 }
74 } 73 }
75 return false; 74 return false;
76 } 75 }
77 76
78 } // namespace 77 } // namespace
79 78
80
81 // 79 //
82 // StackTracer implementation 80 // StackTracer implementation
83 // 81 //
84 DISABLE_ASAN void TickSample::Init(Isolate* isolate, 82 DISABLE_ASAN void TickSample::Init(Isolate* isolate,
85 const v8::RegisterState& regs, 83 const v8::RegisterState& regs,
86 RecordCEntryFrame record_c_entry_frame, 84 RecordCEntryFrame record_c_entry_frame,
87 bool update_stats) { 85 bool update_stats) {
88 timestamp = base::TimeTicks::HighResolutionNow(); 86 timestamp = base::TimeTicks::HighResolutionNow();
89 pc = reinterpret_cast<Address>(regs.pc);
90 state = isolate->current_vm_state();
91 this->update_stats = update_stats; 87 this->update_stats = update_stats;
92 88
93 // Avoid collecting traces while doing GC. 89 SampleInfo info;
94 if (state == GC) return; 90 if (GetStackSample(isolate, regs, record_c_entry_frame,
91 reinterpret_cast<void**>(&stack[0]), kMaxFramesCount,
92 &info)) {
93 state = info.vm_state;
94 pc = static_cast<Address>(regs.pc);
95 frames_count = static_cast<unsigned>(info.frames_count);
96 has_external_callback = info.external_callback_entry != nullptr;
97 if (has_external_callback) {
98 external_callback_entry =
99 static_cast<Address>(info.external_callback_entry);
100 } else if (frames_count) {
101 // sp register may point at an arbitrary place in memory, make
102 // sure MSAN doesn't complain about it.
103 MSAN_MEMORY_IS_INITIALIZED(regs.sp, sizeof(Address));
104 // Sample potential return address value for frameless invocation of
105 // stubs (we'll figure out later, if this value makes sense).
106 tos = Memory::Address_at(reinterpret_cast<Address>(regs.sp));
107 } else {
108 tos = nullptr;
109 }
110 } else {
111 // It is executing JS but failed to collect a stack trace.
112 // Mark the sample as spoiled.
113 timestamp = base::TimeTicks();
114 pc = nullptr;
115 }
116 }
117
118 bool TickSample::GetStackSample(Isolate* isolate, const v8::RegisterState& regs,
119 RecordCEntryFrame record_c_entry_frame,
120 void** frames, size_t frames_limit,
121 v8::SampleInfo* sample_info) {
122 sample_info->frames_count = 0;
123 sample_info->vm_state = isolate->current_vm_state();
124 sample_info->external_callback_entry = nullptr;
125 if (sample_info->vm_state == GC) return true;
95 126
96 Address js_entry_sp = isolate->js_entry_sp(); 127 Address js_entry_sp = isolate->js_entry_sp();
97 if (js_entry_sp == 0) return; // Not executing JS now. 128 if (js_entry_sp == 0) return true; // Not executing JS now.
98 129
99 if (pc && IsNoFrameRegion(pc)) { 130 if (regs.pc && IsNoFrameRegion(static_cast<Address>(regs.pc))) {
100 // Can't collect stack. Mark the sample as spoiled. 131 // Can't collect stack.
101 timestamp = base::TimeTicks(); 132 return false;
102 pc = 0;
103 return;
104 } 133 }
105 134
106 ExternalCallbackScope* scope = isolate->external_callback_scope(); 135 ExternalCallbackScope* scope = isolate->external_callback_scope();
107 Address handler = Isolate::handler(isolate->thread_local_top()); 136 Address handler = Isolate::handler(isolate->thread_local_top());
108 // 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
109 // we have already entrered JavaScript again and the external callback 138 // we have already entrered JavaScript again and the external callback
110 // is not the top function. 139 // is not the top function.
111 if (scope && scope->scope_address() < handler) { 140 if (scope && scope->scope_address() < handler) {
112 external_callback_entry = *scope->callback_entrypoint_address(); 141 sample_info->external_callback_entry =
113 has_external_callback = true; 142 *scope->callback_entrypoint_address();
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 } 143 }
123 144
124 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp), 145 SafeStackFrameIterator it(isolate, reinterpret_cast<Address>(regs.fp),
125 reinterpret_cast<Address>(regs.sp), js_entry_sp); 146 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; 147 size_t i = 0;
155 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() && 148 if (record_c_entry_frame == kIncludeCEntryFrame && !it.done() &&
156 it.top_frame_type() == StackFrame::EXIT) { 149 it.top_frame_type() == StackFrame::EXIT) {
157 frames[i++] = isolate->c_function(); 150 frames[i++] = isolate->c_function();
158 } 151 }
159 while (!it.done() && i < frames_limit) { 152 while (!it.done() && i < frames_limit) {
160 if (it.frame()->is_interpreted()) { 153 if (it.frame()->is_interpreted()) {
161 // For interpreted frames use the bytecode array pointer as the pc. 154 // For interpreted frames use the bytecode array pointer as the pc.
162 InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame()); 155 InterpretedFrame* frame = static_cast<InterpretedFrame*>(it.frame());
163 // Since the sampler can interrupt execution at any point the 156 // Since the sampler can interrupt execution at any point the
164 // bytecode_array might be garbage, so don't dereference it. 157 // bytecode_array might be garbage, so don't dereference it.
165 Address bytecode_array = 158 Address bytecode_array =
166 reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag; 159 reinterpret_cast<Address>(frame->GetBytecodeArray()) - kHeapObjectTag;
167 frames[i++] = bytecode_array + BytecodeArray::kHeaderSize + 160 frames[i++] = bytecode_array + BytecodeArray::kHeaderSize +
168 frame->GetBytecodeOffset(); 161 frame->GetBytecodeOffset();
169 } else { 162 } else {
170 frames[i++] = it.frame()->pc(); 163 frames[i++] = it.frame()->pc();
171 } 164 }
172 it.Advance(); 165 it.Advance();
173 } 166 }
174 sample_info->frames_count = i; 167 sample_info->frames_count = i;
168 return true;
175 } 169 }
176 170
177
178 #if defined(USE_SIMULATOR) 171 #if defined(USE_SIMULATOR)
179 bool SimulatorHelper::FillRegisters(Isolate* isolate, 172 bool SimulatorHelper::FillRegisters(Isolate* isolate,
180 v8::RegisterState* state) { 173 v8::RegisterState* state) {
181 Simulator *simulator = isolate->thread_local_top()->simulator_; 174 Simulator *simulator = isolate->thread_local_top()->simulator_;
182 // Check if there is active simulator. 175 // Check if there is active simulator.
183 if (simulator == NULL) return false; 176 if (simulator == NULL) return false;
184 #if V8_TARGET_ARCH_ARM 177 #if V8_TARGET_ARCH_ARM
185 if (!simulator->has_bad_pc()) { 178 if (!simulator->has_bad_pc()) {
186 state->pc = reinterpret_cast<Address>(simulator->get_pc()); 179 state->pc = reinterpret_cast<Address>(simulator->get_pc());
187 } 180 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 // it is not guaranteed to be atomic even when both host and target 217 // it is not guaranteed to be atomic even when both host and target
225 // are of same bitness. 218 // are of same bitness.
226 return false; 219 return false;
227 } 220 }
228 return true; 221 return true;
229 } 222 }
230 #endif // USE_SIMULATOR 223 #endif // USE_SIMULATOR
231 224
232 } // namespace internal 225 } // namespace internal
233 } // namespace v8 226 } // namespace v8
OLDNEW
« no previous file with comments | « src/profiler/tick-sample.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698