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