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

Side by Side Diff: src/debug.h

Issue 39124: Handle thread preemption in debugger (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/debug.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 18 matching lines...) Expand all
29 #define V8_V8_DEBUG_H_ 29 #define V8_V8_DEBUG_H_
30 30
31 #include "../include/v8-debug.h" 31 #include "../include/v8-debug.h"
32 #include "assembler.h" 32 #include "assembler.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "debug-agent.h" 34 #include "debug-agent.h"
35 #include "execution.h" 35 #include "execution.h"
36 #include "factory.h" 36 #include "factory.h"
37 #include "platform.h" 37 #include "platform.h"
38 #include "string-stream.h" 38 #include "string-stream.h"
39 #include "v8threads.h"
39 40
40 41
41 namespace v8 { namespace internal { 42 namespace v8 { namespace internal {
42 43
44
45 // Forward declarations.
46 class EnterDebugger;
47
48
43 // Step actions. NOTE: These values are in macros.py as well. 49 // Step actions. NOTE: These values are in macros.py as well.
44 enum StepAction { 50 enum StepAction {
45 StepNone = -1, // Stepping not prepared. 51 StepNone = -1, // Stepping not prepared.
46 StepOut = 0, // Step out of the current function. 52 StepOut = 0, // Step out of the current function.
47 StepNext = 1, // Step to the next statement in the current function. 53 StepNext = 1, // Step to the next statement in the current function.
48 StepIn = 2, // Step into new functions invoked or the next statement 54 StepIn = 2, // Step into new functions invoked or the next statement
49 // in the current function. 55 // in the current function.
50 StepMin = 3, // Perform a minimum step in the current function. 56 StepMin = 3, // Perform a minimum step in the current function.
51 StepInMin = 4 // Step into new functions invoked or perform a minimum step 57 StepInMin = 4 // Step into new functions invoked or perform a minimum step
52 // in the current function. 58 // in the current function.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 // This class controls the debug info for all functions which currently have 165 // This class controls the debug info for all functions which currently have
160 // active breakpoints in them. This debug info is held in the heap root object 166 // active breakpoints in them. This debug info is held in the heap root object
161 // debug_info which is a FixedArray. Each entry in this list is of class 167 // debug_info which is a FixedArray. Each entry in this list is of class
162 // DebugInfo. 168 // DebugInfo.
163 class Debug { 169 class Debug {
164 public: 170 public:
165 static void Setup(bool create_heap_objects); 171 static void Setup(bool create_heap_objects);
166 static bool Load(); 172 static bool Load();
167 static void Unload(); 173 static void Unload();
168 static bool IsLoaded() { return !debug_context_.is_null(); } 174 static bool IsLoaded() { return !debug_context_.is_null(); }
169 static bool InDebugger() { return Top::is_break(); } 175 static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
176 static void PreemptionWhileInDebugger();
170 static void Iterate(ObjectVisitor* v); 177 static void Iterate(ObjectVisitor* v);
171 178
172 static Object* Break(Arguments args); 179 static Object* Break(Arguments args);
173 static void SetBreakPoint(Handle<SharedFunctionInfo> shared, 180 static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
174 int source_position, 181 int source_position,
175 Handle<Object> break_point_object); 182 Handle<Object> break_point_object);
176 static void ClearBreakPoint(Handle<Object> break_point_object); 183 static void ClearBreakPoint(Handle<Object> break_point_object);
177 static void ClearAllBreakPoints(); 184 static void ClearAllBreakPoints();
178 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); 185 static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
179 static void FloodHandlerWithOneShot(); 186 static void FloodHandlerWithOneShot();
(...skipping 24 matching lines...) Expand all
204 211
205 // Getter for the debug_context. 212 // Getter for the debug_context.
206 inline static Handle<Context> debug_context() { return debug_context_; } 213 inline static Handle<Context> debug_context() { return debug_context_; }
207 214
208 // Check whether a global object is the debug global object. 215 // Check whether a global object is the debug global object.
209 static bool IsDebugGlobal(GlobalObject* global); 216 static bool IsDebugGlobal(GlobalObject* global);
210 217
211 // Fast check to see if any break points are active. 218 // Fast check to see if any break points are active.
212 inline static bool has_break_points() { return has_break_points_; } 219 inline static bool has_break_points() { return has_break_points_; }
213 220
221 static void NewBreak(StackFrame::Id break_frame_id);
222 static void SetBreak(StackFrame::Id break_frame_id, int break_id);
223 static StackFrame::Id break_frame_id() {
224 return thread_local_.break_frame_id_;
225 }
226 static int break_id() { return thread_local_.break_id_; }
227
228
229
230
214 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; } 231 static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
215 static void HandleStepIn(Handle<JSFunction> function, 232 static void HandleStepIn(Handle<JSFunction> function,
216 Address fp, 233 Address fp,
217 bool is_constructor); 234 bool is_constructor);
218 static Address step_in_fp() { return thread_local_.step_into_fp_; } 235 static Address step_in_fp() { return thread_local_.step_into_fp_; }
219 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; } 236 static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
220 237
238 static EnterDebugger* debugger_entry() {
239 return thread_local_.debugger_entry_;
240 }
241 static void set_debugger_entry(EnterDebugger* entry) {
242 thread_local_.debugger_entry_ = entry;
243 }
244
245 static bool preemption_pending() {
246 return thread_local_.preemption_pending_;
247 }
248 static void set_preemption_pending(bool preemption_pending) {
249 thread_local_.preemption_pending_ = preemption_pending;
250 }
251
221 // Getter and setter for the disable break state. 252 // Getter and setter for the disable break state.
222 static bool disable_break() { return disable_break_; } 253 static bool disable_break() { return disable_break_; }
223 static void set_disable_break(bool disable_break) { 254 static void set_disable_break(bool disable_break) {
224 disable_break_ = disable_break; 255 disable_break_ = disable_break;
225 } 256 }
226 257
227 // Getters for the current exception break state. 258 // Getters for the current exception break state.
228 static bool break_on_exception() { return break_on_exception_; } 259 static bool break_on_exception() { return break_on_exception_; }
229 static bool break_on_uncaught_exception() { 260 static bool break_on_uncaught_exception() {
230 return break_on_uncaught_exception_; 261 return break_on_uncaught_exception_;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 static Handle<Context> debug_context_; 337 static Handle<Context> debug_context_;
307 338
308 // Boolean state indicating whether any break points are set. 339 // Boolean state indicating whether any break points are set.
309 static bool has_break_points_; 340 static bool has_break_points_;
310 static DebugInfoListNode* debug_info_list_; 341 static DebugInfoListNode* debug_info_list_;
311 342
312 static bool disable_break_; 343 static bool disable_break_;
313 static bool break_on_exception_; 344 static bool break_on_exception_;
314 static bool break_on_uncaught_exception_; 345 static bool break_on_uncaught_exception_;
315 346
316 // Per-thread: 347 // Per-thread data.
317 class ThreadLocal { 348 class ThreadLocal {
318 public: 349 public:
350 // Counter for generating next break id.
351 int break_count_;
352
353 // Current break id.
354 int break_id_;
355
356 // Frame id for the frame of the current break.
357 StackFrame::Id break_frame_id_;
358
319 // Step action for last step performed. 359 // Step action for last step performed.
320 StepAction last_step_action_; 360 StepAction last_step_action_;
321 361
322 // Source statement position from last step next action. 362 // Source statement position from last step next action.
323 int last_statement_position_; 363 int last_statement_position_;
324 364
325 // Number of steps left to perform before debug event. 365 // Number of steps left to perform before debug event.
326 int step_count_; 366 int step_count_;
327 367
328 // Frame pointer from last step next action. 368 // Frame pointer from last step next action.
329 Address last_fp_; 369 Address last_fp_;
330 370
331 // Frame pointer for frame from which step in was performed. 371 // Frame pointer for frame from which step in was performed.
332 Address step_into_fp_; 372 Address step_into_fp_;
333 373
334 // Storage location for jump when exiting debug break calls. 374 // Storage location for jump when exiting debug break calls.
335 Address after_break_target_; 375 Address after_break_target_;
376
377 // Top debugger entry.
378 EnterDebugger* debugger_entry_;
379
380 // Preemption happened while debugging.
381 bool preemption_pending_;
336 }; 382 };
337 383
338 // Storage location for registers when handling debug break calls 384 // Storage location for registers when handling debug break calls
339 static JSCallerSavedBuffer registers_; 385 static JSCallerSavedBuffer registers_;
340 static ThreadLocal thread_local_; 386 static ThreadLocal thread_local_;
341 static void ThreadInit(); 387 static void ThreadInit();
342 388
343 // Code object for debug break return entry code. 389 // Code object for debug break return entry code.
344 static Code* debug_break_return_entry_; 390 static Code* debug_break_return_entry_;
345 391
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 DISALLOW_COPY_AND_ASSIGN(DebugMessageThread); 558 DISALLOW_COPY_AND_ASSIGN(DebugMessageThread);
513 }; 559 };
514 560
515 561
516 // This class is used for entering the debugger. Create an instance in the stack 562 // This class is used for entering the debugger. Create an instance in the stack
517 // to enter the debugger. This will set the current break state, make sure the 563 // to enter the debugger. This will set the current break state, make sure the
518 // debugger is loaded and switch to the debugger context. If the debugger for 564 // debugger is loaded and switch to the debugger context. If the debugger for
519 // some reason could not be entered FailedToEnter will return true. 565 // some reason could not be entered FailedToEnter will return true.
520 class EnterDebugger BASE_EMBEDDED { 566 class EnterDebugger BASE_EMBEDDED {
521 public: 567 public:
522 EnterDebugger() : has_js_frames_(!it_.done()) { 568 EnterDebugger()
569 : prev_(Debug::debugger_entry()),
570 has_js_frames_(!it_.done()) {
571 ASSERT(!Debug::preemption_pending());
572
573 // Link recursive debugger entry.
574 Debug::set_debugger_entry(this);
575
576 // If a preemption is pending when first entering the debugger clear it as
577 // we don't want preemption happening while executing JavaScript in the
578 // debugger. When recursively entering the debugger the preemption flag
579 // cannot be set as this is disabled while in the debugger (see
580 // RuntimePreempt).
581 if (prev_ == NULL && StackGuard::IsPreempted()) {
582 StackGuard::Continue(PREEMPT);
583 }
584 ASSERT(!StackGuard::IsPreempted());
585
523 // Store the previous break id and frame id. 586 // Store the previous break id and frame id.
524 break_id_ = Top::break_id(); 587 break_id_ = Debug::break_id();
525 break_frame_id_ = Top::break_frame_id(); 588 break_frame_id_ = Debug::break_frame_id();
526 589
527 // Create the new break info. If there is no JavaScript frames there is no 590 // Create the new break info. If there is no JavaScript frames there is no
528 // break frame id. 591 // break frame id.
529 if (has_js_frames_) { 592 if (has_js_frames_) {
530 Top::new_break(it_.frame()->id()); 593 Debug::NewBreak(it_.frame()->id());
531 } else { 594 } else {
532 Top::new_break(StackFrame::NO_ID); 595 Debug::NewBreak(StackFrame::NO_ID);
533 } 596 }
534 597
535 // Make sure that debugger is loaded and enter the debugger context. 598 // Make sure that debugger is loaded and enter the debugger context.
536 load_failed_ = !Debug::Load(); 599 load_failed_ = !Debug::Load();
537 if (!load_failed_) { 600 if (!load_failed_) {
538 // NOTE the member variable save which saves the previous context before 601 // NOTE the member variable save which saves the previous context before
539 // this change. 602 // this change.
540 Top::set_context(*Debug::debug_context()); 603 Top::set_context(*Debug::debug_context());
541 } 604 }
542 } 605 }
543 606
544 ~EnterDebugger() { 607 ~EnterDebugger() {
545 // Restore to the previous break state. 608 // Restore to the previous break state.
546 Top::set_break(break_frame_id_, break_id_); 609 Debug::SetBreak(break_frame_id_, break_id_);
610
611 // Request preemption when leaving the last debugger entry and a preemption
612 // had been recorded while debugging. This is to avoid starvation in some
613 // debugging scenarios.
614 if (prev_ == NULL && Debug::preemption_pending()) {
615 StackGuard::Preempt();
616 Debug::set_preemption_pending(false);
617 }
618
619 // Leaving this debugger entry.
620 Debug::set_debugger_entry(prev_);
547 } 621 }
548 622
549 // Check whether the debugger could be entered. 623 // Check whether the debugger could be entered.
550 inline bool FailedToEnter() { return load_failed_; } 624 inline bool FailedToEnter() { return load_failed_; }
551 625
552 // Check whether there are any JavaScript frames on the stack. 626 // Check whether there are any JavaScript frames on the stack.
553 inline bool HasJavaScriptFrames() { return has_js_frames_; } 627 inline bool HasJavaScriptFrames() { return has_js_frames_; }
554 628
555 private: 629 private:
630 EnterDebugger* prev_; // Previous debugger entry if entered recursively.
556 JavaScriptFrameIterator it_; 631 JavaScriptFrameIterator it_;
557 const bool has_js_frames_; // Were there any JavaScript frames? 632 const bool has_js_frames_; // Were there any JavaScript frames?
558 StackFrame::Id break_frame_id_; // Previous break frame id. 633 StackFrame::Id break_frame_id_; // Previous break frame id.
559 int break_id_; // Previous break id. 634 int break_id_; // Previous break id.
560 bool load_failed_; // Did the debugger fail to load? 635 bool load_failed_; // Did the debugger fail to load?
561 SaveContext save_; // Saves previous context. 636 SaveContext save_; // Saves previous context.
562 }; 637 };
563 638
564 639
565 // Stack allocated class for disabling break. 640 // Stack allocated class for disabling break.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 } 693 }
619 private: 694 private:
620 Debug::AddressId id_; 695 Debug::AddressId id_;
621 int reg_; 696 int reg_;
622 }; 697 };
623 698
624 699
625 } } // namespace v8::internal 700 } } // namespace v8::internal
626 701
627 #endif // V8_V8_DEBUG_H_ 702 #endif // V8_V8_DEBUG_H_
OLDNEW
« no previous file with comments | « no previous file | src/debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698