Commit ceef7cb8 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Make the debugger completely unload when the debug event listener is unregistered.

Added a number of handle scopes to the debugger code to keep handles local to the function using them.

Fixed SetDebugEventListener to actually unregister when passed a NULL pointer. Previously this NULL pointer was wrapped in a Proxy.

BUG=1242702
Review URL: http://codereview.chromium.org/21347

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1269 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent be576757
...@@ -2888,8 +2888,11 @@ bool Debug::SetDebugEventListener(DebugEventCallback that, Handle<Value> data) { ...@@ -2888,8 +2888,11 @@ bool Debug::SetDebugEventListener(DebugEventCallback that, Handle<Value> data) {
EnsureInitialized("v8::Debug::SetDebugEventListener()"); EnsureInitialized("v8::Debug::SetDebugEventListener()");
ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false); ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
HandleScope scope; HandleScope scope;
i::Debugger::SetEventListener(i::Factory::NewProxy(FUNCTION_ADDR(that)), i::Handle<i::Object> proxy = i::Factory::undefined_value();
Utils::OpenHandle(*data)); if (that != NULL) {
proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
}
i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
return true; return true;
} }
......
...@@ -51,6 +51,13 @@ void BreakLocationIterator::ClearDebugBreakAtReturn() { ...@@ -51,6 +51,13 @@ void BreakLocationIterator::ClearDebugBreakAtReturn() {
} }
bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
// Currently debug break is not supported in frame exit code on ARM.
return false;
}
#define __ masm-> #define __ masm->
......
...@@ -37,7 +37,7 @@ namespace v8 { namespace internal { ...@@ -37,7 +37,7 @@ namespace v8 { namespace internal {
// A debug break in the frame exit code is identified by a call instruction. // A debug break in the frame exit code is identified by a call instruction.
bool BreakLocationIterator::IsDebugBreakAtReturn() { bool BreakLocationIterator::IsDebugBreakAtReturn() {
// Opcode E8 is call. // Opcode E8 is call.
return (*(rinfo()->pc()) == 0xE8); return Debug::IsDebugBreakAtReturn(rinfo());
} }
...@@ -59,6 +59,14 @@ void BreakLocationIterator::ClearDebugBreakAtReturn() { ...@@ -59,6 +59,14 @@ void BreakLocationIterator::ClearDebugBreakAtReturn() {
} }
// Check whether the JS frame exit code has been patched with a debug break.
bool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
// Opcode E8 is call.
return (*(rinfo->pc()) == 0xE8);
}
#define __ masm-> #define __ masm->
......
...@@ -314,6 +314,8 @@ void BreakLocationIterator::ClearDebugBreak() { ...@@ -314,6 +314,8 @@ void BreakLocationIterator::ClearDebugBreak() {
void BreakLocationIterator::PrepareStepIn() { void BreakLocationIterator::PrepareStepIn() {
HandleScope scope;
// Step in can only be prepared if currently positioned on an IC call or // Step in can only be prepared if currently positioned on an IC call or
// construct call. // construct call.
Address target = rinfo()->target_address(); Address target = rinfo()->target_address();
...@@ -363,6 +365,17 @@ Object* BreakLocationIterator::BreakPointObjects() { ...@@ -363,6 +365,17 @@ Object* BreakLocationIterator::BreakPointObjects() {
} }
// Clear out all the debug break code. This is ONLY supposed to be used when
// shutting down the debugger as it will leave the break point information in
// DebugInfo even though the code is patched back to the non break point state.
void BreakLocationIterator::ClearAllDebugBreak() {
while (!Done()) {
ClearDebugBreak();
Next();
}
}
bool BreakLocationIterator::RinfoDone() const { bool BreakLocationIterator::RinfoDone() const {
ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
return reloc_iterator_->done(); return reloc_iterator_->done();
...@@ -589,6 +602,9 @@ void Debug::Unload() { ...@@ -589,6 +602,9 @@ void Debug::Unload() {
return; return;
} }
// Get rid of all break points and related information.
ClearAllBreakPoints();
// Clear debugger context global handle. // Clear debugger context global handle.
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
debug_context_ = Handle<Context>(); debug_context_ = Handle<Context>();
...@@ -715,6 +731,8 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { ...@@ -715,6 +731,8 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
// Check whether a single break point object is triggered. // Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
HandleScope scope;
// Ignore check if break point object is not a JSObject. // Ignore check if break point object is not a JSObject.
if (!break_point_object->IsJSObject()) return true; if (!break_point_object->IsJSObject()) return true;
...@@ -765,6 +783,8 @@ Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { ...@@ -765,6 +783,8 @@ Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared, void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
int source_position, int source_position,
Handle<Object> break_point_object) { Handle<Object> break_point_object) {
HandleScope scope;
if (!EnsureDebugInfo(shared)) { if (!EnsureDebugInfo(shared)) {
// Return if retrieving debug info failed. // Return if retrieving debug info failed.
return; return;
...@@ -785,6 +805,8 @@ void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared, ...@@ -785,6 +805,8 @@ void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
void Debug::ClearBreakPoint(Handle<Object> break_point_object) { void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
HandleScope scope;
DebugInfoListNode* node = debug_info_list_; DebugInfoListNode* node = debug_info_list_;
while (node != NULL) { while (node != NULL) {
Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
...@@ -817,6 +839,22 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) { ...@@ -817,6 +839,22 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
} }
void Debug::ClearAllBreakPoints() {
DebugInfoListNode* node = debug_info_list_;
while (node != NULL) {
// Remove all debug break code.
BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
it.ClearAllDebugBreak();
node = node->next();
}
// Remove all debug info.
while (debug_info_list_ != NULL) {
RemoveDebugInfo(debug_info_list_->debug_info());
}
}
void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) { void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
// Make sure the function has setup the debug info. // Make sure the function has setup the debug info.
if (!EnsureDebugInfo(shared)) { if (!EnsureDebugInfo(shared)) {
...@@ -1214,6 +1252,8 @@ void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { ...@@ -1214,6 +1252,8 @@ void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
HandleScope scope;
// Get the executing function in which the debug break occurred. // Get the executing function in which the debug break occurred.
Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared()); Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
...@@ -1289,6 +1329,7 @@ bool Debug::IsDebugGlobal(GlobalObject* global) { ...@@ -1289,6 +1329,7 @@ bool Debug::IsDebugGlobal(GlobalObject* global) {
void Debug::ClearMirrorCache() { void Debug::ClearMirrorCache() {
HandleScope scope;
ASSERT(Top::context() == *Debug::debug_context()); ASSERT(Top::context() == *Debug::debug_context());
// Clear the mirror cache. // Clear the mirror cache.
...@@ -1588,6 +1629,8 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) { ...@@ -1588,6 +1629,8 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
void Debugger::ProcessDebugEvent(v8::DebugEvent event, void Debugger::ProcessDebugEvent(v8::DebugEvent event,
Handle<Object> event_data) { Handle<Object> event_data) {
HandleScope scope;
// Create the execution state. // Create the execution state.
bool caught_exception = false; bool caught_exception = false;
Handle<Object> exec_state = MakeExecutionState(&caught_exception); Handle<Object> exec_state = MakeExecutionState(&caught_exception);
...@@ -1704,6 +1747,9 @@ void Debugger::UpdateActiveDebugger() { ...@@ -1704,6 +1747,9 @@ void Debugger::UpdateActiveDebugger() {
if (!debugger_active() && message_thread_) { if (!debugger_active() && message_thread_) {
message_thread_->OnDebuggerInactive(); message_thread_->OnDebuggerInactive();
} }
if (!debugger_active()) {
Debug::Unload();
}
} }
...@@ -1808,6 +1854,8 @@ void DebugMessageThread::Run() { ...@@ -1808,6 +1854,8 @@ void DebugMessageThread::Run() {
void DebugMessageThread::DebugEvent(v8::DebugEvent event, void DebugMessageThread::DebugEvent(v8::DebugEvent event,
Handle<Object> exec_state, Handle<Object> exec_state,
Handle<Object> event_data) { Handle<Object> event_data) {
HandleScope scope;
if (!Debug::Load()) return; if (!Debug::Load()) return;
// Process the individual events. // Process the individual events.
......
...@@ -89,6 +89,7 @@ class BreakLocationIterator { ...@@ -89,6 +89,7 @@ class BreakLocationIterator {
bool HasBreakPoint(); bool HasBreakPoint();
bool IsDebugBreak(); bool IsDebugBreak();
Object* BreakPointObjects(); Object* BreakPointObjects();
void ClearAllDebugBreak();
inline int code_position() { return pc() - debug_info_->code()->entry(); } inline int code_position() { return pc() - debug_info_->code()->entry(); }
...@@ -172,6 +173,7 @@ class Debug { ...@@ -172,6 +173,7 @@ class Debug {
int source_position, int source_position,
Handle<Object> break_point_object); Handle<Object> break_point_object);
static void ClearBreakPoint(Handle<Object> break_point_object); static void ClearBreakPoint(Handle<Object> break_point_object);
static void ClearAllBreakPoints();
static void FloodWithOneShot(Handle<SharedFunctionInfo> shared); static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
static void FloodHandlerWithOneShot(); static void FloodHandlerWithOneShot();
static void ChangeBreakOnException(ExceptionBreakType type, bool enable); static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
...@@ -186,6 +188,7 @@ class Debug { ...@@ -186,6 +188,7 @@ class Debug {
static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared); static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
static bool IsDebugBreak(Address addr); static bool IsDebugBreak(Address addr);
static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
// Check whether a code stub with the specified major key is a possible break // Check whether a code stub with the specified major key is a possible break
// point location. // point location.
...@@ -257,6 +260,7 @@ class Debug { ...@@ -257,6 +260,7 @@ class Debug {
friend class Debugger; friend class Debugger;
friend Handle<FixedArray> GetDebuggedFunctions(); // Found in test-debug.cc friend Handle<FixedArray> GetDebuggedFunctions(); // Found in test-debug.cc
friend void CheckDebuggerUnloaded(bool); // Found in test-debug.cc
// Threading support. // Threading support.
static char* ArchiveDebug(char* to); static char* ArchiveDebug(char* to);
......
This diff is collapsed.
...@@ -153,9 +153,11 @@ assertFalse(exception, "exception in listener") ...@@ -153,9 +153,11 @@ assertFalse(exception, "exception in listener")
// Remove the debug event listener. // Remove the debug event listener.
Debug.setListener(null); Debug.setListener(null);
// Add debug event listener wich uses recursive breaks. // Set debug event listener wich uses recursive breaks.
listenerComplete = false;
Debug.setListener(listener_recurse); Debug.setListener(listener_recurse);
listenerComplete = false;
Debug.setBreakPoint(f, 2, 0);
debugger; debugger;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment