| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 | 408 |
| 409 | 409 |
| 410 // Check that the debugger has been fully unloaded. | 410 // Check that the debugger has been fully unloaded. |
| 411 void CheckDebuggerUnloaded(bool check_functions) { | 411 void CheckDebuggerUnloaded(bool check_functions) { |
| 412 // Check that the debugger context is cleared and that there is no debug | 412 // Check that the debugger context is cleared and that there is no debug |
| 413 // information stored for the debugger. | 413 // information stored for the debugger. |
| 414 CHECK(Debug::debug_context().is_null()); | 414 CHECK(Debug::debug_context().is_null()); |
| 415 CHECK_EQ(NULL, Debug::debug_info_list_); | 415 CHECK_EQ(NULL, Debug::debug_info_list_); |
| 416 | 416 |
| 417 // Collect garbage to ensure weak handles are cleared. | 417 // Collect garbage to ensure weak handles are cleared. |
| 418 Heap::CollectAllGarbage(false); | 418 Heap::CollectAllGarbage(i::Heap::kNoGCFlags); |
| 419 Heap::CollectAllGarbage(false); | 419 Heap::CollectAllGarbage(i::Heap::kMakeHeapIterableMask); |
| 420 | 420 |
| 421 // Iterate the head and check that there are no debugger related objects left. | 421 // Iterate the head and check that there are no debugger related objects left. |
| 422 HeapIterator iterator; | 422 HeapIterator iterator; |
| 423 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 423 for (HeapObject* obj = iterator.Next(); obj != NULL; obj = iterator.Next()) { |
| 424 CHECK(!obj->IsDebugInfo()); | 424 CHECK(!obj->IsDebugInfo()); |
| 425 CHECK(!obj->IsBreakPointInfo()); | 425 CHECK(!obj->IsBreakPointInfo()); |
| 426 | 426 |
| 427 // If deep check of functions is requested check that no debug break code | 427 // If deep check of functions is requested check that no debug break code |
| 428 // is left in all functions. | 428 // is left in all functions. |
| 429 if (check_functions) { | 429 if (check_functions) { |
| 430 if (obj->IsJSFunction()) { | 430 if (obj->IsJSFunction()) { |
| 431 JSFunction* fun = JSFunction::cast(obj); | 431 JSFunction* fun = JSFunction::cast(obj); |
| 432 for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) { | 432 for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) { |
| 433 RelocInfo::Mode rmode = it.rinfo()->rmode(); | 433 RelocInfo::Mode rmode = it.rinfo()->rmode(); |
| (...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 // Perform a garbage collection when break point is hit and continue. Based | 902 // Perform a garbage collection when break point is hit and continue. Based |
| 903 // on the number of break points hit either scavenge or mark compact | 903 // on the number of break points hit either scavenge or mark compact |
| 904 // collector is used. | 904 // collector is used. |
| 905 if (event == v8::Break) { | 905 if (event == v8::Break) { |
| 906 break_point_hit_count++; | 906 break_point_hit_count++; |
| 907 if (break_point_hit_count % 2 == 0) { | 907 if (break_point_hit_count % 2 == 0) { |
| 908 // Scavenge. | 908 // Scavenge. |
| 909 Heap::CollectGarbage(v8::internal::NEW_SPACE); | 909 Heap::CollectGarbage(v8::internal::NEW_SPACE); |
| 910 } else { | 910 } else { |
| 911 // Mark sweep compact. | 911 // Mark sweep compact. |
| 912 Heap::CollectAllGarbage(true); | 912 Heap::CollectAllGarbage(Heap::kForceCompactionMask); |
| 913 } | 913 } |
| 914 } | 914 } |
| 915 } | 915 } |
| 916 | 916 |
| 917 | 917 |
| 918 // Debug event handler which re-issues a debug break and calls the garbage | 918 // Debug event handler which re-issues a debug break and calls the garbage |
| 919 // collector to have the heap verified. | 919 // collector to have the heap verified. |
| 920 static void DebugEventBreak(v8::DebugEvent event, | 920 static void DebugEventBreak(v8::DebugEvent event, |
| 921 v8::Handle<v8::Object> exec_state, | 921 v8::Handle<v8::Object> exec_state, |
| 922 v8::Handle<v8::Object> event_data, | 922 v8::Handle<v8::Object> event_data, |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 | 1351 |
| 1352 v8::Debug::SetDebugEventListener(NULL); | 1352 v8::Debug::SetDebugEventListener(NULL); |
| 1353 CheckDebuggerUnloaded(); | 1353 CheckDebuggerUnloaded(); |
| 1354 } | 1354 } |
| 1355 | 1355 |
| 1356 | 1356 |
| 1357 // Call the function three times with different garbage collections in between | 1357 // Call the function three times with different garbage collections in between |
| 1358 // and make sure that the break point survives. | 1358 // and make sure that the break point survives. |
| 1359 static void CallAndGC(v8::Local<v8::Object> recv, | 1359 static void CallAndGC(v8::Local<v8::Object> recv, |
| 1360 v8::Local<v8::Function> f, | 1360 v8::Local<v8::Function> f, |
| 1361 bool force_compaction) { | 1361 int gc_flags) { |
| 1362 break_point_hit_count = 0; | 1362 break_point_hit_count = 0; |
| 1363 | 1363 |
| 1364 for (int i = 0; i < 3; i++) { | 1364 for (int i = 0; i < 3; i++) { |
| 1365 // Call function. | 1365 // Call function. |
| 1366 f->Call(recv, 0, NULL); | 1366 f->Call(recv, 0, NULL); |
| 1367 CHECK_EQ(1 + i * 3, break_point_hit_count); | 1367 CHECK_EQ(1 + i * 3, break_point_hit_count); |
| 1368 | 1368 |
| 1369 // Scavenge and call function. | 1369 // Scavenge and call function. |
| 1370 Heap::CollectGarbage(v8::internal::NEW_SPACE); | 1370 Heap::CollectGarbage(v8::internal::NEW_SPACE); |
| 1371 f->Call(recv, 0, NULL); | 1371 f->Call(recv, 0, NULL); |
| 1372 CHECK_EQ(2 + i * 3, break_point_hit_count); | 1372 CHECK_EQ(2 + i * 3, break_point_hit_count); |
| 1373 | 1373 |
| 1374 // Mark sweep (and perhaps compact) and call function. | 1374 // Mark sweep (and perhaps compact) and call function. |
| 1375 Heap::CollectAllGarbage(force_compaction); | 1375 Heap::CollectAllGarbage(gc_flags); |
| 1376 f->Call(recv, 0, NULL); | 1376 f->Call(recv, 0, NULL); |
| 1377 CHECK_EQ(3 + i * 3, break_point_hit_count); | 1377 CHECK_EQ(3 + i * 3, break_point_hit_count); |
| 1378 } | 1378 } |
| 1379 } | 1379 } |
| 1380 | 1380 |
| 1381 | 1381 |
| 1382 static void TestBreakPointSurviveGC(bool force_compaction) { | 1382 static void TestBreakPointSurviveGC(int gc_flags) { |
| 1383 break_point_hit_count = 0; | 1383 break_point_hit_count = 0; |
| 1384 v8::HandleScope scope; | 1384 v8::HandleScope scope; |
| 1385 DebugLocalContext env; | 1385 DebugLocalContext env; |
| 1386 | 1386 |
| 1387 v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, | 1387 v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount, |
| 1388 v8::Undefined()); | 1388 v8::Undefined()); |
| 1389 v8::Local<v8::Function> foo; | 1389 v8::Local<v8::Function> foo; |
| 1390 | 1390 |
| 1391 // Test IC store break point with garbage collection. | 1391 // Test IC store break point with garbage collection. |
| 1392 { | 1392 { |
| 1393 v8::Local<v8::Function> bar = | 1393 v8::Local<v8::Function> bar = |
| 1394 CompileFunction(&env, "function foo(){}", "foo"); | 1394 CompileFunction(&env, "function foo(){}", "foo"); |
| 1395 foo = CompileFunction(&env, "function foo(){bar=0;}", "foo"); | 1395 foo = CompileFunction(&env, "function foo(){bar=0;}", "foo"); |
| 1396 SetBreakPoint(foo, 0); | 1396 SetBreakPoint(foo, 0); |
| 1397 } | 1397 } |
| 1398 CallAndGC(env->Global(), foo, force_compaction); | 1398 CallAndGC(env->Global(), foo, gc_flags); |
| 1399 | 1399 |
| 1400 // Test IC load break point with garbage collection. | 1400 // Test IC load break point with garbage collection. |
| 1401 { | 1401 { |
| 1402 v8::Local<v8::Function> bar = | 1402 v8::Local<v8::Function> bar = |
| 1403 CompileFunction(&env, "function foo(){}", "foo"); | 1403 CompileFunction(&env, "function foo(){}", "foo"); |
| 1404 foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo"); | 1404 foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo"); |
| 1405 SetBreakPoint(foo, 0); | 1405 SetBreakPoint(foo, 0); |
| 1406 } | 1406 } |
| 1407 CallAndGC(env->Global(), foo, force_compaction); | 1407 CallAndGC(env->Global(), foo, gc_flags); |
| 1408 | 1408 |
| 1409 // Test IC call break point with garbage collection. | 1409 // Test IC call break point with garbage collection. |
| 1410 { | 1410 { |
| 1411 v8::Local<v8::Function> bar = | 1411 v8::Local<v8::Function> bar = |
| 1412 CompileFunction(&env, "function foo(){}", "foo"); | 1412 CompileFunction(&env, "function foo(){}", "foo"); |
| 1413 foo = CompileFunction(&env, | 1413 foo = CompileFunction(&env, |
| 1414 "function bar(){};function foo(){bar();}", | 1414 "function bar(){};function foo(){bar();}", |
| 1415 "foo"); | 1415 "foo"); |
| 1416 SetBreakPoint(foo, 0); | 1416 SetBreakPoint(foo, 0); |
| 1417 } | 1417 } |
| 1418 CallAndGC(env->Global(), foo, force_compaction); | 1418 CallAndGC(env->Global(), foo, gc_flags); |
| 1419 | 1419 |
| 1420 // Test return break point with garbage collection. | 1420 // Test return break point with garbage collection. |
| 1421 { | 1421 { |
| 1422 v8::Local<v8::Function> bar = | 1422 v8::Local<v8::Function> bar = |
| 1423 CompileFunction(&env, "function foo(){}", "foo"); | 1423 CompileFunction(&env, "function foo(){}", "foo"); |
| 1424 foo = CompileFunction(&env, "function foo(){}", "foo"); | 1424 foo = CompileFunction(&env, "function foo(){}", "foo"); |
| 1425 SetBreakPoint(foo, 0); | 1425 SetBreakPoint(foo, 0); |
| 1426 } | 1426 } |
| 1427 CallAndGC(env->Global(), foo, force_compaction); | 1427 CallAndGC(env->Global(), foo, gc_flags); |
| 1428 | 1428 |
| 1429 // Test non IC break point with garbage collection. | 1429 // Test non IC break point with garbage collection. |
| 1430 { | 1430 { |
| 1431 v8::Local<v8::Function> bar = | 1431 v8::Local<v8::Function> bar = |
| 1432 CompileFunction(&env, "function foo(){}", "foo"); | 1432 CompileFunction(&env, "function foo(){}", "foo"); |
| 1433 foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo"); | 1433 foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo"); |
| 1434 SetBreakPoint(foo, 0); | 1434 SetBreakPoint(foo, 0); |
| 1435 } | 1435 } |
| 1436 CallAndGC(env->Global(), foo, force_compaction); | 1436 CallAndGC(env->Global(), foo, gc_flags); |
| 1437 | 1437 |
| 1438 | 1438 |
| 1439 v8::Debug::SetDebugEventListener(NULL); | 1439 v8::Debug::SetDebugEventListener(NULL); |
| 1440 CheckDebuggerUnloaded(); | 1440 CheckDebuggerUnloaded(); |
| 1441 } | 1441 } |
| 1442 | 1442 |
| 1443 | 1443 |
| 1444 // Test that a break point can be set at a return store location. | 1444 // Test that a break point can be set at a return store location. |
| 1445 TEST(BreakPointSurviveGC) { | 1445 TEST(BreakPointSurviveGC) { |
| 1446 TestBreakPointSurviveGC(false); | 1446 TestBreakPointSurviveGC(Heap::kNoGCFlags); |
| 1447 TestBreakPointSurviveGC(true); | 1447 TestBreakPointSurviveGC(Heap::kForceCompactionMask); |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 | 1450 |
| 1451 // Test that break points can be set using the global Debug object. | 1451 // Test that break points can be set using the global Debug object. |
| 1452 TEST(BreakPointThroughJavaScript) { | 1452 TEST(BreakPointThroughJavaScript) { |
| 1453 break_point_hit_count = 0; | 1453 break_point_hit_count = 0; |
| 1454 v8::HandleScope scope; | 1454 v8::HandleScope scope; |
| 1455 DebugLocalContext env; | 1455 DebugLocalContext env; |
| 1456 env.ExposeDebug(); | 1456 env.ExposeDebug(); |
| 1457 | 1457 |
| (...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2192 " a = 1; // line 1\n" | 2192 " a = 1; // line 1\n" |
| 2193 "}\n" | 2193 "}\n" |
| 2194 "a = 2; // line 3\n"); | 2194 "a = 2; // line 3\n"); |
| 2195 v8::Local<v8::Function> f; | 2195 v8::Local<v8::Function> f; |
| 2196 { | 2196 { |
| 2197 v8::HandleScope scope; | 2197 v8::HandleScope scope; |
| 2198 v8::Script::Compile(script, v8::String::New("test.html"))->Run(); | 2198 v8::Script::Compile(script, v8::String::New("test.html"))->Run(); |
| 2199 } | 2199 } |
| 2200 f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); | 2200 f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); |
| 2201 | 2201 |
| 2202 Heap::CollectAllGarbage(false); | 2202 Heap::CollectAllGarbage(Heap::kNoGCFlags); |
| 2203 | 2203 |
| 2204 SetScriptBreakPointByNameFromJS("test.html", 3, -1); | 2204 SetScriptBreakPointByNameFromJS("test.html", 3, -1); |
| 2205 | 2205 |
| 2206 // Call f and check that there was no break points. | 2206 // Call f and check that there was no break points. |
| 2207 break_point_hit_count = 0; | 2207 break_point_hit_count = 0; |
| 2208 f->Call(env->Global(), 0, NULL); | 2208 f->Call(env->Global(), 0, NULL); |
| 2209 CHECK_EQ(0, break_point_hit_count); | 2209 CHECK_EQ(0, break_point_hit_count); |
| 2210 | 2210 |
| 2211 // Recompile and run script and check that break point was hit. | 2211 // Recompile and run script and check that break point was hit. |
| 2212 break_point_hit_count = 0; | 2212 break_point_hit_count = 0; |
| (...skipping 4166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6379 break_point_hit_count = 0; | 6379 break_point_hit_count = 0; |
| 6380 script_collected_count = 0; | 6380 script_collected_count = 0; |
| 6381 v8::HandleScope scope; | 6381 v8::HandleScope scope; |
| 6382 DebugLocalContext env; | 6382 DebugLocalContext env; |
| 6383 | 6383 |
| 6384 // Request the loaded scripts to initialize the debugger script cache. | 6384 // Request the loaded scripts to initialize the debugger script cache. |
| 6385 Debug::GetLoadedScripts(); | 6385 Debug::GetLoadedScripts(); |
| 6386 | 6386 |
| 6387 // Do garbage collection to ensure that only the script in this test will be | 6387 // Do garbage collection to ensure that only the script in this test will be |
| 6388 // collected afterwards. | 6388 // collected afterwards. |
| 6389 Heap::CollectAllGarbage(false); | 6389 Heap::CollectAllGarbage(Heap::kNoGCFlags); |
| 6390 | 6390 |
| 6391 script_collected_count = 0; | 6391 script_collected_count = 0; |
| 6392 v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, | 6392 v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent, |
| 6393 v8::Undefined()); | 6393 v8::Undefined()); |
| 6394 { | 6394 { |
| 6395 v8::Script::Compile(v8::String::New("eval('a=1')"))->Run(); | 6395 v8::Script::Compile(v8::String::New("eval('a=1')"))->Run(); |
| 6396 v8::Script::Compile(v8::String::New("eval('a=2')"))->Run(); | 6396 v8::Script::Compile(v8::String::New("eval('a=2')"))->Run(); |
| 6397 } | 6397 } |
| 6398 | 6398 |
| 6399 // Do garbage collection to collect the script above which is no longer | 6399 // Do garbage collection to collect the script above which is no longer |
| 6400 // referenced. | 6400 // referenced. |
| 6401 Heap::CollectAllGarbage(false); | 6401 Heap::CollectAllGarbage(Heap::kNoGCFlags); |
| 6402 | 6402 |
| 6403 CHECK_EQ(2, script_collected_count); | 6403 CHECK_EQ(2, script_collected_count); |
| 6404 | 6404 |
| 6405 v8::Debug::SetDebugEventListener(NULL); | 6405 v8::Debug::SetDebugEventListener(NULL); |
| 6406 CheckDebuggerUnloaded(); | 6406 CheckDebuggerUnloaded(); |
| 6407 } | 6407 } |
| 6408 | 6408 |
| 6409 | 6409 |
| 6410 // Debug event listener which counts the script collected events. | 6410 // Debug event listener which counts the script collected events. |
| 6411 int script_collected_message_count = 0; | 6411 int script_collected_message_count = 0; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 6426 v8::HandleScope scope; | 6426 v8::HandleScope scope; |
| 6427 | 6427 |
| 6428 { // Scope for the DebugLocalContext. | 6428 { // Scope for the DebugLocalContext. |
| 6429 DebugLocalContext env; | 6429 DebugLocalContext env; |
| 6430 | 6430 |
| 6431 // Request the loaded scripts to initialize the debugger script cache. | 6431 // Request the loaded scripts to initialize the debugger script cache. |
| 6432 Debug::GetLoadedScripts(); | 6432 Debug::GetLoadedScripts(); |
| 6433 | 6433 |
| 6434 // Do garbage collection to ensure that only the script in this test will be | 6434 // Do garbage collection to ensure that only the script in this test will be |
| 6435 // collected afterwards. | 6435 // collected afterwards. |
| 6436 Heap::CollectAllGarbage(false); | 6436 Heap::CollectAllGarbage(Heap::kNoGCFlags); |
| 6437 | 6437 |
| 6438 v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler); | 6438 v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler); |
| 6439 { | 6439 { |
| 6440 v8::Script::Compile(v8::String::New("eval('a=1')"))->Run(); | 6440 v8::Script::Compile(v8::String::New("eval('a=1')"))->Run(); |
| 6441 v8::Script::Compile(v8::String::New("eval('a=2')"))->Run(); | 6441 v8::Script::Compile(v8::String::New("eval('a=2')"))->Run(); |
| 6442 } | 6442 } |
| 6443 } | 6443 } |
| 6444 | 6444 |
| 6445 // Do garbage collection to collect the script above which is no longer | 6445 // Do garbage collection to collect the script above which is no longer |
| 6446 // referenced. | 6446 // referenced. |
| 6447 Heap::CollectAllGarbage(false); | 6447 Heap::CollectAllGarbage(Heap::kNoGCFlags); |
| 6448 | 6448 |
| 6449 CHECK_EQ(2, script_collected_message_count); | 6449 CHECK_EQ(2, script_collected_message_count); |
| 6450 | 6450 |
| 6451 v8::Debug::SetMessageHandler2(NULL); | 6451 v8::Debug::SetMessageHandler2(NULL); |
| 6452 } | 6452 } |
| 6453 | 6453 |
| 6454 | 6454 |
| 6455 // Debug event listener which counts the after compile events. | 6455 // Debug event listener which counts the after compile events. |
| 6456 int after_compile_message_count = 0; | 6456 int after_compile_message_count = 0; |
| 6457 static void AfterCompileMessageHandler(const v8::Debug::Message& message) { | 6457 static void AfterCompileMessageHandler(const v8::Debug::Message& message) { |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7195 TestDebugBreakInLoop("for (;;) {", loop_bodies, "}"); | 7195 TestDebugBreakInLoop("for (;;) {", loop_bodies, "}"); |
| 7196 TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}"); | 7196 TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}"); |
| 7197 | 7197 |
| 7198 // Get rid of the debug event listener. | 7198 // Get rid of the debug event listener. |
| 7199 v8::Debug::SetDebugEventListener(NULL); | 7199 v8::Debug::SetDebugEventListener(NULL); |
| 7200 CheckDebuggerUnloaded(); | 7200 CheckDebuggerUnloaded(); |
| 7201 } | 7201 } |
| 7202 | 7202 |
| 7203 | 7203 |
| 7204 #endif // ENABLE_DEBUGGER_SUPPORT | 7204 #endif // ENABLE_DEBUGGER_SUPPORT |
| OLD | NEW |