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

Side by Side Diff: src/sampler.cc

Issue 1348533005: Reland of Make profiler no frame region detection code more robust [ia86/x64] (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 3 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 | « no previous file | 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/sampler.h" 5 #include "src/sampler.h"
6 6
7 #if V8_OS_POSIX && !V8_OS_CYGWIN 7 #if V8_OS_POSIX && !V8_OS_CYGWIN
8 8
9 #define USE_SIGNALS 9 #define USE_SIGNALS
10 10
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {} 166 PlatformDataCommon() : profiled_thread_id_(ThreadId::Current()) {}
167 ThreadId profiled_thread_id() { return profiled_thread_id_; } 167 ThreadId profiled_thread_id() { return profiled_thread_id_; }
168 168
169 protected: 169 protected:
170 ~PlatformDataCommon() {} 170 ~PlatformDataCommon() {}
171 171
172 private: 172 private:
173 ThreadId profiled_thread_id_; 173 ThreadId profiled_thread_id_;
174 }; 174 };
175 175
176
177 bool IsSamePage(byte* ptr1, byte* ptr2) {
178 const uint32_t kPageSize = 4096;
179 uintptr_t mask = ~static_cast<uintptr_t>(kPageSize - 1);
180 return (reinterpret_cast<uintptr_t>(ptr1) & mask) ==
181 (reinterpret_cast<uintptr_t>(ptr2) & mask);
182 }
183
184
185 // Check if the code at specified address could potentially be a
186 // frame setup code.
187 bool IsNoFrameRegion(Address address) {
188 struct Pattern {
189 int bytes_count;
190 byte bytes[8];
191 int offsets[4];
192 };
193 byte* pc = reinterpret_cast<byte*>(address);
194 static Pattern patterns[] = {
195 #if V8_HOST_ARCH_IA32
196 // push %ebp
197 // mov %esp,%ebp
198 {3, {0x55, 0x89, 0xe5}, {0, 1, -1}},
199 // pop %ebp
200 // ret N
201 {2, {0x5d, 0xc2}, {0, 1, -1}},
202 // pop %ebp
203 // ret
204 {2, {0x5d, 0xc3}, {0, 1, -1}},
205 #elif V8_HOST_ARCH_X64
206 // pushq %rbp
207 // movq %rsp,%rbp
208 {4, {0x55, 0x48, 0x89, 0xe5}, {0, 1, -1}},
209 // popq %rbp
210 // ret N
211 {2, {0x5d, 0xc2}, {0, 1, -1}},
212 // popq %rbp
213 // ret
214 {2, {0x5d, 0xc3}, {0, 1, -1}},
215 #endif
216 {0, {}, {}}
217 };
218 for (Pattern* pattern = patterns; pattern->bytes_count; ++pattern) {
219 for (int* offset_ptr = pattern->offsets; *offset_ptr != -1; ++offset_ptr) {
220 int offset = *offset_ptr;
221 if (!offset || IsSamePage(pc, pc - offset)) {
222 MSAN_MEMORY_IS_INITIALIZED(pc - offset, pattern->bytes_count);
223 if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
224 return true;
225 } else {
226 // It is not safe to examine bytes on another page as it might not be
227 // allocated thus causing a SEGFAULT.
228 // Check the pattern part that's on the same page and
229 // pessimistically assume it could be the entire pattern match.
230 MSAN_MEMORY_IS_INITIALIZED(pc, pattern->bytes_count - offset);
231 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
232 return true;
233 }
234 }
235 }
236 return false;
237 }
238
176 } // namespace 239 } // namespace
177 240
178 #if defined(USE_SIGNALS) 241 #if defined(USE_SIGNALS)
179 242
180 class Sampler::PlatformData : public PlatformDataCommon { 243 class Sampler::PlatformData : public PlatformDataCommon {
181 public: 244 public:
182 PlatformData() : vm_tid_(pthread_self()) {} 245 PlatformData() : vm_tid_(pthread_self()) {}
183 pthread_t vm_tid() const { return vm_tid_; } 246 pthread_t vm_tid() const { return vm_tid_; }
184 247
185 private: 248 private:
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 class SimulatorHelper { 288 class SimulatorHelper {
226 public: 289 public:
227 inline bool Init(Isolate* isolate) { 290 inline bool Init(Isolate* isolate) {
228 simulator_ = isolate->thread_local_top()->simulator_; 291 simulator_ = isolate->thread_local_top()->simulator_;
229 // Check if there is active simulator. 292 // Check if there is active simulator.
230 return simulator_ != NULL; 293 return simulator_ != NULL;
231 } 294 }
232 295
233 inline void FillRegisters(v8::RegisterState* state) { 296 inline void FillRegisters(v8::RegisterState* state) {
234 #if V8_TARGET_ARCH_ARM 297 #if V8_TARGET_ARCH_ARM
235 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 298 if (!simulator_->has_bad_pc()) {
299 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
300 }
236 state->sp = reinterpret_cast<Address>(simulator_->get_register( 301 state->sp = reinterpret_cast<Address>(simulator_->get_register(
237 Simulator::sp)); 302 Simulator::sp));
238 state->fp = reinterpret_cast<Address>(simulator_->get_register( 303 state->fp = reinterpret_cast<Address>(simulator_->get_register(
239 Simulator::r11)); 304 Simulator::r11));
240 #elif V8_TARGET_ARCH_ARM64 305 #elif V8_TARGET_ARCH_ARM64
241 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 306 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
242 // It's possible that the simulator is interrupted while it is updating 307 // It's possible that the simulator is interrupted while it is updating
243 // the sp or fp register. ARM64 simulator does this in two steps: 308 // the sp or fp register. ARM64 simulator does this in two steps:
244 // first setting it to zero and then setting it to a new value. 309 // first setting it to zero and then setting it to a new value.
245 // Bailout if sp/fp doesn't contain the new value. 310 // Bailout if sp/fp doesn't contain the new value.
311 //
312 // FIXME: The above doesn't really solve the issue.
313 // If a 64-bit target is executed on a 32-bit host even the final
314 // write is non-atomic, so it might obtain a half of the result.
315 // Moreover as long as the register set code uses memcpy (as of now),
316 // it is not guaranteed to be atomic even when both host and target
317 // are of same bitness.
246 return; 318 return;
247 } 319 }
248 state->pc = reinterpret_cast<Address>(simulator_->pc()); 320 state->pc = reinterpret_cast<Address>(simulator_->pc());
249 state->sp = reinterpret_cast<Address>(simulator_->sp()); 321 state->sp = reinterpret_cast<Address>(simulator_->sp());
250 state->fp = reinterpret_cast<Address>(simulator_->fp()); 322 state->fp = reinterpret_cast<Address>(simulator_->fp());
251 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 323 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
252 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 324 if (!simulator_->has_bad_pc()) {
325 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
326 }
253 state->sp = reinterpret_cast<Address>(simulator_->get_register( 327 state->sp = reinterpret_cast<Address>(simulator_->get_register(
254 Simulator::sp)); 328 Simulator::sp));
255 state->fp = reinterpret_cast<Address>(simulator_->get_register( 329 state->fp = reinterpret_cast<Address>(simulator_->get_register(
256 Simulator::fp)); 330 Simulator::fp));
257 #elif V8_TARGET_ARCH_PPC 331 #elif V8_TARGET_ARCH_PPC
258 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 332 if (!simulator_->has_bad_pc()) {
333 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
334 }
259 state->sp = 335 state->sp =
260 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 336 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
261 state->fp = 337 state->fp =
262 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp)); 338 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
263 #endif 339 #endif
264 } 340 }
265 341
266 private: 342 private:
267 Simulator* simulator_; 343 Simulator* simulator_;
268 }; 344 };
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 timestamp = base::TimeTicks::HighResolutionNow(); 661 timestamp = base::TimeTicks::HighResolutionNow();
586 pc = reinterpret_cast<Address>(regs.pc); 662 pc = reinterpret_cast<Address>(regs.pc);
587 state = isolate->current_vm_state(); 663 state = isolate->current_vm_state();
588 664
589 // Avoid collecting traces while doing GC. 665 // Avoid collecting traces while doing GC.
590 if (state == GC) return; 666 if (state == GC) return;
591 667
592 Address js_entry_sp = isolate->js_entry_sp(); 668 Address js_entry_sp = isolate->js_entry_sp();
593 if (js_entry_sp == 0) return; // Not executing JS now. 669 if (js_entry_sp == 0) return; // Not executing JS now.
594 670
671 if (pc && IsNoFrameRegion(pc)) {
672 pc = 0;
673 return;
674 }
675
595 ExternalCallbackScope* scope = isolate->external_callback_scope(); 676 ExternalCallbackScope* scope = isolate->external_callback_scope();
596 Address handler = Isolate::handler(isolate->thread_local_top()); 677 Address handler = Isolate::handler(isolate->thread_local_top());
597 // If there is a handler on top of the external callback scope then 678 // If there is a handler on top of the external callback scope then
598 // we have already entrered JavaScript again and the external callback 679 // we have already entrered JavaScript again and the external callback
599 // is not the top function. 680 // is not the top function.
600 if (scope && scope->scope_address() < handler) { 681 if (scope && scope->scope_address() < handler) {
601 external_callback = scope->callback(); 682 external_callback = scope->callback();
602 has_external_callback = true; 683 has_external_callback = true;
603 } else { 684 } else {
604 // Sample potential return address value for frameless invocation of 685 // Sample potential return address value for frameless invocation of
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 SampleStack(state); 849 SampleStack(state);
769 } 850 }
770 ResumeThread(profiled_thread); 851 ResumeThread(profiled_thread);
771 } 852 }
772 853
773 #endif // USE_SIGNALS 854 #endif // USE_SIGNALS
774 855
775 856
776 } // namespace internal 857 } // namespace internal
777 } // namespace v8 858 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698