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 |