| Index: src/debug.h
|
| ===================================================================
|
| --- src/debug.h (revision 3427)
|
| +++ src/debug.h (working copy)
|
| @@ -206,7 +206,80 @@
|
| DebugInfoListNode* next_;
|
| };
|
|
|
| +class DebugData {
|
| + public:
|
| + // List of active debug info objects. public for tests
|
| + DebugInfoListNode* debug_info_list_;
|
| + private:
|
| + // Global handle to debug context where all the debugger JavaScript code is
|
| + // loaded.
|
| + Handle<Context> debug_context_;
|
|
|
| + // Boolean state indicating whether any break points are set.
|
| + bool has_break_points_;
|
| +
|
| + // Cache of all scripts in the heap.
|
| + ScriptCache* script_cache_;
|
| +
|
| + bool disable_break_;
|
| + bool break_on_exception_;
|
| + bool break_on_uncaught_exception_;
|
| +
|
| + // 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_;
|
| +
|
| + // Source statement position from last step next action.
|
| + int last_statement_position_;
|
| +
|
| + // Number of steps left to perform before debug event.
|
| + int step_count_;
|
| +
|
| + // Frame pointer from last step next action.
|
| + Address last_fp_;
|
| +
|
| + // Frame pointer for frame from which step in was performed.
|
| + Address step_into_fp_;
|
| +
|
| + // Frame pointer for the frame where debugger should be called when current
|
| + // step out action is completed.
|
| + Address step_out_fp_;
|
| +
|
| + // Storage location for jump when exiting debug break calls.
|
| + Address after_break_target_;
|
| +
|
| + // Top debugger entry.
|
| + EnterDebugger* debugger_entry_;
|
| +
|
| + // Pending interrupts scheduled while debugging.
|
| + int pending_interrupts_;
|
| + };
|
| +
|
| + // Storage location for registers when handling debug break calls
|
| + JSCallerSavedBuffer registers_;
|
| + ThreadLocal thread_local_;
|
| +
|
| + // Code to call for handling debug break on return.
|
| + Code* debug_break_return_;
|
| +
|
| + friend class Debug;
|
| + friend class V8Context;
|
| +
|
| + DebugData();
|
| + DISALLOW_COPY_AND_ASSIGN(DebugData);
|
| +};
|
| +
|
| // This class contains the debugger support. The main purpose is to handle
|
| // setting break points in the code.
|
| //
|
| @@ -219,8 +292,12 @@
|
| static void Setup(bool create_heap_objects);
|
| static bool Load();
|
| static void Unload();
|
| - static bool IsLoaded() { return !debug_context_.is_null(); }
|
| - static bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
|
| + static bool IsLoaded() {
|
| + return !v8_context()->debug_data_.debug_context_.is_null();
|
| + }
|
| + static bool InDebugger() {
|
| + return v8_context()->debug_data_.thread_local_.debugger_entry_ != NULL;
|
| + }
|
| static void PreemptionWhileInDebugger();
|
| static void Iterate(ObjectVisitor* v);
|
|
|
| @@ -261,64 +338,86 @@
|
| Handle<SharedFunctionInfo> shared);
|
|
|
| // Getter for the debug_context.
|
| - inline static Handle<Context> debug_context() { return debug_context_; }
|
| + inline static Handle<Context> debug_context() {
|
| + return v8_context()->debug_data_.debug_context_;
|
| + }
|
|
|
| // Check whether a global object is the debug global object.
|
| static bool IsDebugGlobal(GlobalObject* global);
|
|
|
| // Fast check to see if any break points are active.
|
| - inline static bool has_break_points() { return has_break_points_; }
|
| + inline static bool has_break_points() {
|
| + return v8_context()->debug_data_.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_;
|
| + return v8_context()->debug_data_.thread_local_.break_frame_id_;
|
| }
|
| - static int break_id() { return thread_local_.break_id_; }
|
| + static int break_id() {
|
| + return v8_context()->debug_data_.thread_local_.break_id_;
|
| + }
|
|
|
| - static bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
|
| + static bool StepInActive() {
|
| + return v8_context()->debug_data_.thread_local_.step_into_fp_ != 0;
|
| + }
|
| static void HandleStepIn(Handle<JSFunction> function,
|
| Handle<Object> holder,
|
| Address fp,
|
| bool is_constructor);
|
| - static Address step_in_fp() { return thread_local_.step_into_fp_; }
|
| - static Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
|
| + static Address step_in_fp() {
|
| + return v8_context()->debug_data_.thread_local_.step_into_fp_;
|
| + }
|
| + static Address* step_in_fp_addr() {
|
| + return &v8_context()->debug_data_.thread_local_.step_into_fp_;
|
| + }
|
|
|
| - static bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
|
| - static Address step_out_fp() { return thread_local_.step_out_fp_; }
|
| + static bool StepOutActive() {
|
| + return v8_context()->debug_data_.thread_local_.step_out_fp_ != 0;
|
| + }
|
| + static Address step_out_fp() {
|
| + return v8_context()->debug_data_.thread_local_.step_out_fp_;
|
| + }
|
|
|
| static EnterDebugger* debugger_entry() {
|
| - return thread_local_.debugger_entry_;
|
| + return v8_context()->debug_data_.thread_local_.debugger_entry_;
|
| }
|
| static void set_debugger_entry(EnterDebugger* entry) {
|
| - thread_local_.debugger_entry_ = entry;
|
| + v8_context()->debug_data_.thread_local_.debugger_entry_ = entry;
|
| }
|
|
|
| // Check whether any of the specified interrupts are pending.
|
| static bool is_interrupt_pending(InterruptFlag what) {
|
| - return (thread_local_.pending_interrupts_ & what) != 0;
|
| + return (v8_context()->debug_data_.thread_local_.pending_interrupts_ &
|
| + what) != 0;
|
| }
|
|
|
| // Set specified interrupts as pending.
|
| static void set_interrupts_pending(InterruptFlag what) {
|
| - thread_local_.pending_interrupts_ |= what;
|
| + v8_context()->debug_data_.thread_local_.pending_interrupts_ |= what;
|
| }
|
|
|
| // Clear specified interrupts from pending.
|
| static void clear_interrupt_pending(InterruptFlag what) {
|
| - thread_local_.pending_interrupts_ &= ~static_cast<int>(what);
|
| + v8_context()->debug_data_.thread_local_.pending_interrupts_ &=
|
| + ~static_cast<int>(what);
|
| }
|
|
|
| // Getter and setter for the disable break state.
|
| - static bool disable_break() { return disable_break_; }
|
| + static bool disable_break() {
|
| + return v8_context()->debug_data_.disable_break_;
|
| + }
|
| static void set_disable_break(bool disable_break) {
|
| - disable_break_ = disable_break;
|
| + v8_context()->debug_data_.disable_break_ = disable_break;
|
| }
|
|
|
| // Getters for the current exception break state.
|
| - static bool break_on_exception() { return break_on_exception_; }
|
| + static bool break_on_exception() {
|
| + return v8_context()->debug_data_.break_on_exception_;
|
| + }
|
| static bool break_on_uncaught_exception() {
|
| - return break_on_uncaught_exception_;
|
| + return v8_context()->debug_data_.break_on_uncaught_exception_;
|
| }
|
|
|
| enum AddressId {
|
| @@ -329,18 +428,21 @@
|
|
|
| // Support for setting the address to jump to when returning from break point.
|
| static Address* after_break_target_address() {
|
| - return reinterpret_cast<Address*>(&thread_local_.after_break_target_);
|
| + return reinterpret_cast<Address*>(
|
| + &v8_context()->debug_data_.thread_local_.after_break_target_);
|
| }
|
|
|
| // Support for saving/restoring registers when handling debug break calls.
|
| static Object** register_address(int r) {
|
| - return ®isters_[r];
|
| + return &v8_context()->debug_data_.registers_[r];
|
| }
|
|
|
| // Access to the debug break on return code.
|
| - static Code* debug_break_return() { return debug_break_return_; }
|
| + static Code* debug_break_return() {
|
| + return v8_context()->debug_data_.debug_break_return_;
|
| + }
|
| static Code** debug_break_return_address() {
|
| - return &debug_break_return_;
|
| + return &v8_context()->debug_data_.debug_break_return_;
|
| }
|
|
|
| static const int kEstimatedNofDebugInfoEntries = 16;
|
| @@ -397,72 +499,9 @@
|
| static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
|
| static bool CheckBreakPoint(Handle<Object> break_point_object);
|
|
|
| - // Global handle to debug context where all the debugger JavaScript code is
|
| - // loaded.
|
| - static Handle<Context> debug_context_;
|
| -
|
| - // Boolean state indicating whether any break points are set.
|
| - static bool has_break_points_;
|
| -
|
| - // Cache of all scripts in the heap.
|
| - static ScriptCache* script_cache_;
|
| -
|
| - // List of active debug info objects.
|
| - static DebugInfoListNode* debug_info_list_;
|
| -
|
| - static bool disable_break_;
|
| - static bool break_on_exception_;
|
| - static bool break_on_uncaught_exception_;
|
| -
|
| - // 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_;
|
| -
|
| - // Source statement position from last step next action.
|
| - int last_statement_position_;
|
| -
|
| - // Number of steps left to perform before debug event.
|
| - int step_count_;
|
| -
|
| - // Frame pointer from last step next action.
|
| - Address last_fp_;
|
| -
|
| - // Frame pointer for frame from which step in was performed.
|
| - Address step_into_fp_;
|
| -
|
| - // Frame pointer for the frame where debugger should be called when current
|
| - // step out action is completed.
|
| - Address step_out_fp_;
|
| -
|
| - // Storage location for jump when exiting debug break calls.
|
| - Address after_break_target_;
|
| -
|
| - // Top debugger entry.
|
| - EnterDebugger* debugger_entry_;
|
| -
|
| - // Pending interrupts scheduled while debugging.
|
| - int pending_interrupts_;
|
| - };
|
| -
|
| - // Storage location for registers when handling debug break calls
|
| - static JSCallerSavedBuffer registers_;
|
| - static ThreadLocal thread_local_;
|
| + typedef DebugData::ThreadLocal ThreadLocal;
|
| static void ThreadInit();
|
|
|
| - // Code to call for handling debug break on return.
|
| - static Code* debug_break_return_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(Debug);
|
| };
|
|
|
| @@ -577,7 +616,31 @@
|
| DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
|
| };
|
|
|
| +class DebuggerData {
|
| + Mutex* debugger_access_; // Mutex guarding debugger variables.
|
| + Handle<Object> event_listener_; // Global handle to listener.
|
| + Handle<Object> event_listener_data_;
|
| + bool compiling_natives_; // Are we compiling natives?
|
| + bool is_loading_debugger_; // Are we loading the debugger?
|
| + bool never_unload_debugger_; // Can we unload the debugger?
|
| + v8::Debug::MessageHandler2 message_handler_;
|
| + bool debugger_unload_pending_; // Was message handler cleared?
|
| + v8::Debug::HostDispatchHandler host_dispatch_handler_;
|
| + v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
|
| + int host_dispatch_micros_;
|
|
|
| + DebuggerAgent* agent_;
|
| +
|
| + LockingCommandMessageQueue command_queue_;
|
| + Semaphore* command_received_; // Signaled for each command received.
|
| + static const int kQueueInitialSize = 4;
|
| +
|
| + friend class Debugger;
|
| + friend class V8Context;
|
| + DebuggerData();
|
| + DISALLOW_COPY_AND_ASSIGN(DebuggerData);
|
| +};
|
| +
|
| class Debugger {
|
| public:
|
| static void DebugRequest(const uint16_t* json_request, int length);
|
| @@ -649,46 +712,35 @@
|
| static void UnloadDebugger();
|
|
|
| inline static bool EventActive(v8::DebugEvent event) {
|
| - ScopedLock with(debugger_access_);
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + ScopedLock with(data.debugger_access_);
|
|
|
| // Check whether the message handler was been cleared.
|
| - if (debugger_unload_pending_) {
|
| + if (data.debugger_unload_pending_) {
|
| UnloadDebugger();
|
| }
|
|
|
| // Currently argument event is not used.
|
| - return !compiling_natives_ && Debugger::IsDebuggerActive();
|
| + return !data.compiling_natives_ && Debugger::IsDebuggerActive();
|
| }
|
|
|
| static void set_compiling_natives(bool compiling_natives) {
|
| - Debugger::compiling_natives_ = compiling_natives;
|
| + v8_context()->debugger_data_.compiling_natives_ = compiling_natives;
|
| }
|
| - static bool compiling_natives() { return Debugger::compiling_natives_; }
|
| - static void set_loading_debugger(bool v) { is_loading_debugger_ = v; }
|
| - static bool is_loading_debugger() { return Debugger::is_loading_debugger_; }
|
| + static bool compiling_natives() {
|
| + return v8_context()->debugger_data_.compiling_natives_;
|
| + }
|
| + static void set_loading_debugger(bool v) {
|
| + v8_context()->debugger_data_.is_loading_debugger_ = v;
|
| + }
|
| + static bool is_loading_debugger() {
|
| + return v8_context()->debugger_data_.is_loading_debugger_;
|
| + }
|
|
|
| private:
|
| static bool IsDebuggerActive();
|
| static void ListenersChanged();
|
|
|
| - static Mutex* debugger_access_; // Mutex guarding debugger variables.
|
| - static Handle<Object> event_listener_; // Global handle to listener.
|
| - static Handle<Object> event_listener_data_;
|
| - static bool compiling_natives_; // Are we compiling natives?
|
| - static bool is_loading_debugger_; // Are we loading the debugger?
|
| - static bool never_unload_debugger_; // Can we unload the debugger?
|
| - static v8::Debug::MessageHandler2 message_handler_;
|
| - static bool debugger_unload_pending_; // Was message handler cleared?
|
| - static v8::Debug::HostDispatchHandler host_dispatch_handler_;
|
| - static v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
|
| - static int host_dispatch_micros_;
|
| -
|
| - static DebuggerAgent* agent_;
|
| -
|
| - static const int kQueueInitialSize = 4;
|
| - static LockingCommandMessageQueue command_queue_;
|
| - static Semaphore* command_received_; // Signaled for each command received.
|
| -
|
| friend class EnterDebugger;
|
| };
|
|
|
|
|