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

Unified Diff: src/debug.h

Issue 298863011: Merge the classes Debug and Debugger. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rename EnterDebugger Created 6 years, 7 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 | « src/compiler.cc ('k') | src/debug.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.h
diff --git a/src/debug.h b/src/debug.h
index e0f3ea09770c9266021d51b8c59f72554b511cc6..06e60523fd3b9ddd2875fab810a2d6c7b44e2c36 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -13,6 +13,7 @@
#include "flags.h"
#include "frames-inl.h"
#include "hashmap.h"
+#include "liveedit.h"
#include "platform.h"
#include "string-stream.h"
#include "v8threads.h"
@@ -24,7 +25,7 @@ namespace internal {
// Forward declarations.
-class EnterDebugger;
+class DebugScope;
// Step actions. NOTE: These values are in macros.py as well.
@@ -149,10 +150,7 @@ class BreakLocationIterator {
// the cache is the script id.
class ScriptCache : private HashMap {
public:
- explicit ScriptCache(Isolate* isolate)
- : HashMap(HashMap::PointersMatch),
- isolate_(isolate),
- collected_scripts_(10) {}
+ explicit ScriptCache(Isolate* isolate);
virtual ~ScriptCache() { Clear(); }
// Add script to the cache.
@@ -202,413 +200,6 @@ class DebugInfoListNode {
DebugInfoListNode* next_;
};
-// This class contains the debugger support. The main purpose is to handle
-// setting break points in the code.
-//
-// This class controls the debug info for all functions which currently have
-// active breakpoints in them. This debug info is held in the heap root object
-// debug_info which is a FixedArray. Each entry in this list is of class
-// DebugInfo.
-class Debug {
- public:
- bool Load();
- void Unload();
- bool IsLoaded() { return !debug_context_.is_null(); }
- bool InDebugger() { return thread_local_.debugger_entry_ != NULL; }
-
- Object* Break(Arguments args);
- bool SetBreakPoint(Handle<JSFunction> function,
- Handle<Object> break_point_object,
- int* source_position);
- bool SetBreakPointForScript(Handle<Script> script,
- Handle<Object> break_point_object,
- int* source_position,
- BreakPositionAlignment alignment);
- void ClearBreakPoint(Handle<Object> break_point_object);
- void ClearAllBreakPoints();
- void FloodWithOneShot(Handle<JSFunction> function);
- void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
- void FloodHandlerWithOneShot();
- void ChangeBreakOnException(ExceptionBreakType type, bool enable);
- bool IsBreakOnException(ExceptionBreakType type);
-
- void PromiseHandlePrologue(Handle<JSFunction> promise_getter);
- void PromiseHandleEpilogue();
- // Returns a promise if it does not have a reject handler.
- Handle<Object> GetPromiseForUncaughtException();
-
- void PrepareStep(StepAction step_action,
- int step_count,
- StackFrame::Id frame_id);
- void ClearStepping();
- void ClearStepOut();
- bool IsStepping() { return thread_local_.step_count_ > 0; }
- bool StepNextContinue(BreakLocationIterator* break_location_iterator,
- JavaScriptFrame* frame);
- static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
- static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
-
- void PrepareForBreakPoints();
-
- // This function is used in FunctionNameUsing* tests.
- Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
-
- // Returns whether the operation succeeded. Compilation can only be triggered
- // if a valid closure is passed as the second argument, otherwise the shared
- // function needs to be compiled already.
- bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
- Handle<JSFunction> function);
-
- // Returns true if the current stub call is patched to call the debugger.
- static bool IsDebugBreak(Address addr);
- // Returns true if the current return statement has been patched to be
- // a debugger breakpoint.
- static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
-
- // Check whether a code stub with the specified major key is a possible break
- // point location.
- static bool IsSourceBreakStub(Code* code);
- static bool IsBreakStub(Code* code);
-
- // Find the builtin to use for invoking the debug break
- static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
-
- static Handle<Object> GetSourceBreakLocations(
- Handle<SharedFunctionInfo> shared,
- BreakPositionAlignment position_aligment);
-
- // Getter for the debug_context.
- inline Handle<Context> debug_context() { return debug_context_; }
-
- // Check whether a global object is the debug global object.
- bool IsDebugGlobal(GlobalObject* global);
-
- // Check whether this frame is just about to return.
- bool IsBreakAtReturn(JavaScriptFrame* frame);
-
- // Fast check to see if any break points are active.
- inline bool has_break_points() { return has_break_points_; }
-
- void NewBreak(StackFrame::Id break_frame_id);
- void SetBreak(StackFrame::Id break_frame_id, int break_id);
- StackFrame::Id break_frame_id() {
- return thread_local_.break_frame_id_;
- }
- int break_id() { return thread_local_.break_id_; }
-
- bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
- void HandleStepIn(Handle<JSFunction> function,
- Handle<Object> holder,
- Address fp,
- bool is_constructor);
- Address step_in_fp() { return thread_local_.step_into_fp_; }
- Address* step_in_fp_addr() { return &thread_local_.step_into_fp_; }
-
- bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
- Address step_out_fp() { return thread_local_.step_out_fp_; }
-
- EnterDebugger* debugger_entry() {
- return thread_local_.debugger_entry_;
- }
- void set_debugger_entry(EnterDebugger* entry) {
- thread_local_.debugger_entry_ = entry;
- }
-
- // Check whether any of the specified interrupts are pending.
- bool has_pending_interrupt() {
- return thread_local_.has_pending_interrupt_;
- }
-
- // Set specified interrupts as pending.
- void set_has_pending_interrupt(bool value) {
- thread_local_.has_pending_interrupt_ = value;
- }
-
- // Getter and setter for the disable break state.
- bool disable_break() { return disable_break_; }
- void set_disable_break(bool disable_break) {
- disable_break_ = disable_break;
- }
-
- // Getters for the current exception break state.
- bool break_on_exception() { return break_on_exception_; }
- bool break_on_uncaught_exception() {
- return break_on_uncaught_exception_;
- }
-
- enum AddressId {
- k_after_break_target_address,
- k_restarter_frame_function_pointer
- };
-
- // Support for setting the address to jump to when returning from break point.
- Address after_break_target_address() {
- return reinterpret_cast<Address>(&thread_local_.after_break_target_);
- }
-
- Address restarter_frame_function_pointer_address() {
- Object*** address = &thread_local_.restarter_frame_function_pointer_;
- return reinterpret_cast<Address>(address);
- }
-
- static const int kEstimatedNofDebugInfoEntries = 16;
- static const int kEstimatedNofBreakPointsInFunction = 16;
-
- // Passed to MakeWeak.
- static void HandleWeakDebugInfo(
- const v8::WeakCallbackData<v8::Value, void>& data);
-
- friend class Debugger;
- friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
- friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
-
- // Threading support.
- char* ArchiveDebug(char* to);
- char* RestoreDebug(char* from);
- static int ArchiveSpacePerThread();
- void FreeThreadResources() { }
-
- // Mirror cache handling.
- void ClearMirrorCache();
-
- // Script cache handling.
- void CreateScriptCache();
- void DestroyScriptCache();
- void AddScriptToScriptCache(Handle<Script> script);
- Handle<FixedArray> GetLoadedScripts();
-
- // Record function from which eval was called.
- static void RecordEvalCaller(Handle<Script> script);
-
- // Garbage collection notifications.
- void AfterGarbageCollection();
-
- // Code generator routines.
- static void GenerateSlot(MacroAssembler* masm);
- static void GenerateCallICStubDebugBreak(MacroAssembler* masm);
- static void GenerateLoadICDebugBreak(MacroAssembler* masm);
- static void GenerateStoreICDebugBreak(MacroAssembler* masm);
- static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
- static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
- static void GenerateCompareNilICDebugBreak(MacroAssembler* masm);
- static void GenerateReturnDebugBreak(MacroAssembler* masm);
- static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
- static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
- static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
- static void GenerateSlotDebugBreak(MacroAssembler* masm);
- static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
-
- // FrameDropper is a code replacement for a JavaScript frame with possibly
- // several frames above.
- // There is no calling conventions here, because it never actually gets
- // called, it only gets returned to.
- static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
-
- // Describes how exactly a frame has been dropped from stack.
- enum FrameDropMode {
- // No frame has been dropped.
- FRAMES_UNTOUCHED,
- // The top JS frame had been calling IC stub. IC stub mustn't be called now.
- FRAME_DROPPED_IN_IC_CALL,
- // The top JS frame had been calling debug break slot stub. Patch the
- // address this stub jumps to in the end.
- FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
- // The top JS frame had been calling some C++ function. The return address
- // gets patched automatically.
- FRAME_DROPPED_IN_DIRECT_CALL,
- FRAME_DROPPED_IN_RETURN_CALL,
- CURRENTLY_SET_MODE
- };
-
- void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
- FrameDropMode mode,
- Object** restarter_frame_function_pointer);
-
- // Initializes an artificial stack frame. The data it contains is used for:
- // a. successful work of frame dropper code which eventually gets control,
- // b. being compatible with regular stack structure for various stack
- // iterators.
- // Returns address of stack allocated pointer to restarted function,
- // the value that is called 'restarter_frame_function_pointer'. The value
- // at this address (possibly updated by GC) may be used later when preparing
- // 'step in' operation.
- static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
- Handle<Code> code);
-
- static const int kFrameDropperFrameSize;
-
- // Architecture-specific constant.
- static const bool kFrameDropperSupported;
-
- /**
- * Defines layout of a stack frame that supports padding. This is a regular
- * internal frame that has a flexible stack structure. LiveEdit can shift
- * its lower part up the stack, taking up the 'padding' space when additional
- * stack memory is required.
- * Such frame is expected immediately above the topmost JavaScript frame.
- *
- * Stack Layout:
- * --- Top
- * LiveEdit routine frames
- * ---
- * C frames of debug handler
- * ---
- * ...
- * ---
- * An internal frame that has n padding words:
- * - any number of words as needed by code -- upper part of frame
- * - padding size: a Smi storing n -- current size of padding
- * - padding: n words filled with kPaddingValue in form of Smi
- * - 3 context/type words of a regular InternalFrame
- * - fp
- * ---
- * Topmost JavaScript frame
- * ---
- * ...
- * --- Bottom
- */
- class FramePaddingLayout : public AllStatic {
- public:
- // Architecture-specific constant.
- static const bool kIsSupported;
-
- // A size of frame base including fp. Padding words starts right above
- // the base.
- static const int kFrameBaseSize = 4;
-
- // A number of words that should be reserved on stack for the LiveEdit use.
- // Normally equals 1. Stored on stack in form of Smi.
- static const int kInitialSize;
- // A value that padding words are filled with (in form of Smi). Going
- // bottom-top, the first word not having this value is a counter word.
- static const int kPaddingValue;
- };
-
- private:
- explicit Debug(Isolate* isolate);
-
- static bool CompileDebuggerScript(Isolate* isolate, int index);
- void ClearOneShot();
- void ActivateStepIn(StackFrame* frame);
- void ClearStepIn();
- void ActivateStepOut(StackFrame* frame);
- void ClearStepNext();
- // Returns whether the compile succeeded.
- void RemoveDebugInfo(Handle<DebugInfo> debug_info);
- void SetAfterBreakTarget(JavaScriptFrame* frame);
- Handle<Object> CheckBreakPoints(Handle<Object> break_point);
- bool CheckBreakPoint(Handle<Object> break_point_object);
-
- void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function);
- void RecompileAndRelocateSuspendedGenerators(
- const List<Handle<JSGeneratorObject> > &suspended_generators);
-
- // 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_;
-
- // List of active debug info objects.
- DebugInfoListNode* debug_info_list_;
-
- bool disable_break_;
- bool break_on_exception_;
- bool break_on_uncaught_exception_;
-
- class PromiseOnStack {
- public:
- PromiseOnStack(Isolate* isolate,
- PromiseOnStack* prev,
- Handle<JSFunction> getter);
- ~PromiseOnStack();
- StackHandler* handler() { return handler_; }
- Handle<JSFunction> getter() { return getter_; }
- PromiseOnStack* prev() { return prev_; }
- private:
- Isolate* isolate_;
- StackHandler* handler_;
- Handle<JSFunction> getter_;
- PromiseOnStack* prev_;
- };
-
- // 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_;
-
- // Number of queued steps left to perform before debug event.
- int queued_step_count_;
-
- // 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_;
-
- // Stores the way how LiveEdit has patched the stack. It is used when
- // debugger returns control back to user script.
- FrameDropMode frame_drop_mode_;
-
- // Top debugger entry.
- EnterDebugger* debugger_entry_;
-
- // Pending interrupts scheduled while debugging.
- bool has_pending_interrupt_;
-
- // When restarter frame is on stack, stores the address
- // of the pointer to function being restarted. Otherwise (most of the time)
- // stores NULL. This pointer is used with 'step in' implementation.
- Object** restarter_frame_function_pointer_;
-
- // When a promise is being resolved, we may want to trigger a debug event
- // if we catch a throw. For this purpose we remember the try-catch
- // handler address that would catch the exception. We also hold onto a
- // closure that returns a promise if the exception is considered uncaught.
- // Due to the possibility of reentry we use a linked list.
- PromiseOnStack* promise_on_stack_;
- };
-
- // Storage location for registers when handling debug break calls
- ThreadLocal thread_local_;
- void ThreadInit();
-
- Isolate* isolate_;
-
- friend class Isolate;
-
- DISALLOW_COPY_AND_ASSIGN(Debug);
-};
-
-
-DECLARE_RUNTIME_FUNCTION(Debug_Break);
// Message delivered to the message handler callback. This is either a debugger
@@ -693,7 +284,6 @@ class CommandMessage {
static CommandMessage New(const Vector<uint16_t>& command,
v8::Debug::ClientData* data);
CommandMessage();
- ~CommandMessage();
// Deletes user data and disposes of the text.
void Dispose();
@@ -707,6 +297,7 @@ class CommandMessage {
v8::Debug::ClientData* client_data_;
};
+
// A Queue of CommandMessage objects. A thread-safe version is
// LockingCommandMessageQueue, based on this class.
class CommandMessageQueue BASE_EMBEDDED {
@@ -728,9 +319,6 @@ class CommandMessageQueue BASE_EMBEDDED {
};
-class MessageDispatchHelperThread;
-
-
// LockingCommandMessageQueue is a thread-safe circular buffer of CommandMessage
// messages. The message data is not managed by LockingCommandMessageQueue.
// Pointers to the data are passed in and out. Implemented by adding a
@@ -750,70 +338,202 @@ class LockingCommandMessageQueue BASE_EMBEDDED {
};
-class Debugger {
+class PromiseOnStack {
public:
- void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
- void OnException(Handle<Object> exception, bool uncaught);
- void OnBeforeCompile(Handle<Script> script);
+ PromiseOnStack(Isolate* isolate,
+ PromiseOnStack* prev,
+ Handle<JSFunction> getter);
+ ~PromiseOnStack();
+ StackHandler* handler() { return handler_; }
+ Handle<JSFunction> getter() { return getter_; }
+ PromiseOnStack* prev() { return prev_; }
+ private:
+ Isolate* isolate_;
+ StackHandler* handler_;
+ Handle<JSFunction> getter_;
+ PromiseOnStack* prev_;
+};
+
+// This class contains the debugger support. The main purpose is to handle
+// setting break points in the code.
+//
+// This class controls the debug info for all functions which currently have
+// active breakpoints in them. This debug info is held in the heap root object
+// debug_info which is a FixedArray. Each entry in this list is of class
+// DebugInfo.
+class Debug {
+ public:
enum AfterCompileFlags {
NO_AFTER_COMPILE_FLAGS,
SEND_WHEN_DEBUGGING
};
+
+ // Debug event triggers.
+ void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
+ void OnException(Handle<Object> exception, bool uncaught);
+ void OnBeforeCompile(Handle<Script> script);
void OnAfterCompile(Handle<Script> script,
AfterCompileFlags after_compile_flags);
void OnScriptCollected(int id);
+ // API facing.
void SetEventListener(Handle<Object> callback, Handle<Object> data);
void SetMessageHandler(v8::Debug::MessageHandler handler);
-
- // Add a debugger command to the command queue.
void EnqueueCommandMessage(Vector<const uint16_t> command,
v8::Debug::ClientData* client_data = NULL);
-
- // Check whether there are commands in the command queue.
- bool HasCommands();
-
// Enqueue a debugger command to the command queue for event listeners.
void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
-
MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun,
Handle<Object> data);
-
Handle<Context> GetDebugContext();
+ void HandleDebugBreak();
+ void ProcessDebugMessages(bool debug_command_only);
+
+ // Internal logic
+ bool Load();
+ void Break(Arguments args, JavaScriptFrame*);
+ void SetAfterBreakTarget(JavaScriptFrame* frame);
+
+ // Scripts handling.
+ Handle<FixedArray> GetLoadedScripts();
+
+ // Break point handling.
+ bool SetBreakPoint(Handle<JSFunction> function,
+ Handle<Object> break_point_object,
+ int* source_position);
+ bool SetBreakPointForScript(Handle<Script> script,
+ Handle<Object> break_point_object,
+ int* source_position,
+ BreakPositionAlignment alignment);
+ void ClearBreakPoint(Handle<Object> break_point_object);
+ void ClearAllBreakPoints();
+ void FloodWithOneShot(Handle<JSFunction> function);
+ void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
+ void FloodHandlerWithOneShot();
+ void ChangeBreakOnException(ExceptionBreakType type, bool enable);
+ bool IsBreakOnException(ExceptionBreakType type);
+
+ // Stepping handling.
+ void PrepareStep(StepAction step_action,
+ int step_count,
+ StackFrame::Id frame_id);
+ void ClearStepping();
+ void ClearStepOut();
+ bool IsStepping() { return thread_local_.step_count_ > 0; }
+ bool StepNextContinue(BreakLocationIterator* break_location_iterator,
+ JavaScriptFrame* frame);
+ bool StepInActive() { return thread_local_.step_into_fp_ != 0; }
+ void HandleStepIn(Handle<JSFunction> function,
+ Handle<Object> holder,
+ Address fp,
+ bool is_constructor);
+ bool StepOutActive() { return thread_local_.step_out_fp_ != 0; }
+
+ // Purge all code objects that have no debug break slots.
+ void PrepareForBreakPoints();
+
+ // Returns whether the operation succeeded. Compilation can only be triggered
+ // if a valid closure is passed as the second argument, otherwise the shared
+ // function needs to be compiled already.
+ bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
+ Handle<JSFunction> function);
+ static Handle<DebugInfo> GetDebugInfo(Handle<SharedFunctionInfo> shared);
+ static bool HasDebugInfo(Handle<SharedFunctionInfo> shared);
+
+ // This function is used in FunctionNameUsing* tests.
+ Object* FindSharedFunctionInfoInScript(Handle<Script> script, int position);
+
+ // Returns true if the current stub call is patched to call the debugger.
+ static bool IsDebugBreak(Address addr);
+ // Returns true if the current return statement has been patched to be
+ // a debugger breakpoint.
+ static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
+
+ static Handle<Object> GetSourceBreakLocations(
+ Handle<SharedFunctionInfo> shared,
+ BreakPositionAlignment position_aligment);
+
+ // Check whether a global object is the debug global object.
+ bool IsDebugGlobal(GlobalObject* global);
+
+ // Check whether this frame is just about to return.
+ bool IsBreakAtReturn(JavaScriptFrame* frame);
+
+ // Promise handling.
+ void PromiseHandlePrologue(Handle<JSFunction> promise_getter);
+ void PromiseHandleEpilogue();
+
+ // Support for LiveEdit
+ void FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
+ LiveEdit::FrameDropMode mode,
+ Object** restarter_frame_function_pointer);
+
+ // Passed to MakeWeak.
+ static void HandleWeakDebugInfo(
+ const v8::WeakCallbackData<v8::Value, void>& data);
- bool ignore_debugger() const { return ignore_debugger_; }
+ // Threading support.
+ char* ArchiveDebug(char* to);
+ char* RestoreDebug(char* from);
+ static int ArchiveSpacePerThread();
+ void FreeThreadResources() { }
+
+ // Record function from which eval was called.
+ static void RecordEvalCaller(Handle<Script> script);
+
+ // Garbage collection notifications.
+ void AfterGarbageCollection();
+
+ // Flags and states.
+ DebugScope* debugger_entry() { return thread_local_.current_debug_scope_; }
+ inline Handle<Context> debug_context() { return debug_context_; }
void set_live_edit_enabled(bool v) { live_edit_enabled_ = v; }
bool live_edit_enabled() const {
return FLAG_enable_liveedit && live_edit_enabled_ ;
}
- bool is_active() { return is_active_; }
+ inline bool is_active() const { return is_active_; }
+ inline bool is_loaded() const { return !debug_context_.is_null(); }
+ inline bool has_break_points() const { return has_break_points_; }
+ inline bool in_debug_scope() const {
+ return thread_local_.current_debug_scope_ != NULL;
+ }
+ void set_disable_break(bool v) { break_disabled_ = v; }
- class IgnoreScope {
- public:
- explicit IgnoreScope(Debugger* debugger)
- : debugger_(debugger),
- old_state_(debugger_->ignore_debugger_) {
- debugger_->ignore_debugger_ = true;
- }
-
- ~IgnoreScope() {
- debugger_->ignore_debugger_ = old_state_;
- }
-
- private:
- Debugger* debugger_;
- bool old_state_;
- DISALLOW_COPY_AND_ASSIGN(IgnoreScope);
- };
+ StackFrame::Id break_frame_id() { return thread_local_.break_frame_id_; }
+ int break_id() { return thread_local_.break_id_; }
+
+ // Support for embedding into generated code.
+ Address after_break_target_address() {
+ return reinterpret_cast<Address>(&after_break_target_);
+ }
+
+ Address restarter_frame_function_pointer_address() {
+ Object*** address = &thread_local_.restarter_frame_function_pointer_;
+ return reinterpret_cast<Address>(address);
+ }
+
+ Address step_in_fp_addr() {
+ return reinterpret_cast<Address>(&thread_local_.step_into_fp_);
+ }
private:
- explicit Debugger(Isolate* isolate);
- ~Debugger();
+ explicit Debug(Isolate* isolate);
+
+ void UpdateState();
+ void Unload();
+ void SetNextBreakId() {
+ thread_local_.break_id_ = ++thread_local_.break_count_;
+ }
+ // Check whether there are commands in the command queue.
+ inline bool has_commands() const { return !command_queue_.IsEmpty(); }
+ inline bool ignore_events() const { return is_suppressed_ || !is_active_; }
+
+ // Constructors for debug event objects.
MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
- Vector<const char> constructor_name,
+ const char* constructor_name,
int argc,
Handle<Object> argv[]);
MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
@@ -827,19 +547,16 @@ class Debugger {
Handle<Script> script, bool before);
MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id);
+ // Mirror cache handling.
+ void ClearMirrorCache();
+
+ // Returns a promise if it does not have a reject handler.
+ Handle<Object> GetPromiseForUncaughtException();
+
void CallEventCallback(v8::DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data,
v8::Debug::ClientData* client_data);
- void CallCEventCallback(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- v8::Debug::ClientData* client_data);
- void CallJSEventCallback(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data);
- void UpdateState();
-
void ProcessDebugEvent(v8::DebugEvent event,
Handle<JSObject> event_data,
bool auto_continue);
@@ -847,87 +564,210 @@ class Debugger {
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
bool auto_continue);
-
- // Invoke the message handler function.
void InvokeMessageHandler(MessageImpl message);
- inline bool EventActive() {
- // Check whether the message handler was been cleared.
- // TODO(yangguo): handle loading and unloading of the debugger differently.
- // Currently argument event is not used.
- return !ignore_debugger_ && is_active_;
+ static bool CompileDebuggerScript(Isolate* isolate, int index);
+ void ClearOneShot();
+ void ActivateStepIn(StackFrame* frame);
+ void ClearStepIn();
+ void ActivateStepOut(StackFrame* frame);
+ void ClearStepNext();
+ // Returns whether the compile succeeded.
+ void RemoveDebugInfo(Handle<DebugInfo> debug_info);
+ Handle<Object> CheckBreakPoints(Handle<Object> break_point);
+ bool CheckBreakPoint(Handle<Object> break_point_object);
+
+ inline void AssertDebugContext() {
+ ASSERT(isolate_->context() == *debug_context());
+ ASSERT(in_debug_scope());
}
- Handle<Object> event_listener_; // Global handle to listener.
+ void ThreadInit();
+
+ // Global handles.
+ Handle<Context> debug_context_;
+ Handle<Object> event_listener_;
Handle<Object> event_listener_data_;
- bool is_active_;
- bool ignore_debugger_; // Are we temporarily ignoring the debugger?
- bool live_edit_enabled_; // Enable LiveEdit.
+
v8::Debug::MessageHandler message_handler_;
- bool debugger_unload_pending_; // Was message handler cleared?
static const int kQueueInitialSize = 4;
- LockingCommandMessageQueue command_queue_;
Semaphore command_received_; // Signaled for each command received.
+ LockingCommandMessageQueue command_queue_;
LockingCommandMessageQueue event_command_queue_;
+ bool is_active_;
+ bool is_suppressed_;
+ bool live_edit_enabled_;
+ bool has_break_points_;
+ bool break_disabled_;
+ bool break_on_exception_;
+ bool break_on_uncaught_exception_;
+
+ ScriptCache* script_cache_; // Cache of all scripts in the heap.
+ DebugInfoListNode* debug_info_list_; // List of active debug info objects.
+
+ // Storage location for jump when exiting debug break calls.
+ // Note that this address is not GC safe. It should be computed immediately
+ // before returning to the DebugBreakCallHelper.
+ Address after_break_target_;
+
+ // Per-thread data.
+ class ThreadLocal {
+ public:
+ // Top debugger entry.
+ DebugScope* current_debug_scope_;
+
+ // 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_;
+
+ // Number of queued steps left to perform before debug event.
+ int queued_step_count_;
+
+ // 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_;
+
+ // Stores the way how LiveEdit has patched the stack. It is used when
+ // debugger returns control back to user script.
+ LiveEdit::FrameDropMode frame_drop_mode_;
+
+ // When restarter frame is on stack, stores the address
+ // of the pointer to function being restarted. Otherwise (most of the time)
+ // stores NULL. This pointer is used with 'step in' implementation.
+ Object** restarter_frame_function_pointer_;
+
+ // When a promise is being resolved, we may want to trigger a debug event
+ // if we catch a throw. For this purpose we remember the try-catch
+ // handler address that would catch the exception. We also hold onto a
+ // closure that returns a promise if the exception is considered uncaught.
+ // Due to the possibility of reentry we use a linked list.
+ PromiseOnStack* promise_on_stack_;
+ };
+
+ // Storage location for registers when handling debug break calls
+ ThreadLocal thread_local_;
+
Isolate* isolate_;
- friend class EnterDebugger;
friend class Isolate;
+ friend class DebugScope;
+ friend class DisableBreak;
+ friend class SuppressDebug;
+
+ friend Handle<FixedArray> GetDebuggedFunctions(); // In test-debug.cc
+ friend void CheckDebuggerUnloaded(bool check_functions); // In test-debug.cc
- DISALLOW_COPY_AND_ASSIGN(Debugger);
+ DISALLOW_COPY_AND_ASSIGN(Debug);
};
-// This class is used for entering the debugger. Create an instance in the stack
-// to enter the debugger. This will set the current break state, make sure the
-// debugger is loaded and switch to the debugger context. If the debugger for
-// some reason could not be entered FailedToEnter will return true.
-class EnterDebugger BASE_EMBEDDED {
- public:
- explicit EnterDebugger(Isolate* isolate);
- ~EnterDebugger();
+DECLARE_RUNTIME_FUNCTION(Debug_Break);
+
- // Check whether the debugger could be entered.
- inline bool FailedToEnter() { return load_failed_; }
+// This scope is used to load and enter the debug context and create a new
+// break state. Leaving the scope will restore the previous state.
+// On failure to load, FailedToEnter returns true.
+class DebugScope BASE_EMBEDDED {
+ public:
+ explicit DebugScope(Debug* debug);
+ ~DebugScope();
- // Check whether there are any JavaScript frames on the stack.
- inline bool HasJavaScriptFrames() { return has_js_frames_; }
+ // Check whether loading was successful.
+ inline bool failed() { return failed_; }
// Get the active context from before entering the debugger.
inline Handle<Context> GetContext() { return save_.context(); }
private:
- Isolate* isolate_;
- EnterDebugger* prev_; // Previous debugger entry if entered recursively.
- bool has_js_frames_; // Were there any JavaScript frames?
+ Isolate* isolate() { return debug_->isolate_; }
+
+ Debug* debug_;
+ DebugScope* prev_; // Previous scope if entered recursively.
StackFrame::Id break_frame_id_; // Previous break frame id.
- int break_id_; // Previous break id.
- bool load_failed_; // Did the debugger fail to load?
- SaveContext save_; // Saves previous context.
+ int break_id_; // Previous break id.
+ bool failed_; // Did the debug context fail to load?
+ SaveContext save_; // Saves previous context.
};
// Stack allocated class for disabling break.
class DisableBreak BASE_EMBEDDED {
public:
- explicit DisableBreak(Isolate* isolate, bool disable_break)
- : isolate_(isolate) {
- prev_disable_break_ = isolate_->debug()->disable_break();
- isolate_->debug()->set_disable_break(disable_break);
+ explicit DisableBreak(Debug* debug, bool disable_break)
+ : debug_(debug), old_state_(debug->break_disabled_) {
+ debug_->break_disabled_ = disable_break;
}
- ~DisableBreak() {
- isolate_->debug()->set_disable_break(prev_disable_break_);
+ ~DisableBreak() { debug_->break_disabled_ = old_state_; }
+
+ private:
+ Debug* debug_;
+ bool old_state_;
+ DISALLOW_COPY_AND_ASSIGN(DisableBreak);
+};
+
+
+class SuppressDebug BASE_EMBEDDED {
+ public:
+ explicit SuppressDebug(Debug* debug)
+ : debug_(debug), old_state_(debug->is_suppressed_) {
+ debug_->is_suppressed_ = true;
}
+ ~SuppressDebug() { debug_->is_suppressed_ = old_state_; }
private:
- Isolate* isolate_;
- // The previous state of the disable break used to restore the value when this
- // object is destructed.
- bool prev_disable_break_;
+ Debug* debug_;
+ bool old_state_;
+ DISALLOW_COPY_AND_ASSIGN(SuppressDebug);
+};
+
+
+// Code generator routines.
+class DebugCodegen : public AllStatic {
+ public:
+ static void GenerateSlot(MacroAssembler* masm);
+ static void GenerateCallICStubDebugBreak(MacroAssembler* masm);
+ static void GenerateLoadICDebugBreak(MacroAssembler* masm);
+ static void GenerateStoreICDebugBreak(MacroAssembler* masm);
+ static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
+ static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
+ static void GenerateCompareNilICDebugBreak(MacroAssembler* masm);
+ static void GenerateReturnDebugBreak(MacroAssembler* masm);
+ static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
+ static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
+ static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
+ static void GenerateSlotDebugBreak(MacroAssembler* masm);
+ static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
+
+ // FrameDropper is a code replacement for a JavaScript frame with possibly
+ // several frames above.
+ // There is no calling conventions here, because it never actually gets
+ // called, it only gets returned to.
+ static void GenerateFrameDropperLiveEdit(MacroAssembler* masm);
};
+
} } // namespace v8::internal
#endif // V8_DEBUG_H_
« no previous file with comments | « src/compiler.cc ('k') | src/debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698