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) {
EnsureInitialized("v8::Debug::SetDebugEventListener()");
ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
HandleScope scope;
i::Debugger::SetEventListener(i::Factory::NewProxy(FUNCTION_ADDR(that)),
Utils::OpenHandle(*data));
i::Handle<i::Object> proxy = i::Factory::undefined_value();
if (that != NULL) {
proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
}
i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
return true;
}
......
......@@ -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->
......
......@@ -37,7 +37,7 @@ namespace v8 { namespace internal {
// A debug break in the frame exit code is identified by a call instruction.
bool BreakLocationIterator::IsDebugBreakAtReturn() {
// Opcode E8 is call.
return (*(rinfo()->pc()) == 0xE8);
return Debug::IsDebugBreakAtReturn(rinfo());
}
......@@ -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->
......
......@@ -314,6 +314,8 @@ void BreakLocationIterator::ClearDebugBreak() {
void BreakLocationIterator::PrepareStepIn() {
HandleScope scope;
// Step in can only be prepared if currently positioned on an IC call or
// construct call.
Address target = rinfo()->target_address();
......@@ -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 {
ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
return reloc_iterator_->done();
......@@ -589,6 +602,9 @@ void Debug::Unload() {
return;
}
// Get rid of all break points and related information.
ClearAllBreakPoints();
// Clear debugger context global handle.
GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
debug_context_ = Handle<Context>();
......@@ -715,6 +731,8 @@ Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
// Check whether a single break point object is triggered.
bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
HandleScope scope;
// Ignore check if break point object is not a JSObject.
if (!break_point_object->IsJSObject()) return true;
......@@ -765,6 +783,8 @@ Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
int source_position,
Handle<Object> break_point_object) {
HandleScope scope;
if (!EnsureDebugInfo(shared)) {
// Return if retrieving debug info failed.
return;
......@@ -785,6 +805,8 @@ void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
HandleScope scope;
DebugInfoListNode* node = debug_info_list_;
while (node != NULL) {
Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
......@@ -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) {
// Make sure the function has setup the debug info.
if (!EnsureDebugInfo(shared)) {
......@@ -1214,6 +1252,8 @@ void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
HandleScope scope;
// Get the executing function in which the debug break occurred.
Handle<SharedFunctionInfo> shared =
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
......@@ -1289,6 +1329,7 @@ bool Debug::IsDebugGlobal(GlobalObject* global) {
void Debug::ClearMirrorCache() {
HandleScope scope;
ASSERT(Top::context() == *Debug::debug_context());
// Clear the mirror cache.
......@@ -1588,6 +1629,8 @@ void Debugger::OnNewFunction(Handle<JSFunction> function) {
void Debugger::ProcessDebugEvent(v8::DebugEvent event,
Handle<Object> event_data) {
HandleScope scope;
// Create the execution state.
bool caught_exception = false;
Handle<Object> exec_state = MakeExecutionState(&caught_exception);
......@@ -1704,6 +1747,9 @@ void Debugger::UpdateActiveDebugger() {
if (!debugger_active() && message_thread_) {
message_thread_->OnDebuggerInactive();
}
if (!debugger_active()) {
Debug::Unload();
}
}
......@@ -1808,6 +1854,8 @@ void DebugMessageThread::Run() {
void DebugMessageThread::DebugEvent(v8::DebugEvent event,
Handle<Object> exec_state,
Handle<Object> event_data) {
HandleScope scope;
if (!Debug::Load()) return;
// Process the individual events.
......
......@@ -89,6 +89,7 @@ class BreakLocationIterator {
bool HasBreakPoint();
bool IsDebugBreak();
Object* BreakPointObjects();
void ClearAllDebugBreak();
inline int code_position() { return pc() - debug_info_->code()->entry(); }
......@@ -172,6 +173,7 @@ class Debug {
int source_position,
Handle<Object> break_point_object);
static void ClearBreakPoint(Handle<Object> break_point_object);
static void ClearAllBreakPoints();
static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
static void FloodHandlerWithOneShot();
static void ChangeBreakOnException(ExceptionBreakType type, bool enable);
......@@ -186,6 +188,7 @@ class Debug {
static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
static bool IsDebugBreak(Address addr);
static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
// Check whether a code stub with the specified major key is a possible break
// point location.
......@@ -257,6 +260,7 @@ class Debug {
friend class Debugger;
friend Handle<FixedArray> GetDebuggedFunctions(); // Found in test-debug.cc
friend void CheckDebuggerUnloaded(bool); // Found in test-debug.cc
// Threading support.
static char* ArchiveDebug(char* to);
......
This diff is collapsed.
......@@ -153,9 +153,11 @@ assertFalse(exception, "exception in listener")
// Remove the debug event listener.
Debug.setListener(null);
// Add debug event listener wich uses recursive breaks.
listenerComplete = false;
// Set debug event listener wich uses recursive breaks.
Debug.setListener(listener_recurse);
listenerComplete = false;
Debug.setBreakPoint(f, 2, 0);
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