Chromium Code Reviews| Index: test/cctest/test-cpu-profiler.cc |
| diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc |
| index a3e7b8d773a7bc51b11a981ed428621fa872d51f..871a709e885b2ca90c8e71e09b93805b3acc11c0 100644 |
| --- a/test/cctest/test-cpu-profiler.cc |
| +++ b/test/cctest/test-cpu-profiler.cc |
| @@ -1064,6 +1064,156 @@ TEST(BoundFunctionCall) { |
| } |
| +// Check that the profile tree for the script below will look like the |
| +// following: |
| +// |
| +// [Top down]: |
| +// 0 (root)0 #1 |
| +// 15 start 20 #3 no reason |
| +// 3 foo 20 #4 TryCatchStatement |
| +// 121 bar 20 #5 TryCatchStatement |
| +// 223 loop 20 #6 no reason |
| +// |
| +// This tests checks distribution of the samples through the source lines. |
| +// The optimizing compiler is disabled for the hotest function to make |
| +// the test deterministic. |
| + |
| +static int GetHitLineSampleCount(const v8::CpuProfileNode* node) { |
| + int sampleCount = 0; |
| + unsigned int lineCount = node->GetHitLineCount(); |
| + if (lineCount) { |
| + v8::LineTick* entries = new v8::LineTick[lineCount]; |
| + CHECK_EQ(true, node->GetLineTicks(entries, lineCount)); |
| + for (unsigned int i = 0; i < lineCount; i++) { |
| + sampleCount += entries[i].ticks; |
| + } |
| + delete [] entries; |
|
yurys
2014/07/29 13:15:10
Can be handled using a smart pointer from src/smar
|
| + } |
| + return sampleCount; |
| +} |
| + |
| + |
| +void CheckHitLine(unsigned int lineNo, |
| + const v8::CpuProfileNode* node, |
| + unsigned int sampleTotal, |
| + unsigned int threshold) { |
| + bool found = false; |
| + |
| + unsigned int lineCount = node->GetHitLineCount(); |
| + CHECK_GT(lineCount, 0); |
| + |
| + v8::LineTick* entries = new v8::LineTick[lineCount]; |
| + CHECK_EQ(true, node->GetLineTicks(entries, lineCount)); |
| + |
| + unsigned int i = 0; |
| + for (i = 0; i < lineCount; i++) { |
| + if (entries[i].line == lineNo) { |
| + found = true; |
| + break; |
| + } |
| + } |
| + CHECK_EQ(true, found); |
| + CHECK_GT(entries[i].ticks * 100 / sampleTotal, threshold); |
| + |
| + delete[] entries; |
| +} |
| + |
| + |
| +static void CheckBranchWithTickLines(v8::Isolate* isolate, |
| + const v8::CpuProfile* profile) { |
| + const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| + |
| + const v8::CpuProfileNode* startNode = |
| + GetChild(isolate, root, "start"); |
| + CHECK_EQ(1, startNode->GetChildrenCount()); |
| + CHECK_EQ(startNode->GetHitCount(), GetHitLineSampleCount(startNode)); |
| + |
| + const v8::CpuProfileNode* fooNode = |
| + GetChild(isolate, startNode, "foo"); |
| + CHECK_EQ(1, fooNode->GetChildrenCount()); |
| + CHECK_EQ(fooNode->GetHitCount(), GetHitLineSampleCount(fooNode)); |
| + |
| + const v8::CpuProfileNode* barNode = |
| + GetChild(isolate, fooNode, "bar"); |
| + CHECK_EQ(1, barNode->GetChildrenCount()); |
| + CHECK_EQ(barNode->GetHitCount(), GetHitLineSampleCount(barNode)); |
| + // Check that line #14 collects at least 90% of the samples. |
| + CheckHitLine(14, barNode, barNode->GetHitCount(), 90); |
| + |
| + const v8::CpuProfileNode* loopNode = |
| + GetChild(isolate, barNode, "loop"); |
| + CHECK_EQ(0, loopNode->GetChildrenCount()); |
| + CHECK_EQ(loopNode->GetHitCount(), GetHitLineSampleCount(loopNode)); |
| + |
| + // Check that line #8 collects at least 60% of the samples |
| + CheckHitLine(8, loopNode, loopNode->GetHitCount(), 60); |
| +} |
| + |
| + |
| +static const char* cpu_profiler_test_source3 = "function loop(timeout) {\n" |
| +" with({}); // disable the optimizing compiler for this function" |
| +" this.mmm = 0;\n" |
| +" var start = Date.now();\n" |
| +" while (Date.now() - start < timeout) {\n" |
| +" var n = 100*1000;\n" |
| +" while(n > 1) {\n" |
| +" n--;\n" |
| +" this.mmm += n * n * n;\n" |
| +" }\n" |
| +" }\n" |
| +"}\n" |
| +"function bar() {\n" |
| +" try {\n" |
| +" loop(10);\n" |
| +" } catch(e) { }\n" |
| +"}\n" |
| +"function foo() {\n" |
| +" try {\n" |
| +" bar();\n" |
| +" } catch (e) { }\n" |
| +"}\n" |
| +"function start(timeout) {\n" |
| +" var start = Date.now();\n" |
| +" do {\n" |
| +" foo();\n" |
| +" var duration = Date.now() - start;\n" |
| +" } while (duration < timeout);\n" |
| +" return duration;\n" |
| +"}\n"; |
| + |
| + |
| +TEST(TickLines) { |
|
yurys
2014/07/29 13:15:10
The test is bound to be flaky like other CPU profi
|
| + LocalContext env; |
| + v8::HandleScope scope(env->GetIsolate()); |
| + v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), |
| + cpu_profiler_test_source3))->Run(); |
| + v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| + env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start"))); |
| + |
| + int32_t profiling_interval_ms = 200; |
| + v8::Handle<v8::Value> args[] = { |
| + v8::Integer::New(env->GetIsolate(), profiling_interval_ms) |
| + }; |
| + |
| + // The first run tests distribution of the samples through the source |
| + // line information taken from "relocation info" created during code |
| + // generation. |
| + v8::CpuProfile* profile = |
| + RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200); |
| + function->Call(env->Global(), ARRAY_SIZE(args), args); |
| + CheckBranchWithTickLines(env->GetIsolate(), profile); |
| + profile->Delete(); |
| + |
| + // This is a case when the precompiled functions located on the heap |
| + // are profiled. The second run tests that same source lines collect |
| + // the expected number of samples. |
| + profile = RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200); |
| + function->Call(env->Global(), ARRAY_SIZE(args), args); |
| + CheckBranchWithTickLines(env->GetIsolate(), profile); |
| + profile->Delete(); |
| +} |
| + |
| + |
| static const char* call_function_test_source = "function bar(iterations) {\n" |
| "}\n" |
| "function start(duration) {\n" |