Clear function breakpoints in Debug::HandleWeakDebugInfo callback.
authorpodivilov@chromium.org <podivilov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Jul 2010 11:48:45 +0000 (11:48 +0000)
committerpodivilov@chromium.org <podivilov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Jul 2010 11:48:45 +0000 (11:48 +0000)
When removing debug_info from SharedFunctionInfo, clear all breakpoints associated with that debug_info.
This is needed because function will live in heap until next gc, and therefore can be found
by Runtime::FindSharedFunctionInfoInScript.

Review URL: http://codereview.chromium.org/2848032

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4997 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/debug.cc
test/cctest/test-debug.cc

index f7c06f0..1dc6275 100644 (file)
@@ -684,6 +684,12 @@ void Debug::Setup(bool create_heap_objects) {
 
 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
   DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
+  // We need to clear all breakpoints associated with the function to restore
+  // original code and avoid patching the code twice later because
+  // the function will live in the heap until next gc, and can be found by
+  // Runtime::FindSharedFunctionInfoInScript.
+  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
+  it.ClearAllDebugBreak();
   RemoveDebugInfo(node->debug_info());
 #ifdef DEBUG
   node = Debug::debug_info_list_;
index e689637..8ebf752 100644 (file)
@@ -2075,6 +2075,39 @@ TEST(ScriptBreakPointLineTopLevel) {
 }
 
 
+// Test that it is possible to add and remove break points in a top level
+// function which has no references but has not been collected yet.
+TEST(ScriptBreakPointTopLevelCrash) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script_source = v8::String::New(
+    "function f() {\n"
+    "  return 0;\n"
+    "}\n"
+    "f()");
+
+  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 3, -1);
+  {
+    v8::HandleScope scope;
+    break_point_hit_count = 0;
+    v8::Script::Compile(script_source, v8::String::New("test.html"))->Run();
+    CHECK_EQ(1, break_point_hit_count);
+  }
+
+  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 3, -1);
+  ClearBreakPointFromJS(sbp1);
+  ClearBreakPointFromJS(sbp2);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 // Test that it is possible to remove the last break point for a function
 // inside the break handling of that break point.
 TEST(RemoveBreakPointInBreak) {
@@ -2129,7 +2162,7 @@ TEST(DebuggerStatement) {
 }
 
 
-// Test setting a breakpoint on the  debugger statement.
+// Test setting a breakpoint on the debugger statement.
 TEST(DebuggerStatementBreakpoint) {
     break_point_hit_count = 0;
     v8::HandleScope scope;