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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.h
===================================================================
--- src/debug.h (revision 1435)
+++ src/debug.h (working copy)
@@ -36,10 +36,16 @@
#include "factory.h"
#include "platform.h"
#include "string-stream.h"
+#include "v8threads.h"
namespace v8 { namespace internal {
+
+// Forward declarations.
+class EnterDebugger;
+
+
// Step actions. NOTE: These values are in macros.py as well.
enum StepAction {
StepNone = -1, // Stepping not prepared.
@@ -166,7 +172,8 @@
static bool Load();
static void Unload();
static bool IsLoaded() { return !debug_context_.is_null(); }
- static bool InDebugger() { return Top::is_break(); }
+ static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
+ static void PreemptionWhileInDebugger();
static void Iterate(ObjectVisitor* v);
static Object* Break(Arguments args);
@@ -211,6 +218,16 @@
// Fast check to see if any break points are active.
inline static bool has_break_points() { return has_break_points_; }
+ static void NewBreak(StackFrame::Id break_frame_id);
+ static void SetBreak(StackFrame::Id break_frame_id, int break_id);
+ static StackFrame::Id break_frame_id() {
+ return thread_local_.break_frame_id_;
+ }
+ static int break_id() { return thread_local_.break_id_; }
+
+
+
+
static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
static void HandleStepIn(Handle<JSFunction> function,
Address fp,
@@ -218,6 +235,20 @@
static Address step_in_fp() { return thread_local_.step_into_fp_; }
static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
+ static EnterDebugger* debugger_entry() {
+ return thread_local_.debugger_entry_;
+ }
+ static void set_debugger_entry(EnterDebugger* entry) {
+ thread_local_.debugger_entry_ = entry;
+ }
+
+ static bool preemption_pending() {
+ return thread_local_.preemption_pending_;
+ }
+ static void set_preemption_pending(bool preemption_pending) {
+ thread_local_.preemption_pending_ = preemption_pending;
+ }
+
// Getter and setter for the disable break state.
static bool disable_break() { return disable_break_; }
static void set_disable_break(bool disable_break) {
@@ -313,9 +344,18 @@
static bool break_on_exception_;
static bool break_on_uncaught_exception_;
- // Per-thread:
+ // Per-thread data.
class ThreadLocal {
public:
+ // Counter for generating next break id.
+ int break_count_;
+
+ // Current break id.
+ int break_id_;
+
+ // Frame id for the frame of the current break.
+ StackFrame::Id break_frame_id_;
+
// Step action for last step performed.
StepAction last_step_action_;
@@ -333,6 +373,12 @@
// Storage location for jump when exiting debug break calls.
Address after_break_target_;
+
+ // Top debugger entry.
+ EnterDebugger* debugger_entry_;
+
+ // Preemption happened while debugging.
+ bool preemption_pending_;
};
// Storage location for registers when handling debug break calls
@@ -519,17 +565,34 @@
// some reason could not be entered FailedToEnter will return true.
class EnterDebugger BASE_EMBEDDED {
public:
- EnterDebugger() : has_js_frames_(!it_.done()) {
+ EnterDebugger()
+ : prev_(Debug::debugger_entry()),
+ has_js_frames_(!it_.done()) {
+ ASSERT(!Debug::preemption_pending());
+
+ // Link recursive debugger entry.
+ Debug::set_debugger_entry(this);
+
+ // If a preemption is pending when first entering the debugger clear it as
+ // we don't want preemption happening while executing JavaScript in the
+ // debugger. When recursively entering the debugger the preemption flag
+ // cannot be set as this is disabled while in the debugger (see
+ // RuntimePreempt).
+ if (prev_ == NULL && StackGuard::IsPreempted()) {
+ StackGuard::Continue(PREEMPT);
+ }
+ ASSERT(!StackGuard::IsPreempted());
+
// Store the previous break id and frame id.
- break_id_ = Top::break_id();
- break_frame_id_ = Top::break_frame_id();
+ break_id_ = Debug::break_id();
+ break_frame_id_ = Debug::break_frame_id();
// Create the new break info. If there is no JavaScript frames there is no
// break frame id.
if (has_js_frames_) {
- Top::new_break(it_.frame()->id());
+ Debug::NewBreak(it_.frame()->id());
} else {
- Top::new_break(StackFrame::NO_ID);
+ Debug::NewBreak(StackFrame::NO_ID);
}
// Make sure that debugger is loaded and enter the debugger context.
@@ -543,7 +606,18 @@
~EnterDebugger() {
// Restore to the previous break state.
- Top::set_break(break_frame_id_, break_id_);
+ Debug::SetBreak(break_frame_id_, break_id_);
+
+ // Request preemption when leaving the last debugger entry and a preemption
+ // had been recorded while debugging. This is to avoid starvation in some
+ // debugging scenarios.
+ if (prev_ == NULL && Debug::preemption_pending()) {
+ StackGuard::Preempt();
+ Debug::set_preemption_pending(false);
+ }
+
+ // Leaving this debugger entry.
+ Debug::set_debugger_entry(prev_);
}
// Check whether the debugger could be entered.
@@ -553,6 +627,7 @@
inline bool HasJavaScriptFrames() { return has_js_frames_; }
private:
+ EnterDebugger* prev_; // Previous debugger entry if entered recursively.
JavaScriptFrameIterator it_;
const bool has_js_frames_; // Were there any JavaScript frames?
StackFrame::Id break_frame_id_; // Previous break frame id.
« 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