Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Tests of logging functions from log.h | 3 // Tests of logging functions from log.h |
| 4 | 4 |
| 5 #ifdef ENABLE_LOGGING_AND_PROFILING | 5 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 6 | 6 |
| 7 #include "v8.h" | 7 #include "v8.h" |
| 8 | 8 |
| 9 #include "log.h" | 9 #include "log.h" |
| 10 #include "cctest.h" | 10 #include "cctest.h" |
| 11 | 11 |
| 12 using v8::internal::Address; | 12 using v8::internal::Address; |
| 13 using v8::internal::EmbeddedVector; | |
| 13 using v8::internal::Logger; | 14 using v8::internal::Logger; |
| 14 | 15 |
| 15 namespace i = v8::internal; | 16 namespace i = v8::internal; |
| 16 | 17 |
| 17 static void SetUp() { | 18 static void SetUp() { |
| 18 // Log to memory buffer. | 19 // Log to memory buffer. |
| 19 i::FLAG_logfile = "*"; | 20 i::FLAG_logfile = "*"; |
| 20 i::FLAG_log = true; | 21 i::FLAG_log = true; |
| 21 Logger::Setup(); | 22 Logger::Setup(); |
| 22 } | 23 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len)); | 78 CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len)); |
| 78 CHECK_EQ(all_lines, log_lines); | 79 CHECK_EQ(all_lines, log_lines); |
| 79 memset(log_lines, 0, sizeof(log_lines)); | 80 memset(log_lines, 0, sizeof(log_lines)); |
| 80 CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3)); | 81 CHECK_EQ(all_lines_len, Logger::GetLogLines(0, log_lines, all_lines_len + 3)); |
| 81 CHECK_EQ(all_lines, log_lines); | 82 CHECK_EQ(all_lines, log_lines); |
| 82 memset(log_lines, 0, sizeof(log_lines)); | 83 memset(log_lines, 0, sizeof(log_lines)); |
| 83 TearDown(); | 84 TearDown(); |
| 84 } | 85 } |
| 85 | 86 |
| 86 | 87 |
| 88 template <typename T> | |
|
Søren Thygesen Gjesse
2009/05/25 07:09:15
Why is this a template function? T needs to be cha
Mikhail Naganov
2009/05/25 08:23:43
Yep, you're right. Fixed.
| |
| 89 static int GetLogLines(int start_pos, i::Vector<T>* buffer) { | |
| 90 return Logger::GetLogLines(start_pos, buffer->start(), buffer->length()); | |
| 91 } | |
| 92 | |
| 93 | |
| 87 TEST(BeyondWritePosition) { | 94 TEST(BeyondWritePosition) { |
| 88 SetUp(); | 95 SetUp(); |
| 89 Logger::StringEvent("aaa", "bbb"); | 96 Logger::StringEvent("aaa", "bbb"); |
| 90 Logger::StringEvent("cccc", "dddd"); | 97 Logger::StringEvent("cccc", "dddd"); |
| 91 // See Logger::StringEvent. | 98 // See Logger::StringEvent. |
| 92 const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n"; | 99 const char* all_lines = "aaa,\"bbb\"\ncccc,\"dddd\"\n"; |
| 93 const int all_lines_len = strlen(all_lines); | 100 const int all_lines_len = strlen(all_lines); |
| 94 CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 1)); | 101 EmbeddedVector<char, 100> buffer; |
| 95 CHECK_EQ(0, Logger::GetLogLines(all_lines_len, NULL, 100)); | 102 const int beyond_write_pos = all_lines_len; |
| 96 CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 1)); | 103 CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos, buffer.start(), 1)); |
| 97 CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 1, NULL, 100)); | 104 CHECK_EQ(0, GetLogLines(beyond_write_pos, &buffer)); |
| 98 CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 1)); | 105 CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 1, buffer.start(), 1)); |
| 99 CHECK_EQ(0, Logger::GetLogLines(all_lines_len + 100, NULL, 100)); | 106 CHECK_EQ(0, GetLogLines(beyond_write_pos + 1, &buffer)); |
| 100 CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 1)); | 107 CHECK_EQ(0, Logger::GetLogLines(beyond_write_pos + 100, buffer.start(), 1)); |
| 101 CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, NULL, 100)); | 108 CHECK_EQ(0, GetLogLines(beyond_write_pos + 100, &buffer)); |
| 109 CHECK_EQ(0, Logger::GetLogLines(10 * 1024 * 1024, buffer.start(), 1)); | |
| 110 CHECK_EQ(0, GetLogLines(10 * 1024 * 1024, &buffer)); | |
| 102 TearDown(); | 111 TearDown(); |
| 103 } | 112 } |
| 104 | 113 |
| 105 | 114 |
| 106 TEST(MemoryLoggingTurnedOff) { | 115 TEST(MemoryLoggingTurnedOff) { |
| 107 // Log to stdout | 116 // Log to stdout |
| 108 i::FLAG_logfile = "-"; | 117 i::FLAG_logfile = "-"; |
| 109 i::FLAG_log = true; | 118 i::FLAG_log = true; |
| 110 Logger::Setup(); | 119 Logger::Setup(); |
| 111 CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0)); | 120 CHECK_EQ(0, Logger::GetLogLines(0, NULL, 0)); |
| 112 CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0)); | 121 CHECK_EQ(0, Logger::GetLogLines(100, NULL, 0)); |
| 113 CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100)); | 122 CHECK_EQ(0, Logger::GetLogLines(0, NULL, 100)); |
| 114 CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100)); | 123 CHECK_EQ(0, Logger::GetLogLines(100, NULL, 100)); |
| 115 Logger::TearDown(); | 124 Logger::TearDown(); |
| 116 } | 125 } |
| 117 | 126 |
| 118 | 127 |
| 128 static void CompileAndRunScript(const char *src) { | |
| 129 v8::Script::Compile(v8::String::New(src))->Run(); | |
| 130 } | |
| 131 | |
| 132 | |
| 133 namespace v8 { | |
| 134 namespace internal { | |
| 135 | |
| 136 class LoggerTestHelper : public AllStatic { | |
| 137 public: | |
| 138 static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); } | |
| 139 }; | |
| 140 | |
| 141 } // namespace v8::internal | |
| 142 } // namespace v8 | |
| 143 | |
| 144 using v8::internal::LoggerTestHelper; | |
| 145 | |
| 146 | |
| 147 static int CheckThatProfilerWorks(int log_pos) { | |
| 148 Logger::ResumeProfiler(); | |
| 149 CHECK(LoggerTestHelper::IsSamplerActive()); | |
| 150 | |
| 151 // Verify that the current map of compiled functions has been logged. | |
| 152 EmbeddedVector<char, 102400> buffer; | |
| 153 int map_log_size = GetLogLines(log_pos, &buffer); | |
| 154 printf("map_log_size: %d\n", map_log_size); | |
| 155 CHECK_GT(map_log_size, 0); | |
| 156 CHECK_GT(buffer.length(), map_log_size); | |
| 157 log_pos += map_log_size; | |
| 158 // Check buffer contents. | |
| 159 buffer[map_log_size] = '\0'; | |
| 160 const char* code_creation = "\ncode-creation,"; // eq. to /^code-creation,/ | |
| 161 CHECK_NE(NULL, strstr(buffer.start(), code_creation)); | |
| 162 | |
| 163 // Force compiler to generate new code by parametrizing source. | |
| 164 EmbeddedVector<char, 100> script_src; | |
| 165 i::OS::SNPrintF(script_src, | |
| 166 "for (var i = 0; i < 1000; ++i) { " | |
| 167 "(function(x) { return %d * x; })(i); }", | |
| 168 log_pos); | |
| 169 // Run code for 100 msecs to get some ticks. | |
| 170 const int64_t started_us = i::OS::Ticks(); | |
| 171 while (i::OS::Ticks() - started_us < 100 * 1000) { | |
| 172 CompileAndRunScript(script_src.start()); | |
| 173 } | |
| 174 | |
| 175 Logger::PauseProfiler(); | |
| 176 CHECK(!LoggerTestHelper::IsSamplerActive()); | |
| 177 | |
| 178 // Now we must have compiler and tick records. | |
| 179 int log_size = GetLogLines(log_pos, &buffer); | |
| 180 printf("log_size: %d\n", log_size); | |
| 181 CHECK_GT(log_size, 0); | |
| 182 CHECK_GT(buffer.length(), log_size); | |
| 183 log_pos += log_size; | |
| 184 // Check buffer contents. | |
| 185 buffer[log_size] = '\0'; | |
| 186 const char* tick = "\ntick,"; | |
| 187 CHECK_NE(NULL, strstr(buffer.start(), code_creation)); | |
| 188 CHECK_NE(NULL, strstr(buffer.start(), tick)); | |
| 189 | |
| 190 return log_pos; | |
| 191 } | |
| 192 | |
| 193 | |
| 194 TEST(ProfLazyMode) { | |
| 195 const bool saved_prof_lazy = i::FLAG_prof_lazy; | |
| 196 const bool saved_prof = i::FLAG_prof; | |
| 197 const bool saved_prof_auto = i::FLAG_prof_auto; | |
| 198 i::FLAG_prof = true; | |
| 199 i::FLAG_prof_lazy = true; | |
| 200 i::FLAG_prof_auto = false; | |
| 201 i::FLAG_logfile = "*"; | |
| 202 | |
| 203 // If tests are being run manually, V8 will be already initialized | |
| 204 // by the test below. | |
| 205 const bool need_to_set_up_logger = i::V8::HasBeenSetup(); | |
| 206 v8::HandleScope scope; | |
| 207 v8::Handle<v8::Context> env = v8::Context::New(); | |
| 208 if (need_to_set_up_logger) Logger::Setup(); | |
| 209 env->Enter(); | |
| 210 | |
| 211 // No sampling should happen prior to resuming profiler. | |
| 212 CHECK(!LoggerTestHelper::IsSamplerActive()); | |
| 213 | |
| 214 // Read initial logged data (static libs map). | |
| 215 EmbeddedVector<char, 102400> buffer; | |
| 216 int log_pos = GetLogLines(0, &buffer); | |
| 217 CHECK_GT(log_pos, 0); | |
| 218 CHECK_GT(buffer.length(), log_pos); | |
| 219 | |
| 220 CompileAndRunScript("var a = (function(x) { return x + 1; })(10);"); | |
| 221 | |
| 222 // Nothing must be logged while profiling is suspended. | |
| 223 CHECK_EQ(0, GetLogLines(log_pos, &buffer)); | |
| 224 | |
| 225 log_pos = CheckThatProfilerWorks(log_pos); | |
| 226 | |
| 227 CompileAndRunScript("var a = (function(x) { return x + 1; })(10);"); | |
| 228 | |
| 229 // No new data beyond last retrieved position. | |
| 230 CHECK_EQ(0, GetLogLines(log_pos, &buffer)); | |
| 231 | |
| 232 // Check that profiling can be resumed again. | |
| 233 CheckThatProfilerWorks(log_pos); | |
| 234 | |
| 235 env->Exit(); | |
| 236 Logger::TearDown(); | |
| 237 i::FLAG_prof_lazy = saved_prof_lazy; | |
| 238 i::FLAG_prof = saved_prof; | |
| 239 i::FLAG_prof_auto = saved_prof_auto; | |
| 240 } | |
| 241 | |
| 242 | |
| 119 static inline bool IsStringEqualTo(const char* r, const char* s) { | 243 static inline bool IsStringEqualTo(const char* r, const char* s) { |
| 120 return strncmp(r, s, strlen(r)) == 0; | 244 return strncmp(r, s, strlen(r)) == 0; |
| 121 } | 245 } |
| 122 | 246 |
| 123 | 247 |
| 124 static bool Consume(const char* str, char** buf) { | 248 static bool Consume(const char* str, char** buf) { |
| 125 if (IsStringEqualTo(str, *buf)) { | 249 if (IsStringEqualTo(str, *buf)) { |
| 126 *buf += strlen(str); | 250 *buf += strlen(str); |
| 127 return true; | 251 return true; |
| 128 } | 252 } |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 const char* args_count = "\"args_count:"; | 604 const char* args_count = "\"args_count:"; |
| 481 return IsStringEqualTo(args_count, ref_e); | 605 return IsStringEqualTo(args_count, ref_e); |
| 482 } | 606 } |
| 483 return false; | 607 return false; |
| 484 } | 608 } |
| 485 | 609 |
| 486 | 610 |
| 487 // Test that logging of code create / move / delete events | 611 // Test that logging of code create / move / delete events |
| 488 // is equivalent to traversal of a resulting heap. | 612 // is equivalent to traversal of a resulting heap. |
| 489 TEST(EquivalenceOfLoggingAndTraversal) { | 613 TEST(EquivalenceOfLoggingAndTraversal) { |
| 614 // This test needs to be run on a "clean" V8 to ensure that snapshot log | |
| 615 // is loaded. This is always true when running using tools/test.py because | |
| 616 // it launches a new cctest instance for every test. To be sure that launching | |
| 617 // cctest manually also works, please be sure that no tests below | |
| 618 // are using V8. | |
| 619 // | |
| 620 // P.S. No, V8 can't be re-initialized after disposal, see include/v8.h. | |
| 621 CHECK(!i::V8::HasBeenSetup()); | |
| 622 | |
| 490 i::FLAG_logfile = "*"; | 623 i::FLAG_logfile = "*"; |
| 491 i::FLAG_log = true; | 624 i::FLAG_log = true; |
| 492 i::FLAG_log_code = true; | 625 i::FLAG_log_code = true; |
| 493 | 626 |
| 494 // Make sure objects move. | 627 // Make sure objects move. |
| 495 bool saved_always_compact = i::FLAG_always_compact; | 628 bool saved_always_compact = i::FLAG_always_compact; |
| 496 if (!i::FLAG_never_compact) { | 629 if (!i::FLAG_never_compact) { |
| 497 i::FLAG_always_compact = true; | 630 i::FLAG_always_compact = true; |
| 498 } | 631 } |
| 499 | 632 |
| 500 v8::HandleScope scope; | 633 v8::HandleScope scope; |
| 501 v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>(); | 634 v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>(); |
| 502 v8::Persistent<v8::Context> env = v8::Context::New( | 635 v8::Handle<v8::Context> env = v8::Context::New( |
| 503 0, v8::Handle<v8::ObjectTemplate>(), global_object); | 636 0, v8::Handle<v8::ObjectTemplate>(), global_object); |
| 504 env->Enter(); | 637 env->Enter(); |
| 505 | 638 |
| 506 // Compile and run a function that creates other functions. | 639 // Compile and run a function that creates other functions. |
| 507 v8::Local<v8::Script> script = v8::Script::Compile(v8::String::New( | 640 CompileAndRunScript( |
| 508 "(function f(obj) {\n" | 641 "(function f(obj) {\n" |
| 509 " obj.test =\n" | 642 " obj.test =\n" |
| 510 " (function a(j) { return function b() { return j; } })(100);\n" | 643 " (function a(j) { return function b() { return j; } })(100);\n" |
| 511 "})(this);")); | 644 "})(this);"); |
| 512 script->Run(); | |
| 513 i::Heap::CollectAllGarbage(); | 645 i::Heap::CollectAllGarbage(); |
| 514 | 646 |
| 515 i::EmbeddedVector<char, 204800> buffer; | 647 EmbeddedVector<char, 204800> buffer; |
| 516 int log_size; | 648 int log_size; |
| 517 ParseLogResult ref_result; | 649 ParseLogResult ref_result; |
| 518 | 650 |
| 519 // Retrieve the log. | 651 // Retrieve the log. |
| 520 { | 652 { |
| 521 // Make sure that no GCs occur prior to LogCompiledFunctions call. | 653 // Make sure that no GCs occur prior to LogCompiledFunctions call. |
| 522 i::AssertNoAllocation no_alloc; | 654 i::AssertNoAllocation no_alloc; |
| 523 | 655 |
| 524 log_size = Logger::GetLogLines(0, buffer.start(), buffer.length()); | 656 log_size = GetLogLines(0, &buffer); |
| 525 CHECK_GT(log_size, 0); | 657 CHECK_GT(log_size, 0); |
| 526 CHECK_GT(buffer.length(), log_size); | 658 CHECK_GT(buffer.length(), log_size); |
| 527 | 659 |
| 528 // Fill a map of compiled code objects. | 660 // Fill a map of compiled code objects. |
| 529 ParseLog(buffer.start(), buffer.start() + log_size, &ref_result); | 661 ParseLog(buffer.start(), buffer.start() + log_size, &ref_result); |
| 530 } | 662 } |
| 531 | 663 |
| 532 // Iterate heap to find compiled functions, will write to log. | 664 // Iterate heap to find compiled functions, will write to log. |
| 533 i::Logger::LogCompiledFunctions(); | 665 i::Logger::LogCompiledFunctions(); |
| 534 char* new_log_start = buffer.start() + log_size; | 666 char* new_log_start = buffer.start() + log_size; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 559 PrintCodeEntitiesInfo(equal, addr, ref_entity, new_entity); | 691 PrintCodeEntitiesInfo(equal, addr, ref_entity, new_entity); |
| 560 } | 692 } |
| 561 } | 693 } |
| 562 iter = iter->get_next(); | 694 iter = iter->get_next(); |
| 563 } | 695 } |
| 564 // Make sure that all log data is written prior crash due to CHECK failure. | 696 // Make sure that all log data is written prior crash due to CHECK failure. |
| 565 fflush(stdout); | 697 fflush(stdout); |
| 566 CHECK(results_equal); | 698 CHECK(results_equal); |
| 567 | 699 |
| 568 env->Exit(); | 700 env->Exit(); |
| 569 v8::V8::Dispose(); | 701 Logger::TearDown(); |
| 570 i::FLAG_always_compact = saved_always_compact; | 702 i::FLAG_always_compact = saved_always_compact; |
| 571 } | 703 } |
| 572 | 704 |
| 573 | 705 |
| 574 #endif // ENABLE_LOGGING_AND_PROFILING | 706 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |