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

Unified Diff: src/debug.cc

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/debug.h ('k') | src/execution.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index 8956e92c7d9628343dedd1721a637de53cb8719e..27225b3b453170f256c5691686c1fc5b33936253 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -31,12 +31,22 @@ namespace v8 {
namespace internal {
Debug::Debug(Isolate* isolate)
- : has_break_points_(false),
- script_cache_(NULL),
- debug_info_list_(NULL),
- disable_break_(false),
+ : debug_context_(Handle<Context>()),
+ event_listener_(Handle<Object>()),
+ event_listener_data_(Handle<Object>()),
+ message_handler_(NULL),
+ command_received_(0),
+ command_queue_(isolate->logger(), kQueueInitialSize),
+ event_command_queue_(isolate->logger(), kQueueInitialSize),
+ is_active_(false),
+ is_suppressed_(false),
+ live_edit_enabled_(true), // TODO(yangguo): set to false by default.
+ has_break_points_(false),
+ break_disabled_(false),
break_on_exception_(false),
break_on_uncaught_exception_(false),
+ script_cache_(NULL),
+ debug_info_list_(NULL),
isolate_(isolate) {
ThreadInit();
}
@@ -70,6 +80,22 @@ BreakLocationIterator::~BreakLocationIterator() {
}
+// Check whether a code stub with the specified major key is a possible break
+// point location when looking for source break locations.
+static bool IsSourceBreakStub(Code* code) {
+ CodeStub::Major major_key = CodeStub::GetMajorKey(code);
+ return major_key == CodeStub::CallFunction;
+}
+
+
+// Check whether a code stub with the specified major key is a possible break
+// location.
+static bool IsBreakStub(Code* code) {
+ CodeStub::Major major_key = CodeStub::GetMajorKey(code);
+ return major_key == CodeStub::CallFunction;
+}
+
+
void BreakLocationIterator::Next() {
DisallowHeapAllocation no_gc;
ASSERT(!RinfoDone());
@@ -119,15 +145,14 @@ void BreakLocationIterator::Next() {
if (IsDebuggerStatement()) {
break_point_++;
return;
- }
- if (type_ == ALL_BREAK_LOCATIONS) {
- if (Debug::IsBreakStub(code)) {
+ } else if (type_ == ALL_BREAK_LOCATIONS) {
+ if (IsBreakStub(code)) {
break_point_++;
return;
}
} else {
ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
- if (Debug::IsSourceBreakStub(code)) {
+ if (IsSourceBreakStub(code)) {
break_point_++;
return;
}
@@ -247,9 +272,7 @@ bool BreakLocationIterator::Done() const {
void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
// If there is not already a real break point here patch code with debug
// break.
- if (!HasBreakPoint()) {
- SetDebugBreak();
- }
+ if (!HasBreakPoint()) SetDebugBreak();
ASSERT(IsDebugBreak() || IsDebuggerStatement());
// Set the break point information.
DebugInfo::SetBreakPoint(debug_info_, code_position(),
@@ -271,9 +294,7 @@ void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
void BreakLocationIterator::SetOneShot() {
// Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) {
- return;
- }
+ if (IsDebuggerStatement()) return;
// If there is a real break point here no more to do.
if (HasBreakPoint()) {
@@ -288,9 +309,7 @@ void BreakLocationIterator::SetOneShot() {
void BreakLocationIterator::ClearOneShot() {
// Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) {
- return;
- }
+ if (IsDebuggerStatement()) return;
// If there is a real break point here no more to do.
if (HasBreakPoint()) {
@@ -306,17 +325,13 @@ void BreakLocationIterator::ClearOneShot() {
void BreakLocationIterator::SetDebugBreak() {
// Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) {
- return;
- }
+ if (IsDebuggerStatement()) return;
// If there is already a break point here just return. This might happen if
// the same code is flooded with break points twice. Flooding the same
// function twice might happen when stepping in a function with an exception
// handler as the handler and the function is the same.
- if (IsDebugBreak()) {
- return;
- }
+ if (IsDebugBreak()) return;
if (RelocInfo::IsJSReturn(rmode())) {
// Patch the frame exit code with a break point.
@@ -334,9 +349,7 @@ void BreakLocationIterator::SetDebugBreak() {
void BreakLocationIterator::ClearDebugBreak() {
// Debugger statement always calls debugger. No need to modify it.
- if (IsDebuggerStatement()) {
- return;
- }
+ if (IsDebuggerStatement()) return;
if (RelocInfo::IsJSReturn(rmode())) {
// Restore the frame exit code.
@@ -424,6 +437,53 @@ bool BreakLocationIterator::IsDebugBreak() {
}
+// Find the builtin to use for invoking the debug break
+static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
+ Isolate* isolate = code->GetIsolate();
+
+ // Find the builtin debug break function matching the calling convention
+ // used by the call site.
+ if (code->is_inline_cache_stub()) {
+ switch (code->kind()) {
+ case Code::CALL_IC:
+ return isolate->builtins()->CallICStub_DebugBreak();
+
+ case Code::LOAD_IC:
+ return isolate->builtins()->LoadIC_DebugBreak();
+
+ case Code::STORE_IC:
+ return isolate->builtins()->StoreIC_DebugBreak();
+
+ case Code::KEYED_LOAD_IC:
+ return isolate->builtins()->KeyedLoadIC_DebugBreak();
+
+ case Code::KEYED_STORE_IC:
+ return isolate->builtins()->KeyedStoreIC_DebugBreak();
+
+ case Code::COMPARE_NIL_IC:
+ return isolate->builtins()->CompareNilIC_DebugBreak();
+
+ default:
+ UNREACHABLE();
+ }
+ }
+ if (RelocInfo::IsConstructCall(mode)) {
+ if (code->has_function_cache()) {
+ return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
+ } else {
+ return isolate->builtins()->CallConstructStub_DebugBreak();
+ }
+ }
+ if (code->kind() == Code::STUB) {
+ ASSERT(code->major_key() == CodeStub::CallFunction);
+ return isolate->builtins()->CallFunctionStub_DebugBreak();
+ }
+
+ UNREACHABLE();
+ return Handle<Code>::null();
+}
+
+
void BreakLocationIterator::SetDebugBreakAtIC() {
// Patch the original code with the current address as the current address
// might have changed by the inline caching since the code was copied.
@@ -436,7 +496,7 @@ void BreakLocationIterator::SetDebugBreakAtIC() {
// Patch the code to invoke the builtin debug break function matching the
// calling convention used by the call site.
- Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
+ Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
rinfo()->set_target_address(dbgbrk_code->entry());
}
}
@@ -504,10 +564,8 @@ void Debug::ThreadInit() {
thread_local_.queued_step_count_ = 0;
thread_local_.step_into_fp_ = 0;
thread_local_.step_out_fp_ = 0;
- thread_local_.after_break_target_ = 0;
// TODO(isolates): frames_are_dropped_?
- thread_local_.debugger_entry_ = NULL;
- thread_local_.has_pending_interrupt_ = false;
+ thread_local_.current_debug_scope_ = NULL;
thread_local_.restarter_frame_function_pointer_ = NULL;
thread_local_.promise_on_stack_ = NULL;
}
@@ -534,31 +592,29 @@ int Debug::ArchiveSpacePerThread() {
}
-// Frame structure (conforms InternalFrame structure):
-// -- code
-// -- SMI maker
-// -- function (slot is called "context")
-// -- frame base
-Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
- Handle<Code> code) {
- ASSERT(bottom_js_frame->is_java_script());
-
- Address fp = bottom_js_frame->fp();
+ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
+ isolate_(isolate),
+ collected_scripts_(10) {
+ Heap* heap = isolate_->heap();
+ HandleScope scope(isolate_);
- // Move function pointer into "context" slot.
- Memory::Object_at(fp + StandardFrameConstants::kContextOffset) =
- Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset);
+ // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
+ // rid of all the cached script wrappers and the second gets rid of the
+ // scripts which are no longer referenced. The second also sweeps precisely,
+ // which saves us doing yet another GC to make the heap iterable.
+ heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
- Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code;
- Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) =
- Smi::FromInt(StackFrame::INTERNAL);
+ // Scan heap for Script objects.
+ HeapIterator iterator(heap);
+ DisallowHeapAllocation no_allocation;
- return reinterpret_cast<Object**>(&Memory::Object_at(
- fp + StandardFrameConstants::kContextOffset));
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
+ if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
+ Add(Handle<Script>(Script::cast(obj)));
+ }
+ }
}
-const int Debug::kFrameDropperFrameSize = 4;
-
void ScriptCache::Add(Handle<Script> script) {
GlobalHandles* global_handles = isolate_->global_handles();
@@ -597,9 +653,9 @@ Handle<FixedArray> ScriptCache::GetScripts() {
void ScriptCache::ProcessCollectedScripts() {
- Debugger* debugger = isolate_->debugger();
+ Debug* debug = isolate_->debug();
for (int i = 0; i < collected_scripts_.length(); i++) {
- debugger->OnScriptCollected(collected_scripts_[i]);
+ debug->OnScriptCollected(collected_scripts_[i]);
}
collected_scripts_.Clear();
}
@@ -746,16 +802,16 @@ bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
bool Debug::Load() {
// Return if debugger is already loaded.
- if (IsLoaded()) return true;
+ if (is_loaded()) return true;
// Bail out if we're already in the process of compiling the native
// JavaScript source code for the debugger.
- if (isolate_->debugger()->ignore_debugger()) return false;
- Debugger::IgnoreScope during_create(isolate_->debugger());
+ if (is_suppressed_) return false;
+ SuppressDebug while_loading(this);
// Disable breakpoints and interrupts while compiling and running the
// debugger scripts including the context creation code.
- DisableBreak disable(isolate_, true);
+ DisableBreak disable(this, true);
PostponeInterruptsScope postpone(isolate_);
// Create the debugger context.
@@ -806,10 +862,13 @@ bool Debug::Load() {
void Debug::Unload() {
// Return debugger is not loaded.
- if (!IsLoaded()) return;
+ if (!is_loaded()) return;
// Clear the script cache.
- DestroyScriptCache();
+ if (script_cache_ != NULL) {
+ delete script_cache_;
+ script_cache_ = NULL;
+ }
// Clear debugger context global handle.
GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
@@ -817,28 +876,21 @@ void Debug::Unload() {
}
-Object* Debug::Break(Arguments args) {
+void Debug::Break(Arguments args, JavaScriptFrame* frame) {
Heap* heap = isolate_->heap();
HandleScope scope(isolate_);
ASSERT(args.length() == 0);
- thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
-
- // Get the top-most JavaScript frame.
- JavaScriptFrameIterator it(isolate_);
- JavaScriptFrame* frame = it.frame();
+ if (live_edit_enabled()) {
+ thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED;
+ }
// Just continue if breaks are disabled or debugger cannot be loaded.
- if (disable_break()) {
- SetAfterBreakTarget(frame);
- return heap->undefined_value();
- }
+ if (break_disabled_) return;
// Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) {
- return heap->undefined_value();
- }
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
// Postpone interrupt during breakpoint processing.
PostponeInterruptsScope postpone(isolate_);
@@ -874,7 +926,8 @@ Object* Debug::Break(Arguments args) {
// If step out is active skip everything until the frame where we need to step
// out to is reached, unless real breakpoint is hit.
- if (StepOutActive() && frame->fp() != step_out_fp() &&
+ if (StepOutActive() &&
+ frame->fp() != thread_local_.step_out_fp_ &&
break_points_hit->IsUndefined() ) {
// Step count should always be 0 for StepOut.
ASSERT(thread_local_.step_count_ == 0);
@@ -897,7 +950,7 @@ Object* Debug::Break(Arguments args) {
PrepareStep(StepNext, step_count, StackFrame::NO_ID);
} else {
// Notify the debug event listeners.
- isolate_->debugger()->OnDebugBreak(break_points_hit, false);
+ OnDebugBreak(break_points_hit, false);
}
} else if (thread_local_.last_step_action_ != StepNone) {
// Hold on to last step action as it is cleared by the call to
@@ -934,40 +987,15 @@ Object* Debug::Break(Arguments args) {
// Set up for the remaining steps.
PrepareStep(step_action, step_count, StackFrame::NO_ID);
}
-
- if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
- SetAfterBreakTarget(frame);
- } else if (thread_local_.frame_drop_mode_ ==
- FRAME_DROPPED_IN_IC_CALL) {
- // We must have been calling IC stub. Do not go there anymore.
- Code* plain_return = isolate_->builtins()->builtin(
- Builtins::kPlainReturn_LiveEdit);
- thread_local_.after_break_target_ = plain_return->entry();
- } else if (thread_local_.frame_drop_mode_ ==
- FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
- // Debug break slot stub does not return normally, instead it manually
- // cleans the stack and jumps. We should patch the jump address.
- Code* plain_return = isolate_->builtins()->builtin(
- Builtins::kFrameDropper_LiveEdit);
- thread_local_.after_break_target_ = plain_return->entry();
- } else if (thread_local_.frame_drop_mode_ ==
- FRAME_DROPPED_IN_DIRECT_CALL) {
- // Nothing to do, after_break_target is not used here.
- } else if (thread_local_.frame_drop_mode_ ==
- FRAME_DROPPED_IN_RETURN_CALL) {
- Code* plain_return = isolate_->builtins()->builtin(
- Builtins::kFrameDropper_LiveEdit);
- thread_local_.after_break_target_ = plain_return->entry();
- } else {
- UNREACHABLE();
- }
-
- return heap->undefined_value();
}
RUNTIME_FUNCTION(Debug_Break) {
- return isolate->debug()->Break(args);
+ // Get the top-most JavaScript frame.
+ JavaScriptFrameIterator it(isolate);
+ isolate->debug()->Break(args, it.frame());
+ isolate->debug()->SetAfterBreakTarget(it.frame());
+ return isolate->heap()->undefined_value();
}
@@ -1248,7 +1276,7 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) {
}
-Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate,
+PromiseOnStack::PromiseOnStack(Isolate* isolate,
PromiseOnStack* prev,
Handle<JSFunction> getter)
: isolate_(isolate), prev_(prev) {
@@ -1259,7 +1287,7 @@ Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate,
}
-Debug::PromiseOnStack::~PromiseOnStack() {
+PromiseOnStack::~PromiseOnStack() {
isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location());
}
@@ -1315,7 +1343,7 @@ void Debug::PrepareStep(StepAction step_action,
PrepareForBreakPoints();
- ASSERT(Debug::InDebugger());
+ ASSERT(in_debug_scope());
// Remember this step action and count.
thread_local_.last_step_action_ = step_action;
@@ -1586,67 +1614,7 @@ bool Debug::IsDebugBreak(Address addr) {
}
-// Check whether a code stub with the specified major key is a possible break
-// point location when looking for source break locations.
-bool Debug::IsSourceBreakStub(Code* code) {
- CodeStub::Major major_key = CodeStub::GetMajorKey(code);
- return major_key == CodeStub::CallFunction;
-}
-
-
-// Check whether a code stub with the specified major key is a possible break
-// location.
-bool Debug::IsBreakStub(Code* code) {
- CodeStub::Major major_key = CodeStub::GetMajorKey(code);
- return major_key == CodeStub::CallFunction;
-}
-
-
-// Find the builtin to use for invoking the debug break
-Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
- Isolate* isolate = code->GetIsolate();
-
- // Find the builtin debug break function matching the calling convention
- // used by the call site.
- if (code->is_inline_cache_stub()) {
- switch (code->kind()) {
- case Code::CALL_IC:
- return isolate->builtins()->CallICStub_DebugBreak();
-
- case Code::LOAD_IC:
- return isolate->builtins()->LoadIC_DebugBreak();
-
- case Code::STORE_IC:
- return isolate->builtins()->StoreIC_DebugBreak();
-
- case Code::KEYED_LOAD_IC:
- return isolate->builtins()->KeyedLoadIC_DebugBreak();
- case Code::KEYED_STORE_IC:
- return isolate->builtins()->KeyedStoreIC_DebugBreak();
-
- case Code::COMPARE_NIL_IC:
- return isolate->builtins()->CompareNilIC_DebugBreak();
-
- default:
- UNREACHABLE();
- }
- }
- if (RelocInfo::IsConstructCall(mode)) {
- if (code->has_function_cache()) {
- return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
- } else {
- return isolate->builtins()->CallConstructStub_DebugBreak();
- }
- }
- if (code->kind() == Code::STUB) {
- ASSERT(code->major_key() == CodeStub::CallFunction);
- return isolate->builtins()->CallFunctionStub_DebugBreak();
- }
-
- UNREACHABLE();
- return Handle<Code>::null();
-}
// Simple function for returning the source positions for active break points.
@@ -1691,18 +1659,6 @@ Handle<Object> Debug::GetSourceBreakLocations(
}
-void Debug::NewBreak(StackFrame::Id break_frame_id) {
- thread_local_.break_frame_id_ = break_frame_id;
- thread_local_.break_id_ = ++thread_local_.break_count_;
-}
-
-
-void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
- thread_local_.break_frame_id_ = break_frame_id;
- thread_local_.break_id_ = break_id;
-}
-
-
// Handle stepping into a function.
void Debug::HandleStepIn(Handle<JSFunction> function,
Handle<Object> holder,
@@ -1723,7 +1679,7 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
// Flood the function with one-shot break points if it is called from where
// step into was requested.
- if (fp == step_in_fp()) {
+ if (fp == thread_local_.step_into_fp_) {
if (function->shared()->bound()) {
// Handle Function.prototype.bind
Debug::FloodBoundFunctionWithOneShot(function);
@@ -1980,7 +1936,7 @@ class ActiveFunctionsRedirector : public ThreadVisitor {
};
-void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
+static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
if (function->code()->kind() == Code::FUNCTION &&
function->code()->has_debug_break_slots()) {
// Nothing to do. Function code already had debug break slots.
@@ -1999,7 +1955,7 @@ void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
}
-void Debug::RecompileAndRelocateSuspendedGenerators(
+static void RecompileAndRelocateSuspendedGenerators(
const List<Handle<JSGeneratorObject> > &generators) {
for (int i = 0; i < generators.length(); i++) {
Handle<JSFunction> fun(generators[i]->function());
@@ -2346,8 +2302,13 @@ void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
- HandleScope scope(isolate_);
+ if (live_edit_enabled()) {
+ after_break_target_ =
+ LiveEdit::AfterBreakTarget(thread_local_.frame_drop_mode_, isolate_);
+ if (after_break_target_ != NULL) return; // LiveEdit did the job.
+ }
+ HandleScope scope(isolate_);
PrepareForBreakPoints();
// Get the executing function in which the debug break occurred.
@@ -2396,18 +2357,17 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
// place in the original code. If not the break point was removed during
// break point processing.
if (break_at_js_return_active) {
- addr += original_code->instruction_start() - code->instruction_start();
+ addr += original_code->instruction_start() - code->instruction_start();
}
// Move back to where the call instruction sequence started.
- thread_local_.after_break_target_ =
- addr - Assembler::kPatchReturnSequenceAddressOffset;
+ after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
} else if (at_debug_break_slot) {
// Address of where the debug break slot starts.
addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
// Continue just after the slot.
- thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
+ after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
} else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
// We now know that there is still a debug break call at the target address,
// so the break point is still there and the original code will hold the
@@ -2419,15 +2379,13 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
// Install jump to the call address in the original code. This will be the
// call which was overwritten by the call to DebugBreakXXX.
- thread_local_.after_break_target_ =
- Assembler::target_address_at(addr, *original_code);
+ after_break_target_ = Assembler::target_address_at(addr, *original_code);
} else {
// There is no longer a break point present. Don't try to look in the
// original code as the running code will have the right address. This takes
// care of the case where the last break point is removed from the function
// and therefore no "original code" is available.
- thread_local_.after_break_target_ =
- Assembler::target_address_at(addr, *code);
+ after_break_target_ = Assembler::target_address_at(addr, *code);
}
}
@@ -2476,9 +2434,9 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
- FrameDropMode mode,
+ LiveEdit::FrameDropMode mode,
Object** restarter_frame_function_pointer) {
- if (mode != CURRENTLY_SET_MODE) {
+ if (mode != LiveEdit::CURRENTLY_SET_MODE) {
thread_local_.frame_drop_mode_ = mode;
}
thread_local_.break_frame_id_ = new_break_frame_id;
@@ -2487,91 +2445,33 @@ void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
}
-const int Debug::FramePaddingLayout::kInitialSize = 1;
-
-
-// Any even value bigger than kInitialSize as needed for stack scanning.
-const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
-
-
bool Debug::IsDebugGlobal(GlobalObject* global) {
- return IsLoaded() && global == debug_context()->global_object();
+ return is_loaded() && global == debug_context()->global_object();
}
void Debug::ClearMirrorCache() {
PostponeInterruptsScope postpone(isolate_);
HandleScope scope(isolate_);
- ASSERT(isolate_->context() == *Debug::debug_context());
+ AssertDebugContext();
// Clear the mirror cache.
- Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("ClearMirrorCache"));
Handle<Object> fun = Object::GetProperty(
- isolate_->global_object(), function_name).ToHandleChecked();
+ isolate_,
+ isolate_->global_object(),
+ "ClearMirrorCache").ToHandleChecked();
ASSERT(fun->IsJSFunction());
- Execution::TryCall(
- Handle<JSFunction>::cast(fun),
- Handle<JSObject>(Debug::debug_context()->global_object()),
- 0,
- NULL);
-}
-
-
-void Debug::CreateScriptCache() {
- Heap* heap = isolate_->heap();
- HandleScope scope(isolate_);
-
- // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
- // rid of all the cached script wrappers and the second gets rid of the
- // scripts which are no longer referenced. The second also sweeps precisely,
- // which saves us doing yet another GC to make the heap iterable.
- heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
-
- ASSERT(script_cache_ == NULL);
- script_cache_ = new ScriptCache(isolate_);
-
- // Scan heap for Script objects.
- int count = 0;
- HeapIterator iterator(heap);
-
- for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
- if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
- script_cache_->Add(Handle<Script>(Script::cast(obj)));
- count++;
- }
- }
-}
-
-
-void Debug::DestroyScriptCache() {
- // Get rid of the script cache if it was created.
- if (script_cache_ != NULL) {
- delete script_cache_;
- script_cache_ = NULL;
- }
-}
-
-
-void Debug::AddScriptToScriptCache(Handle<Script> script) {
- if (script_cache_ != NULL) {
- script_cache_->Add(script);
- }
+ Execution::TryCall(Handle<JSFunction>::cast(fun),
+ Handle<JSObject>(Debug::debug_context()->global_object()),
+ 0,
+ NULL);
}
Handle<FixedArray> Debug::GetLoadedScripts() {
// Create and fill the script cache when the loaded scripts is requested for
// the first time.
- if (script_cache_ == NULL) {
- CreateScriptCache();
- }
-
- // If the script cache is not active just return an empty array.
- ASSERT(script_cache_ != NULL);
- if (script_cache_ == NULL) {
- isolate_->factory()->NewFixedArray(0);
- }
+ if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
// Perform GC to get unreferenced scripts evicted from the cache before
// returning the content.
@@ -2606,66 +2506,41 @@ void Debug::AfterGarbageCollection() {
}
-Debugger::Debugger(Isolate* isolate)
- : event_listener_(Handle<Object>()),
- event_listener_data_(Handle<Object>()),
- is_active_(false),
- ignore_debugger_(false),
- live_edit_enabled_(true),
- message_handler_(NULL),
- command_queue_(isolate->logger(), kQueueInitialSize),
- command_received_(0),
- event_command_queue_(isolate->logger(), kQueueInitialSize),
- isolate_(isolate) {
-}
-
-
-Debugger::~Debugger() {}
-
-
-MaybeHandle<Object> Debugger::MakeJSObject(
- Vector<const char> constructor_name,
- int argc,
- Handle<Object> argv[]) {
- ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
-
+MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
+ int argc,
+ Handle<Object> argv[]) {
+ AssertDebugContext();
// Create the execution state object.
- Handle<String> constructor_str =
- isolate_->factory()->InternalizeUtf8String(constructor_name);
- ASSERT(!constructor_str.is_null());
Handle<Object> constructor = Object::GetProperty(
- isolate_->global_object(), constructor_str).ToHandleChecked();
+ isolate_, isolate_->global_object(), constructor_name).ToHandleChecked();
ASSERT(constructor->IsJSFunction());
if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
- return Execution::TryCall(
- Handle<JSFunction>::cast(constructor),
- Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
- argc,
- argv);
+ return Execution::TryCall(Handle<JSFunction>::cast(constructor),
+ Handle<JSObject>(debug_context()->global_object()),
+ argc,
+ argv);
}
-MaybeHandle<Object> Debugger::MakeExecutionState() {
+MaybeHandle<Object> Debug::MakeExecutionState() {
// Create the execution state object.
- Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
- isolate_->debug()->break_id());
- Handle<Object> argv[] = { break_id };
- return MakeJSObject(CStrVector("MakeExecutionState"), ARRAY_SIZE(argv), argv);
+ Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
+ return MakeJSObject("MakeExecutionState", ARRAY_SIZE(argv), argv);
}
-MaybeHandle<Object> Debugger::MakeBreakEvent(Handle<Object> break_points_hit) {
+MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
Handle<Object> exec_state;
if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new break event object.
Handle<Object> argv[] = { exec_state, break_points_hit };
- return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv);
+ return MakeJSObject("MakeBreakEvent", ARRAY_SIZE(argv), argv);
}
-MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
- bool uncaught,
- Handle<Object> promise) {
+MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
+ bool uncaught,
+ Handle<Object> promise) {
Handle<Object> exec_state;
if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the new exception event object.
@@ -2673,12 +2548,12 @@ MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
exception,
isolate_->factory()->ToBoolean(uncaught),
promise };
- return MakeJSObject(CStrVector("MakeExceptionEvent"), ARRAY_SIZE(argv), argv);
+ return MakeJSObject("MakeExceptionEvent", ARRAY_SIZE(argv), argv);
}
-MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
- bool before) {
+MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
+ bool before) {
Handle<Object> exec_state;
if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the compile event object.
@@ -2686,49 +2561,41 @@ MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
Handle<Object> argv[] = { exec_state,
script_wrapper,
isolate_->factory()->ToBoolean(before) };
- return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv);
+ return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv);
}
-MaybeHandle<Object> Debugger::MakeScriptCollectedEvent(int id) {
+MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) {
Handle<Object> exec_state;
if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>();
// Create the script collected event object.
Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
Handle<Object> argv[] = { exec_state, id_object };
-
- return MakeJSObject(
- CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv);
+ return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv);
}
-void Debugger::OnException(Handle<Object> exception, bool uncaught) {
- HandleScope scope(isolate_);
- Debug* debug = isolate_->debug();
+void Debug::OnException(Handle<Object> exception, bool uncaught) {
+ if (in_debug_scope() || ignore_events()) return;
- // Bail out based on state or if there is no listener for this event
- if (debug->InDebugger()) return;
- if (!Debugger::EventActive()) return;
-
- Handle<Object> promise = debug->GetPromiseForUncaughtException();
+ HandleScope scope(isolate_);
+ Handle<Object> promise = GetPromiseForUncaughtException();
uncaught |= !promise->IsUndefined();
// Bail out if exception breaks are not active
if (uncaught) {
// Uncaught exceptions are reported by either flags.
- if (!(debug->break_on_uncaught_exception() ||
- debug->break_on_exception())) return;
+ if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
} else {
// Caught exceptions are reported is activated.
- if (!debug->break_on_exception()) return;
+ if (!break_on_exception_) return;
}
- // Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) return;
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
// Clear all current stepping setup.
- debug->ClearStepping();
+ ClearStepping();
// Create the event data object.
Handle<Object> event_data;
@@ -2744,19 +2611,14 @@ void Debugger::OnException(Handle<Object> exception, bool uncaught) {
}
-void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
+void Debug::OnDebugBreak(Handle<Object> break_points_hit,
bool auto_continue) {
- HandleScope scope(isolate_);
-
- // Debugger has already been entered by caller.
- ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
-
+ // The caller provided for DebugScope.
+ AssertDebugContext();
// Bail out if there is no listener for this event
- if (!Debugger::EventActive()) return;
-
- // Debugger must be entered in advance.
- ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
+ if (ignore_events()) return;
+ HandleScope scope(isolate_);
// Create the event data object.
Handle<Object> event_data;
// Bail out and don't call debugger if exception.
@@ -2769,16 +2631,12 @@ void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
}
-void Debugger::OnBeforeCompile(Handle<Script> script) {
- HandleScope scope(isolate_);
-
- // Bail out based on state or if there is no listener for this event
- if (isolate_->debug()->InDebugger()) return;
- if (!EventActive()) return;
+void Debug::OnBeforeCompile(Handle<Script> script) {
+ if (in_debug_scope() || ignore_events()) return;
- // Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) return;
+ HandleScope scope(isolate_);
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
// Create the event data object.
Handle<Object> event_data;
@@ -2793,23 +2651,20 @@ void Debugger::OnBeforeCompile(Handle<Script> script) {
// Handle debugger actions when a new script is compiled.
-void Debugger::OnAfterCompile(Handle<Script> script,
- AfterCompileFlags after_compile_flags) {
- HandleScope scope(isolate_);
- Debug* debug = isolate_->debug();
-
+void Debug::OnAfterCompile(Handle<Script> script,
+ AfterCompileFlags after_compile_flags) {
// Add the newly compiled script to the script cache.
- debug->AddScriptToScriptCache(script);
+ if (script_cache_ != NULL) script_cache_->Add(script);
// No more to do if not debugging.
- if (!Debugger::EventActive()) return;
+ if (in_debug_scope() || ignore_events()) return;
+ HandleScope scope(isolate_);
// Store whether in debugger before entering debugger.
- bool in_debugger = debug->InDebugger();
+ bool was_in_scope = in_debug_scope();
- // Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) return;
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
// If debugging there might be script break points registered for this
// script. Make sure that these break points are set.
@@ -2818,7 +2673,7 @@ void Debugger::OnAfterCompile(Handle<Script> script,
Handle<String> update_script_break_points_string =
isolate_->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
- Handle<GlobalObject> debug_global(debug->debug_context()->global_object());
+ Handle<GlobalObject> debug_global(debug_context()->global_object());
Handle<Object> update_script_break_points =
Object::GetProperty(
debug_global, update_script_break_points_string).ToHandleChecked();
@@ -2840,7 +2695,7 @@ void Debugger::OnAfterCompile(Handle<Script> script,
return;
}
// Bail out based on state or if there is no listener for this event
- if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
+ if (was_in_scope && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
// Create the compile state object.
Handle<Object> event_data;
@@ -2852,16 +2707,12 @@ void Debugger::OnAfterCompile(Handle<Script> script,
}
-void Debugger::OnScriptCollected(int id) {
- HandleScope scope(isolate_);
-
- // No more to do if not debugging.
- if (isolate_->debug()->InDebugger()) return;
- if (!Debugger::EventActive()) return;
+void Debug::OnScriptCollected(int id) {
+ if (in_debug_scope() || ignore_events()) return;
- // Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) return;
+ HandleScope scope(isolate_);
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
// Create the script collected state object.
Handle<Object> event_data;
@@ -2875,16 +2726,11 @@ void Debugger::OnScriptCollected(int id) {
}
-void Debugger::ProcessDebugEvent(v8::DebugEvent event,
- Handle<JSObject> event_data,
- bool auto_continue) {
+void Debug::ProcessDebugEvent(v8::DebugEvent event,
+ Handle<JSObject> event_data,
+ bool auto_continue) {
HandleScope scope(isolate_);
- // Clear any pending debug break if this is a real break.
- if (!auto_continue) {
- isolate_->debug()->set_has_pending_interrupt(false);
- }
-
// Create the execution state.
Handle<Object> exec_state;
// Bail out and don't call debugger if exception.
@@ -2919,66 +2765,48 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
}
-void Debugger::CallEventCallback(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- v8::Debug::ClientData* client_data) {
+void Debug::CallEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ v8::Debug::ClientData* client_data) {
if (event_listener_->IsForeign()) {
- CallCEventCallback(event, exec_state, event_data, client_data);
+ // Invoke the C debug event listener.
+ v8::Debug::EventCallback2 callback =
+ FUNCTION_CAST<v8::Debug::EventCallback2>(
+ Handle<Foreign>::cast(event_listener_)->foreign_address());
+ EventDetailsImpl event_details(event,
+ Handle<JSObject>::cast(exec_state),
+ Handle<JSObject>::cast(event_data),
+ event_listener_data_,
+ client_data);
+ callback(event_details);
+ ASSERT(!isolate_->has_scheduled_exception());
} else {
- CallJSEventCallback(event, exec_state, event_data);
+ // Invoke the JavaScript debug event listener.
+ ASSERT(event_listener_->IsJSFunction());
+ Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
+ exec_state,
+ event_data,
+ event_listener_data_ };
+ Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
+ isolate_->global_object(),
+ ARRAY_SIZE(argv),
+ argv);
}
}
-void Debugger::CallCEventCallback(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data,
- v8::Debug::ClientData* client_data) {
- Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
- v8::Debug::EventCallback2 callback =
- FUNCTION_CAST<v8::Debug::EventCallback2>(
- callback_obj->foreign_address());
- EventDetailsImpl event_details(
- event,
- Handle<JSObject>::cast(exec_state),
- Handle<JSObject>::cast(event_data),
- event_listener_data_,
- client_data);
- callback(event_details);
-}
-
-
-void Debugger::CallJSEventCallback(v8::DebugEvent event,
- Handle<Object> exec_state,
- Handle<Object> event_data) {
- ASSERT(event_listener_->IsJSFunction());
- Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
-
- // Invoke the JavaScript debug event listener.
- Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
- exec_state,
- event_data,
- event_listener_data_ };
- Execution::TryCall(fun,
- isolate_->global_object(),
- ARRAY_SIZE(argv),
- argv);
- // Silently ignore exceptions from debug event listeners.
-}
-
-
-Handle<Context> Debugger::GetDebugContext() {
- EnterDebugger debugger(isolate_);
+Handle<Context> Debug::GetDebugContext() {
+ DebugScope debug_scope(this);
// The global handle may be destroyed soon after. Return it reboxed.
- return handle(*isolate_->debug()->debug_context(), isolate_);
+ return handle(*debug_context(), isolate_);
}
-void Debugger::NotifyMessageHandler(v8::DebugEvent event,
- Handle<JSObject> exec_state,
- Handle<JSObject> event_data,
- bool auto_continue) {
+void Debug::NotifyMessageHandler(v8::DebugEvent event,
+ Handle<JSObject> exec_state,
+ Handle<JSObject> event_data,
+ bool auto_continue) {
ASSERT(is_active_);
HandleScope scope(isolate_);
// Process the individual events.
@@ -3008,7 +2836,7 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
// The debug command interrupt flag might have been set when the command was
// added. It should be enough to clear the flag only once while we are in the
// debugger.
- ASSERT(isolate_->debug()->InDebugger());
+ ASSERT(in_debug_scope());
isolate_->stack_guard()->ClearDebugCommand();
// Notify the debugger that a debug event has occurred unless auto continue is
@@ -3026,7 +2854,7 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
// in the queue if any. For script collected events don't even process
// messages in the queue as the execution state might not be what is expected
// by the client.
- if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
+ if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) {
return;
}
@@ -3053,7 +2881,7 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
CommandMessage command = command_queue_.Get();
isolate_->logger()->DebugTag(
"Got request from command queue, in interactive loop.");
- if (!Debugger::is_active()) {
+ if (!is_active()) {
// Delete command text and user data.
command.Dispose();
return;
@@ -3102,12 +2930,12 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
// Return from debug event processing if either the VM is put into the
// running state (through a continue command) or auto continue is active
// and there are no more commands queued.
- } while (!running || HasCommands());
+ } while (!running || has_commands());
}
-void Debugger::SetEventListener(Handle<Object> callback,
- Handle<Object> data) {
+void Debug::SetEventListener(Handle<Object> callback,
+ Handle<Object> data) {
GlobalHandles* global_handles = isolate_->global_handles();
// Remove existing entry.
@@ -3127,10 +2955,10 @@ void Debugger::SetEventListener(Handle<Object> callback,
}
-void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) {
+void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
message_handler_ = handler;
UpdateState();
- if (handler == NULL && isolate_->debug()->InDebugger()) {
+ if (handler == NULL && in_debug_scope()) {
// Send an empty command to the debugger if in a break to make JavaScript
// run again if the debugger is closed.
EnqueueCommandMessage(Vector<const uint16_t>::empty());
@@ -3138,29 +2966,24 @@ void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) {
}
-void Debugger::UpdateState() {
- bool activate = message_handler_ != NULL ||
- !event_listener_.is_null() ||
- isolate_->debug()->InDebugger();
- if (!is_active_ && activate) {
+void Debug::UpdateState() {
+ is_active_ = message_handler_ != NULL || !event_listener_.is_null();
+ if (is_active_ || in_debug_scope()) {
// Note that the debug context could have already been loaded to
// bootstrap test cases.
isolate_->compilation_cache()->Disable();
- activate = isolate_->debug()->Load();
- } else if (is_active_ && !activate) {
+ is_active_ = Load();
+ } else if (is_loaded()) {
isolate_->compilation_cache()->Enable();
- isolate_->debug()->ClearAllBreakPoints();
- isolate_->debug()->Unload();
+ ClearAllBreakPoints();
+ Unload();
}
- is_active_ = activate;
- // At this point the debug context is loaded iff the debugger is active.
- ASSERT(isolate_->debug()->IsLoaded() == is_active_);
}
// Calls the registered debug message handler. This callback is part of the
// public API.
-void Debugger::InvokeMessageHandler(MessageImpl message) {
+void Debug::InvokeMessageHandler(MessageImpl message) {
if (message_handler_ != NULL) message_handler_(message);
}
@@ -3169,8 +2992,8 @@ void Debugger::InvokeMessageHandler(MessageImpl message) {
// a copy of the command string managed by the debugger. Up to this
// point, the command data was managed by the API client. Called
// by the API client thread.
-void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command,
- v8::Debug::ClientData* client_data) {
+void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
+ v8::Debug::ClientData* client_data) {
// Need to cast away const.
CommandMessage message = CommandMessage::New(
Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
@@ -3181,35 +3004,22 @@ void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command,
command_received_.Signal();
// Set the debug command break flag to have the command processed.
- if (!isolate_->debug()->InDebugger()) {
- isolate_->stack_guard()->RequestDebugCommand();
- }
-}
-
-
-bool Debugger::HasCommands() {
- return !command_queue_.IsEmpty();
+ if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
}
-void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
+void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
event_command_queue_.Put(message);
// Set the debug command break flag to have the command processed.
- if (!isolate_->debug()->InDebugger()) {
- isolate_->stack_guard()->RequestDebugCommand();
- }
+ if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
}
-MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun,
- Handle<Object> data) {
- // Enter the debugger.
- EnterDebugger debugger(isolate_);
- if (debugger.FailedToEnter()) {
- return isolate_->factory()->undefined_value();
- }
+MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return isolate_->factory()->undefined_value();
// Create the execution state.
Handle<Object> exec_state;
@@ -3221,80 +3031,109 @@ MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun,
return Execution::Call(
isolate_,
fun,
- Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
- isolate_),
+ Handle<Object>(debug_context()->global_proxy(), isolate_),
ARRAY_SIZE(argv),
argv);
}
-EnterDebugger::EnterDebugger(Isolate* isolate)
- : isolate_(isolate),
- prev_(isolate_->debug()->debugger_entry()),
- save_(isolate_) {
- Debug* debug = isolate_->debug();
+void Debug::HandleDebugBreak() {
+ // Ignore debug break during bootstrapping.
+ if (isolate_->bootstrapper()->IsActive()) return;
+ // Just continue if breaks are disabled.
+ if (break_disabled_) return;
+ // Ignore debug break if debugger is not active.
+ if (!is_active()) return;
+ StackLimitCheck check(isolate_);
+ if (check.HasOverflowed()) return;
+
+ { JavaScriptFrameIterator it(isolate_);
+ ASSERT(!it.done());
+ Object* fun = it.frame()->function();
+ if (fun && fun->IsJSFunction()) {
+ // Don't stop in builtin functions.
+ if (JSFunction::cast(fun)->IsBuiltin()) return;
+ GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
+ // Don't stop in debugger functions.
+ if (IsDebugGlobal(global)) return;
+ }
+ }
+
+ // Collect the break state before clearing the flags.
+ bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
+ !isolate_->stack_guard()->CheckDebugBreak();
+
+ isolate_->stack_guard()->ClearDebugBreak();
+
+ ProcessDebugMessages(debug_command_only);
+}
+
+
+void Debug::ProcessDebugMessages(bool debug_command_only) {
+ isolate_->stack_guard()->ClearDebugCommand();
+
+ StackLimitCheck check(isolate_);
+ if (check.HasOverflowed()) return;
+
+ HandleScope scope(isolate_);
+ DebugScope debug_scope(this);
+ if (debug_scope.failed()) return;
+
+ // Notify the debug event listeners. Indicate auto continue if the break was
+ // a debug command break.
+ OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
+}
+
+
+DebugScope::DebugScope(Debug* debug) : debug_(debug),
+ prev_(debug->debugger_entry()),
+ save_(debug_->isolate_) {
// Link recursive debugger entry.
- debug->set_debugger_entry(this);
+ debug_->thread_local_.current_debug_scope_ = this;
// Store the previous break id and frame id.
- break_id_ = debug->break_id();
- break_frame_id_ = debug->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.
- JavaScriptFrameIterator it(isolate_);
- has_js_frames_ = !it.done();
- debug->NewBreak(has_js_frames_ ? it.frame()->id() : StackFrame::NO_ID);
+ JavaScriptFrameIterator it(isolate());
+ bool has_js_frames = !it.done();
+ debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
+ : StackFrame::NO_ID;
+ debug_->SetNextBreakId();
- isolate_->debugger()->UpdateState();
+ debug_->UpdateState();
// Make sure that debugger is loaded and enter the debugger context.
// The previous context is kept in save_.
- load_failed_ = !debug->IsLoaded();
- if (!load_failed_) isolate_->set_context(*debug->debug_context());
+ failed_ = !debug_->is_loaded();
+ if (!failed_) isolate()->set_context(*debug->debug_context());
}
-EnterDebugger::~EnterDebugger() {
- Debug* debug = isolate_->debug();
-
+DebugScope::~DebugScope() {
// Leaving this debugger entry.
- debug->set_debugger_entry(prev_);
+ debug_->thread_local_.current_debug_scope_ = prev_;
// Restore to the previous break state.
- debug->SetBreak(break_frame_id_, break_id_);
+ debug_->thread_local_.break_frame_id_ = break_frame_id_;
+ debug_->thread_local_.break_id_ = break_id_;
// Check for leaving the debugger.
- if (!load_failed_ && prev_ == NULL) {
+ if (!failed_ && prev_ == NULL) {
// Clear mirror cache when leaving the debugger. Skip this if there is a
// pending exception as clearing the mirror cache calls back into
// JavaScript. This can happen if the v8::Debug::Call is used in which
// case the exception should end up in the calling code.
- if (!isolate_->has_pending_exception()) {
- // Try to avoid any pending debug break breaking in the clear mirror
- // cache JavaScript code.
- if (isolate_->stack_guard()->CheckDebugBreak()) {
- debug->set_has_pending_interrupt(true);
- isolate_->stack_guard()->ClearDebugBreak();
- }
- debug->ClearMirrorCache();
- }
-
- // Request debug break when leaving the last debugger entry
- // if one was recorded while debugging.
- if (debug->has_pending_interrupt()) {
- debug->set_has_pending_interrupt(false);
- isolate_->stack_guard()->RequestDebugBreak();
- }
+ if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
// If there are commands in the queue when leaving the debugger request
// that these commands are processed.
- if (isolate_->debugger()->HasCommands()) {
- isolate_->stack_guard()->RequestDebugCommand();
- }
+ if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
}
- isolate_->debugger()->UpdateState();
+ debug_->UpdateState();
}
@@ -3464,10 +3303,6 @@ CommandMessage::CommandMessage(const Vector<uint16_t>& text,
}
-CommandMessage::~CommandMessage() {
-}
-
-
void CommandMessage::Dispose() {
text_.Dispose();
delete client_data_;
@@ -3488,10 +3323,7 @@ CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
CommandMessageQueue::~CommandMessageQueue() {
- while (!IsEmpty()) {
- CommandMessage m = Get();
- m.Dispose();
- }
+ while (!IsEmpty()) Get().Dispose();
DeleteArray(messages_);
}
« no previous file with comments | « src/debug.h ('k') | src/execution.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698