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

Side by Side Diff: src/sampler.cc

Issue 1341413002: [profiler] Make no frame region detection code more robust [x86/x64] (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix crashes on simulators 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 if (!memcmp(pc - offset, pattern->bytes, pattern->bytes_count))
223 return true;
224 } else {
225 // It is not safe to examine bytes on another page as it might not be
226 // allocated thus causing a SEGFAULT.
227 // Check the pattern part that's on the same page and
228 // pessimistically assume it could be the entire pattern match.
229 if (!memcmp(pc, pattern->bytes + offset, pattern->bytes_count - offset))
230 return true;
231 }
232 }
233 }
234 return false;
235 }
236
176 } // namespace 237 } // namespace
177 238
178 #if defined(USE_SIGNALS) 239 #if defined(USE_SIGNALS)
179 240
180 class Sampler::PlatformData : public PlatformDataCommon { 241 class Sampler::PlatformData : public PlatformDataCommon {
181 public: 242 public:
182 PlatformData() : vm_tid_(pthread_self()) {} 243 PlatformData() : vm_tid_(pthread_self()) {}
183 pthread_t vm_tid() const { return vm_tid_; } 244 pthread_t vm_tid() const { return vm_tid_; }
184 245
185 private: 246 private:
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 class SimulatorHelper { 286 class SimulatorHelper {
226 public: 287 public:
227 inline bool Init(Isolate* isolate) { 288 inline bool Init(Isolate* isolate) {
228 simulator_ = isolate->thread_local_top()->simulator_; 289 simulator_ = isolate->thread_local_top()->simulator_;
229 // Check if there is active simulator. 290 // Check if there is active simulator.
230 return simulator_ != NULL; 291 return simulator_ != NULL;
231 } 292 }
232 293
233 inline void FillRegisters(v8::RegisterState* state) { 294 inline void FillRegisters(v8::RegisterState* state) {
234 #if V8_TARGET_ARCH_ARM 295 #if V8_TARGET_ARCH_ARM
235 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 296 if (!simulator_->has_bad_pc()) {
297 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
298 }
236 state->sp = reinterpret_cast<Address>(simulator_->get_register( 299 state->sp = reinterpret_cast<Address>(simulator_->get_register(
237 Simulator::sp)); 300 Simulator::sp));
238 state->fp = reinterpret_cast<Address>(simulator_->get_register( 301 state->fp = reinterpret_cast<Address>(simulator_->get_register(
239 Simulator::r11)); 302 Simulator::r11));
240 #elif V8_TARGET_ARCH_ARM64 303 #elif V8_TARGET_ARCH_ARM64
241 if (simulator_->sp() == 0 || simulator_->fp() == 0) { 304 if (simulator_->sp() == 0 || simulator_->fp() == 0) {
242 // It's possible that the simulator is interrupted while it is updating 305 // 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: 306 // 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. 307 // first setting it to zero and then setting it to a new value.
245 // Bailout if sp/fp doesn't contain the new value. 308 // Bailout if sp/fp doesn't contain the new value.
309 //
310 // FIXME: The above doesn't really solve the issue.
311 // If a 64-bit target is executed on a 32-bit host even the final
312 // write is non-atomic, so it might obtain a half of the result.
313 // Moreover as long as the register set code uses memcpy (as of now),
314 // it is not guaranteed to be atomic even when both host and target
315 // are of same bitness.
246 return; 316 return;
247 } 317 }
248 state->pc = reinterpret_cast<Address>(simulator_->pc()); 318 state->pc = reinterpret_cast<Address>(simulator_->pc());
249 state->sp = reinterpret_cast<Address>(simulator_->sp()); 319 state->sp = reinterpret_cast<Address>(simulator_->sp());
250 state->fp = reinterpret_cast<Address>(simulator_->fp()); 320 state->fp = reinterpret_cast<Address>(simulator_->fp());
251 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 321 #elif V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
252 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 322 if (!simulator_->has_bad_pc()) {
323 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
324 }
253 state->sp = reinterpret_cast<Address>(simulator_->get_register( 325 state->sp = reinterpret_cast<Address>(simulator_->get_register(
254 Simulator::sp)); 326 Simulator::sp));
255 state->fp = reinterpret_cast<Address>(simulator_->get_register( 327 state->fp = reinterpret_cast<Address>(simulator_->get_register(
256 Simulator::fp)); 328 Simulator::fp));
257 #elif V8_TARGET_ARCH_PPC 329 #elif V8_TARGET_ARCH_PPC
258 state->pc = reinterpret_cast<Address>(simulator_->get_pc()); 330 if (!simulator_->has_bad_pc()) {
331 state->pc = reinterpret_cast<Address>(simulator_->get_pc());
332 }
259 state->sp = 333 state->sp =
260 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp)); 334 reinterpret_cast<Address>(simulator_->get_register(Simulator::sp));
261 state->fp = 335 state->fp =
262 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp)); 336 reinterpret_cast<Address>(simulator_->get_register(Simulator::fp));
263 #endif 337 #endif
264 } 338 }
265 339
266 private: 340 private:
267 Simulator* simulator_; 341 Simulator* simulator_;
268 }; 342 };
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 timestamp = base::TimeTicks::HighResolutionNow(); 659 timestamp = base::TimeTicks::HighResolutionNow();
586 pc = reinterpret_cast<Address>(regs.pc); 660 pc = reinterpret_cast<Address>(regs.pc);
587 state = isolate->current_vm_state(); 661 state = isolate->current_vm_state();
588 662
589 // Avoid collecting traces while doing GC. 663 // Avoid collecting traces while doing GC.
590 if (state == GC) return; 664 if (state == GC) return;
591 665
592 Address js_entry_sp = isolate->js_entry_sp(); 666 Address js_entry_sp = isolate->js_entry_sp();
593 if (js_entry_sp == 0) return; // Not executing JS now. 667 if (js_entry_sp == 0) return; // Not executing JS now.
594 668
669 if (pc && IsNoFrameRegion(pc)) {
670 pc = 0;
671 return;
672 }
673
595 ExternalCallbackScope* scope = isolate->external_callback_scope(); 674 ExternalCallbackScope* scope = isolate->external_callback_scope();
596 Address handler = Isolate::handler(isolate->thread_local_top()); 675 Address handler = Isolate::handler(isolate->thread_local_top());
597 // If there is a handler on top of the external callback scope then 676 // If there is a handler on top of the external callback scope then
598 // we have already entrered JavaScript again and the external callback 677 // we have already entrered JavaScript again and the external callback
599 // is not the top function. 678 // is not the top function.
600 if (scope && scope->scope_address() < handler) { 679 if (scope && scope->scope_address() < handler) {
601 external_callback = scope->callback(); 680 external_callback = scope->callback();
602 has_external_callback = true; 681 has_external_callback = true;
603 } else { 682 } else {
604 // Sample potential return address value for frameless invocation of 683 // Sample potential return address value for frameless invocation of
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 SampleStack(state); 847 SampleStack(state);
769 } 848 }
770 ResumeThread(profiled_thread); 849 ResumeThread(profiled_thread);
771 } 850 }
772 851
773 #endif // USE_SIGNALS 852 #endif // USE_SIGNALS
774 853
775 854
776 } // namespace internal 855 } // namespace internal
777 } // namespace v8 856 } // 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