diff options
Diffstat (limited to 'deps/v8/test/cctest/test-cpu-profiler.cc')
-rw-r--r-- | deps/v8/test/cctest/test-cpu-profiler.cc | 333 |
1 files changed, 264 insertions, 69 deletions
diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc index e08bec375e..3a3063ed3c 100644 --- a/deps/v8/test/cctest/test-cpu-profiler.cc +++ b/deps/v8/test/cctest/test-cpu-profiler.cc @@ -37,6 +37,7 @@ #include "src/base/platform/platform.h" #include "src/deoptimizer.h" #include "src/libplatform/default-platform.h" +#include "src/log.h" #include "src/objects-inl.h" #include "src/profiler/cpu-profiler-inl.h" #include "src/profiler/profiler-listener.h" @@ -79,7 +80,7 @@ TEST(StartStop) { CpuProfilesCollection profiles(isolate); ProfileGenerator generator(&profiles); std::unique_ptr<ProfilerEventsProcessor> processor( - new ProfilerEventsProcessor(isolate, &generator, + new SamplingEventsProcessor(isolate, &generator, v8::base::TimeDelta::FromMicroseconds(100))); processor->Start(); processor->StopSynchronously(); @@ -89,19 +90,20 @@ static void EnqueueTickSampleEvent(ProfilerEventsProcessor* proc, i::Address frame1, i::Address frame2 = kNullAddress, i::Address frame3 = kNullAddress) { - v8::TickSample* sample = proc->StartTickSample(); - sample->pc = reinterpret_cast<void*>(frame1); - sample->tos = reinterpret_cast<void*>(frame1); - sample->frames_count = 0; + v8::internal::TickSample sample; + sample.pc = reinterpret_cast<void*>(frame1); + sample.tos = reinterpret_cast<void*>(frame1); + sample.frames_count = 0; if (frame2 != kNullAddress) { - sample->stack[0] = reinterpret_cast<void*>(frame2); - sample->frames_count = 1; + sample.stack[0] = reinterpret_cast<void*>(frame2); + sample.frames_count = 1; } if (frame3 != kNullAddress) { - sample->stack[1] = reinterpret_cast<void*>(frame3); - sample->frames_count = 2; + sample.stack[1] = reinterpret_cast<void*>(frame3); + sample.frames_count = 2; } - proc->FinishTickSample(); + sample.timestamp = base::TimeTicks::HighResolutionNow(); + proc->AddSample(sample); } namespace { @@ -123,7 +125,7 @@ class TestSetup { } // namespace -i::AbstractCode* CreateCode(LocalContext* env) { +i::AbstractCode CreateCode(LocalContext* env) { static int counter = 0; i::EmbeddedVector<char, 256> script; i::EmbeddedVector<char, 32> name; @@ -153,19 +155,17 @@ TEST(CodeEvents) { i::HandleScope scope(isolate); - i::AbstractCode* aaa_code = CreateCode(&env); - i::AbstractCode* comment_code = CreateCode(&env); - i::AbstractCode* comment2_code = CreateCode(&env); - i::AbstractCode* moved_code = CreateCode(&env); + i::AbstractCode aaa_code = CreateCode(&env); + i::AbstractCode comment_code = CreateCode(&env); + i::AbstractCode comment2_code = CreateCode(&env); + i::AbstractCode moved_code = CreateCode(&env); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); ProfileGenerator* generator = new ProfileGenerator(profiles); - ProfilerEventsProcessor* processor = new ProfilerEventsProcessor( + ProfilerEventsProcessor* processor = new SamplingEventsProcessor( isolate, generator, v8::base::TimeDelta::FromMicroseconds(100)); - CpuProfiler profiler(isolate, profiles, generator, processor); - profiles->StartProfiling("", false); processor->Start(); - ProfilerListener profiler_listener(isolate, &profiler); + ProfilerListener profiler_listener(isolate, processor); isolate->logger()->AddCodeEventListener(&profiler_listener); // Enqueue code creation events. @@ -215,19 +215,19 @@ TEST(TickEvents) { i::Isolate* isolate = CcTest::i_isolate(); i::HandleScope scope(isolate); - i::AbstractCode* frame1_code = CreateCode(&env); - i::AbstractCode* frame2_code = CreateCode(&env); - i::AbstractCode* frame3_code = CreateCode(&env); + i::AbstractCode frame1_code = CreateCode(&env); + i::AbstractCode frame2_code = CreateCode(&env); + i::AbstractCode frame3_code = CreateCode(&env); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); ProfileGenerator* generator = new ProfileGenerator(profiles); ProfilerEventsProcessor* processor = - new ProfilerEventsProcessor(CcTest::i_isolate(), generator, + new SamplingEventsProcessor(CcTest::i_isolate(), generator, v8::base::TimeDelta::FromMicroseconds(100)); CpuProfiler profiler(isolate, profiles, generator, processor); profiles->StartProfiling("", false); processor->Start(); - ProfilerListener profiler_listener(isolate, &profiler); + ProfilerListener profiler_listener(isolate, processor); isolate->logger()->AddCodeEventListener(&profiler_listener); profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb"); @@ -286,28 +286,29 @@ TEST(Issue1398) { i::Isolate* isolate = CcTest::i_isolate(); i::HandleScope scope(isolate); - i::AbstractCode* code = CreateCode(&env); + i::AbstractCode code = CreateCode(&env); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); ProfileGenerator* generator = new ProfileGenerator(profiles); ProfilerEventsProcessor* processor = - new ProfilerEventsProcessor(CcTest::i_isolate(), generator, + new SamplingEventsProcessor(CcTest::i_isolate(), generator, v8::base::TimeDelta::FromMicroseconds(100)); CpuProfiler profiler(isolate, profiles, generator, processor); profiles->StartProfiling("", false); processor->Start(); - ProfilerListener profiler_listener(isolate, &profiler); + ProfilerListener profiler_listener(isolate, processor); profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); - v8::TickSample* sample = processor->StartTickSample(); - sample->pc = reinterpret_cast<void*>(code->InstructionStart()); - sample->tos = nullptr; - sample->frames_count = v8::TickSample::kMaxFramesCount; - for (unsigned i = 0; i < sample->frames_count; ++i) { - sample->stack[i] = reinterpret_cast<void*>(code->InstructionStart()); + v8::internal::TickSample sample; + sample.pc = reinterpret_cast<void*>(code->InstructionStart()); + sample.tos = nullptr; + sample.frames_count = v8::TickSample::kMaxFramesCount; + for (unsigned i = 0; i < sample.frames_count; ++i) { + sample.stack[i] = reinterpret_cast<void*>(code->InstructionStart()); } - processor->FinishTickSample(); + sample.timestamp = base::TimeTicks::HighResolutionNow(); + processor->AddSample(sample); processor->StopSynchronously(); CpuProfile* profile = profiles->StopProfiling(""); @@ -459,7 +460,9 @@ v8::CpuProfile* ProfilerHelper::Run(v8::Local<v8::Function> function, v8::internal::CpuProfiler* iprofiler = reinterpret_cast<v8::internal::CpuProfiler*>(profiler_); - v8::sampler::Sampler* sampler = iprofiler->processor()->sampler(); + v8::sampler::Sampler* sampler = + reinterpret_cast<i::SamplingEventsProcessor*>(iprofiler->processor()) + ->sampler(); sampler->StartCountingSamples(); do { function->Call(context_, context_->Global(), argc, argv).ToLocalChecked(); @@ -1077,7 +1080,7 @@ static const char* bound_function_test_source = TEST(BoundFunctionCall) { v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); CompileRun(bound_function_test_source); @@ -1096,7 +1099,9 @@ TEST(BoundFunctionCall) { // This tests checks distribution of the samples through the source lines. static void TickLines(bool optimize) { - if (!optimize) i::FLAG_opt = false; +#ifndef V8_LITE_MODE + FLAG_opt = optimize; +#endif // V8_LITE_MODE CcTest::InitializeVM(); LocalContext env; i::FLAG_allow_natives_syntax = true; @@ -1132,24 +1137,24 @@ static void TickLines(bool optimize) { i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast( v8::Utils::OpenHandle(*GetFunction(env.local(), func_name))); - CHECK(func->shared()); - CHECK(func->shared()->abstract_code()); + CHECK(!func->shared().is_null()); + CHECK(!func->shared()->abstract_code().is_null()); CHECK(!optimize || func->IsOptimized() || !CcTest::i_isolate()->use_optimizer()); - i::AbstractCode* code = func->abstract_code(); - CHECK(code); + i::AbstractCode code = func->abstract_code(); + CHECK(!code.is_null()); i::Address code_address = code->raw_instruction_start(); - CHECK(code_address); + CHECK_NE(code_address, kNullAddress); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); ProfileGenerator* generator = new ProfileGenerator(profiles); ProfilerEventsProcessor* processor = - new ProfilerEventsProcessor(CcTest::i_isolate(), generator, + new SamplingEventsProcessor(CcTest::i_isolate(), generator, v8::base::TimeDelta::FromMicroseconds(100)); CpuProfiler profiler(isolate, profiles, generator, processor); profiles->StartProfiling("", false); processor->Start(); - ProfilerListener profiler_listener(isolate, &profiler); + ProfilerListener profiler_listener(isolate, processor); // Enqueue code creation events. i::Handle<i::String> str = factory->NewStringFromAsciiChecked(func_name); @@ -1340,7 +1345,7 @@ static const char* cpu_profiler_deep_stack_test_source = // 0 foo 21 #254 no reason TEST(CpuProfileDeepStack) { v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); @@ -1398,7 +1403,7 @@ static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) { TEST(JsNativeJsSample) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( @@ -1451,7 +1456,7 @@ static const char* js_native_js_runtime_js_test_source = TEST(JsNativeJsRuntimeJsSample) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New( @@ -1508,7 +1513,7 @@ static const char* js_native1_js_native2_js_test_source = TEST(JsNative1JsNative2JsSample) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::Local<v8::Function> func1 = @@ -1554,7 +1559,7 @@ static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) { TEST(CollectSampleAPI) { v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::Local<v8::FunctionTemplate> func_template = @@ -1608,7 +1613,7 @@ static const char* js_native_js_runtime_multiple_test_source = TEST(JsNativeJsRuntimeJsSampleMultiple) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::Local<v8::FunctionTemplate> func_template = @@ -1673,7 +1678,7 @@ static const char* inlining_test_source = TEST(Inlining) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); @@ -1697,6 +1702,135 @@ TEST(Inlining) { profile->Delete(); } +static const char* inlining_test_source2 = R"( + %NeverOptimizeFunction(action); + %NeverOptimizeFunction(start); + level1(); + level1(); + %OptimizeFunctionOnNextCall(level1); + %OptimizeFunctionOnNextCall(level2); + %OptimizeFunctionOnNextCall(level3); + %OptimizeFunctionOnNextCall(level4); + level1(); + function action(n) { + var s = 0; + for (var i = 0; i < n; ++i) s += i*i*i; + return s; + } + function level4() { + action(100); + return action(100); + } + function level3() { + const a = level4(); + const b = level4(); + return a + b * 1.1; + } + function level2() { + return level3() * 2; + } + function level1() { + action(1); + action(200); + action(1); + return level2(); + } + function start(n) { + while (--n) + level1(); + }; + )"; + +// The simulator builds are extremely slow. We run them with fewer iterations. +#ifdef USE_SIMULATOR +const double load_factor = 0.01; +#else +const double load_factor = 1.0; +#endif + +// [Top down]: +// 0 (root):0 0 #1 +// 13 start:34 6 #3 +// bailed out due to 'Optimization is always disabled' +// 19 level1:36 6 #4 +// 16 action:29 6 #14 +// bailed out due to 'Optimization is always disabled' +// 2748 action:30 6 #10 +// bailed out due to 'Optimization is always disabled' +// 18 action:31 6 #15 +// bailed out due to 'Optimization is always disabled' +// 0 level2:32 6 #5 +// 0 level3:26 6 #6 +// 12 level4:22 6 #11 +// 1315 action:17 6 #13 +// bailed out due to 'Optimization is always disabled' +// 1324 action:18 6 #12 +// bailed out due to 'Optimization is always disabled' +// 16 level4:21 6 #7 +// 1268 action:17 6 #9 +// bailed out due to 'Optimization is always disabled' +// 1322 action:18 6 #8 +// bailed out due to 'Optimization is always disabled' +// 2 (program):0 0 #2 +TEST(Inlining2) { + FLAG_allow_natives_syntax = true; + v8::HandleScope scope(CcTest::isolate()); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); + v8::Context::Scope context_scope(env); + + CompileRun(inlining_test_source2); + v8::Local<v8::Function> function = GetFunction(env, "start"); + + v8::CpuProfiler* profiler = v8::CpuProfiler::New(CcTest::isolate()); + v8::Local<v8::String> profile_name = v8_str("inlining"); + profiler->StartProfiling(profile_name, + v8::CpuProfilingMode::kCallerLineNumbers); + + v8::Local<v8::Value> args[] = { + v8::Integer::New(env->GetIsolate(), 50000 * load_factor)}; + function->Call(env, env->Global(), arraysize(args), args).ToLocalChecked(); + v8::CpuProfile* profile = profiler->StopProfiling(profile_name); + CHECK(profile); + + // Dump collected profile to have a better diagnostic in case of failure. + reinterpret_cast<i::CpuProfile*>(profile)->Print(); + + const v8::CpuProfileNode* root = profile->GetTopDownRoot(); + const v8::CpuProfileNode* start_node = GetChild(env, root, "start"); + + NameLinePair l421_a17[] = {{"level1", 36}, + {"level2", 32}, + {"level3", 26}, + {"level4", 21}, + {"action", 17}}; + CheckBranch(start_node, l421_a17, arraysize(l421_a17)); + NameLinePair l422_a17[] = {{"level1", 36}, + {"level2", 32}, + {"level3", 26}, + {"level4", 22}, + {"action", 17}}; + CheckBranch(start_node, l422_a17, arraysize(l422_a17)); + + NameLinePair l421_a18[] = {{"level1", 36}, + {"level2", 32}, + {"level3", 26}, + {"level4", 21}, + {"action", 18}}; + CheckBranch(start_node, l421_a18, arraysize(l421_a18)); + NameLinePair l422_a18[] = {{"level1", 36}, + {"level2", 32}, + {"level3", 26}, + {"level4", 22}, + {"action", 18}}; + CheckBranch(start_node, l422_a18, arraysize(l422_a18)); + + NameLinePair action_direct[] = {{"level1", 36}, {"action", 30}}; + CheckBranch(start_node, action_direct, arraysize(action_direct)); + + profile->Delete(); + profiler->Dispose(); +} + // [Top down]: // 0 (root) #0 1 // 2 (program) #0 2 @@ -1713,13 +1847,13 @@ TEST(IdleTime) { i::ProfilerEventsProcessor* processor = reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->processor(); - processor->AddCurrentStack(isolate, true); + processor->AddCurrentStack(true); isolate->SetIdle(true); for (int i = 0; i < 3; i++) { - processor->AddCurrentStack(isolate, true); + processor->AddCurrentStack(true); } isolate->SetIdle(false); - processor->AddCurrentStack(isolate, true); + processor->AddCurrentStack(true); v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name); CHECK(profile); @@ -1761,7 +1895,7 @@ static void CheckFunctionDetails(v8::Isolate* isolate, TEST(FunctionDetails) { i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); @@ -1808,7 +1942,7 @@ TEST(FunctionDetailsInlining) { if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); @@ -1881,12 +2015,12 @@ TEST(FunctionDetailsInlining) { const v8::CpuProfileNode* beta = FindChild(env, alpha, "beta"); if (!beta) return; CheckFunctionDetails(env->GetIsolate(), beta, "beta", "script_b", - script_b->GetUnboundScript()->GetId(), 0, 0); + script_b->GetUnboundScript()->GetId(), 1, 14); } TEST(DontStopOnFinishedProfileDelete) { v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); v8::CpuProfiler* profiler = v8::CpuProfiler::New(env->GetIsolate()); @@ -1934,7 +2068,7 @@ TEST(CollectDeoptEvents) { if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); i::CpuProfiler* iprofiler = @@ -2067,7 +2201,7 @@ TEST(DeoptAtFirstLevelInlinedSource) { if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); i::CpuProfiler* iprofiler = @@ -2137,7 +2271,7 @@ TEST(DeoptAtSecondLevelInlinedSource) { if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); i::CpuProfiler* iprofiler = @@ -2212,7 +2346,7 @@ TEST(DeoptUntrackedFunction) { if (!CcTest::i_isolate()->use_optimizer() || i::FLAG_always_opt) return; i::FLAG_allow_natives_syntax = true; v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); ProfilerHelper helper(env); i::CpuProfiler* iprofiler = @@ -2423,7 +2557,7 @@ TEST(StaticCollectSampleAPI) { TEST(CodeEntriesMemoryLeak) { v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); std::string source = "function start() {}\n"; @@ -2457,7 +2591,7 @@ TEST(NativeFrameStackTrace) { // v8::internal::StringTable::LookupStringIfExists_NoAllocate native function // without producing an EXIT frame. v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION); + v8::Local<v8::Context> env = CcTest::NewContext({PROFILER_EXTENSION_ID}); v8::Context::Scope context_scope(env); const char* source = R"( @@ -2503,6 +2637,7 @@ TEST(SourcePositionTable) { int no_info = v8::CpuProfileNode::kNoLineNumberInfo; CHECK_EQ(no_info, info.GetSourceLineNumber(std::numeric_limits<int>::min())); CHECK_EQ(no_info, info.GetSourceLineNumber(0)); + CHECK_EQ(SourcePosition::kNotInlined, info.GetInliningId(0)); CHECK_EQ(no_info, info.GetSourceLineNumber(1)); CHECK_EQ(no_info, info.GetSourceLineNumber(9)); CHECK_EQ(no_info, info.GetSourceLineNumber(10)); @@ -2511,12 +2646,14 @@ TEST(SourcePositionTable) { CHECK_EQ(no_info, info.GetSourceLineNumber(20)); CHECK_EQ(no_info, info.GetSourceLineNumber(21)); CHECK_EQ(no_info, info.GetSourceLineNumber(100)); + CHECK_EQ(SourcePosition::kNotInlined, info.GetInliningId(100)); CHECK_EQ(no_info, info.GetSourceLineNumber(std::numeric_limits<int>::max())); - info.SetPosition(10, 1); - info.SetPosition(20, 2); + info.SetPosition(10, 1, SourcePosition::kNotInlined); + info.SetPosition(20, 2, SourcePosition::kNotInlined); - // The only valid return values are 1 or 2 - every pc maps to a line number. + // The only valid return values are 1 or 2 - every pc maps to a line + // number. CHECK_EQ(1, info.GetSourceLineNumber(std::numeric_limits<int>::min())); CHECK_EQ(1, info.GetSourceLineNumber(0)); CHECK_EQ(1, info.GetSourceLineNumber(1)); @@ -2524,16 +2661,22 @@ TEST(SourcePositionTable) { CHECK_EQ(1, info.GetSourceLineNumber(10)); CHECK_EQ(1, info.GetSourceLineNumber(11)); CHECK_EQ(1, info.GetSourceLineNumber(19)); - CHECK_EQ(2, info.GetSourceLineNumber(20)); + CHECK_EQ(1, info.GetSourceLineNumber(20)); CHECK_EQ(2, info.GetSourceLineNumber(21)); CHECK_EQ(2, info.GetSourceLineNumber(100)); CHECK_EQ(2, info.GetSourceLineNumber(std::numeric_limits<int>::max())); + CHECK_EQ(SourcePosition::kNotInlined, info.GetInliningId(0)); + CHECK_EQ(SourcePosition::kNotInlined, info.GetInliningId(100)); + // Test SetPosition behavior. - info.SetPosition(25, 3); + info.SetPosition(25, 3, 0); CHECK_EQ(2, info.GetSourceLineNumber(21)); CHECK_EQ(3, info.GetSourceLineNumber(100)); CHECK_EQ(3, info.GetSourceLineNumber(std::numeric_limits<int>::max())); + + CHECK_EQ(SourcePosition::kNotInlined, info.GetInliningId(21)); + CHECK_EQ(0, info.GetInliningId(100)); } TEST(MultipleProfilers) { @@ -2545,6 +2688,58 @@ TEST(MultipleProfilers) { profiler2->StopProfiling("2"); } +void ProfileSomeCode(v8::Isolate* isolate) { + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope scope(isolate); + LocalContext context(isolate); + + v8::CpuProfiler* profiler = v8::CpuProfiler::New(isolate); + + v8::Local<v8::String> profile_name = v8_str("1"); + profiler->StartProfiling(profile_name); + const char* source = R"( + function foo() { + var x = 0; + for (var i = 0; i < 1e3; i++) { + for (var j = 0; j < 1e3; j++) { + x = i * j; + } + } + return x; + } + foo(); + )"; + + CompileRun(source); + profiler->StopProfiling(profile_name); + profiler->Dispose(); +} + +class IsolateThread : public v8::base::Thread { + public: + IsolateThread() : Thread(Options("IsolateThread")) {} + + void Run() override { + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + ProfileSomeCode(isolate); + isolate->Dispose(); + } +}; + +// Checking for crashes and TSAN issues with multiple isolates profiling. +TEST(MultipleIsolates) { + IsolateThread thread1; + IsolateThread thread2; + + thread1.Start(); + thread2.Start(); + + thread1.Join(); + thread2.Join(); +} + int GetSourcePositionEntryCount(i::Isolate* isolate, const char* source) { i::Handle<i::JSFunction> function = i::Handle<i::JSFunction>::cast( v8::Utils::OpenHandle(*CompileRun(source))); |