Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: runtime/vm/profiler_test.cc

Issue 1779333004: Add profile data to getSourceReport (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler_service.cc ('k') | runtime/vm/service.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/assert.h" 5 #include "platform/assert.h"
6 6
7 #include "vm/dart_api_impl.h" 7 #include "vm/dart_api_impl.h"
8 #include "vm/dart_api_state.h" 8 #include "vm/dart_api_state.h"
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 #include "vm/profiler.h" 10 #include "vm/profiler.h"
11 #include "vm/profiler_service.h" 11 #include "vm/profiler_service.h"
12 #include "vm/source_report.h"
12 #include "vm/unit_test.h" 13 #include "vm/unit_test.h"
13 14
14 namespace dart { 15 namespace dart {
15 16
16 #ifndef PRODUCT 17 #ifndef PRODUCT
17 18
18 DECLARE_FLAG(bool, profile_vm); 19 DECLARE_FLAG(bool, profile_vm);
19 DECLARE_FLAG(int, max_profile_depth); 20 DECLARE_FLAG(int, max_profile_depth);
20 DECLARE_FLAG(bool, enable_inlining_annotations); 21 DECLARE_FLAG(bool, enable_inlining_annotations);
21 DECLARE_FLAG(int, optimization_counter_threshold); 22 DECLARE_FLAG(int, optimization_counter_threshold);
(...skipping 2270 matching lines...) Expand 10 before | Expand all | Expand 10 after
2292 EXPECT(walker.Down()); 2293 EXPECT(walker.Down());
2293 EXPECT_STREQ("main", walker.CurrentName()); 2294 EXPECT_STREQ("main", walker.CurrentName());
2294 EXPECT_EQ(1, walker.CurrentNodeTickCount()); 2295 EXPECT_EQ(1, walker.CurrentNodeTickCount());
2295 EXPECT_EQ(1, walker.CurrentInclusiveTicks()); 2296 EXPECT_EQ(1, walker.CurrentInclusiveTicks());
2296 EXPECT_EQ(0, walker.CurrentExclusiveTicks()); 2297 EXPECT_EQ(0, walker.CurrentExclusiveTicks());
2297 EXPECT_STREQ("bacon", walker.CurrentToken()); 2298 EXPECT_STREQ("bacon", walker.CurrentToken());
2298 EXPECT(!walker.Down()); 2299 EXPECT(!walker.Down());
2299 } 2300 }
2300 } 2301 }
2301 2302
2303
2304 static void InsertFakeSample(SampleBuffer* sample_buffer,
2305 uword* pc_offsets) {
2306 ASSERT(sample_buffer != NULL);
2307 Isolate* isolate = Isolate::Current();
2308 Sample* sample = sample_buffer->ReserveSample();
2309 ASSERT(sample != NULL);
2310 sample->Init(isolate,
2311 OS::GetCurrentMonotonicMicros(),
2312 OSThread::Current()->trace_id());
2313
2314 intptr_t i = 0;
2315 while (pc_offsets[i] != 0) {
2316 // When we collect a real stack trace, all PCs collected aside from the
2317 // executing one (i == 0) are actually return addresses. Return addresses
2318 // are one byte beyond the call instruction that is executing. The profiler
2319 // accounts for this and subtracts one from these addresses when querying
2320 // inline and token position ranges. To be consistent with real stack
2321 // traces, we add one byte to all PCs except the executing one.
2322 // See OffsetForPC in profiler_service.cc for more context.
2323 const intptr_t return_address_offset = i > 0 ? 1 : 0;
2324 sample->SetAt(i, pc_offsets[i] + return_address_offset);
2325 i++;
2326 }
2327 sample->SetAt(i, NULL);
2328 }
2329
2330
2331 static uword FindPCForTokenPosition(const Code& code,
2332 const CodeSourceMap& code_source_map,
2333 TokenPosition tp) {
2334 CodeSourceMap::Iterator it(code_source_map);
2335
2336 while (it.MoveNext()) {
2337 if (it.TokenPos() == tp) {
2338 return it.PcOffset() + code.EntryPoint();
2339 }
2340 }
2341
2342 return 0;
2343 }
2344
2345
2346 TEST_CASE(Profiler_GetSourceReport) {
2347 const char* kScript =
2348 "doWork(i) => i * i;\n"
2349 "main() {\n"
2350 " var sum = 0;\n"
2351 " for (var i = 0; i < 100; i++) {\n"
2352 " sum += doWork(i);\n"
2353 " }\n"
2354 " return sum;\n"
2355 "}\n";
2356
2357 // Token position of * in `i * i`.
2358 const TokenPosition squarePosition = TokenPosition(6);
2359
2360 // Token position of the call to `doWork`.
2361 const TokenPosition callPosition = TokenPosition(39);
2362
2363 DisableNativeProfileScope dnps;
2364 // Disable profiling for this thread.
2365 DisableThreadInterruptsScope dtis(Thread::Current());
2366
2367 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2368 EXPECT(sample_buffer != NULL);
2369
2370 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
2371 EXPECT_VALID(lib);
2372 Library& root_library = Library::Handle();
2373 root_library ^= Api::UnwrapHandle(lib);
2374
2375 // Invoke main so that it gets compiled.
2376 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
2377 EXPECT_VALID(result);
2378
2379 {
2380 // Clear the profile for this isolate.
2381 ClearProfileVisitor cpv(Isolate::Current());
2382 sample_buffer->VisitSamples(&cpv);
2383 }
2384
2385 // Query the code object for main and determine the PC at some token
2386 // positions.
2387 const Function& main = Function::Handle(GetFunction(root_library, "main"));
2388 EXPECT(!main.IsNull());
2389
2390 const Function& do_work =
2391 Function::Handle(GetFunction(root_library, "doWork"));
2392 EXPECT(!do_work.IsNull());
2393
2394 const Script& script = Script::Handle(main.script());
2395 EXPECT(!script.IsNull());
2396
2397 const Code& main_code = Code::Handle(main.CurrentCode());
2398 EXPECT(!main_code.IsNull());
2399
2400 const Code& do_work_code = Code::Handle(do_work.CurrentCode());
2401 EXPECT(!do_work_code.IsNull());
2402
2403 const CodeSourceMap& main_code_source_map =
2404 CodeSourceMap::Handle(main_code.code_source_map());
2405 EXPECT(!main_code_source_map.IsNull());
2406
2407 const CodeSourceMap& do_work_code_source_map =
2408 CodeSourceMap::Handle(do_work_code.code_source_map());
2409 EXPECT(!do_work_code_source_map.IsNull());
2410
2411 // Dump code source map.
2412 CodeSourceMap::Dump(do_work_code_source_map, do_work_code, main);
2413 CodeSourceMap::Dump(main_code_source_map, main_code, main);
2414
2415 // Look up some source token position's pc.
2416 uword squarePositionPc =
2417 FindPCForTokenPosition(do_work_code,
2418 do_work_code_source_map,
2419 squarePosition);
2420 EXPECT(squarePositionPc != 0);
2421
2422 uword callPositionPc =
2423 FindPCForTokenPosition(main_code, main_code_source_map, callPosition);
2424 EXPECT(callPositionPc != 0);
2425
2426 // Look up some classifying token position's pc.
2427 uword controlFlowPc =
2428 FindPCForTokenPosition(do_work_code,
2429 do_work_code_source_map,
2430 TokenPosition::kControlFlow);
2431 EXPECT(controlFlowPc != 0);
2432
2433 uword tempMovePc =
2434 FindPCForTokenPosition(main_code,
2435 main_code_source_map,
2436 TokenPosition::kTempMove);
2437 EXPECT(tempMovePc != 0);
2438
2439 // Insert fake samples.
2440
2441 // Sample 1:
2442 // squarePositionPc exclusive.
2443 // callPositionPc inclusive.
2444 uword sample1[] = {
2445 squarePositionPc, // doWork.
2446 callPositionPc, // main.
2447 0
2448 };
2449
2450 // Sample 2:
2451 // squarePositionPc exclusive.
2452 uword sample2[] = {
2453 squarePositionPc, // doWork.
2454 0,
2455 };
2456
2457 // Sample 3:
2458 // controlFlowPc exclusive.
2459 // callPositionPc inclusive.
2460 uword sample3[] = {
2461 controlFlowPc, // doWork.
2462 callPositionPc, // main.
2463 0
2464 };
2465
2466 // Sample 4:
2467 // tempMovePc exclusive.
2468 uword sample4[] = {
2469 tempMovePc, // main.
2470 0
2471 };
2472
2473 InsertFakeSample(sample_buffer, &sample1[0]);
2474 InsertFakeSample(sample_buffer, &sample2[0]);
2475 InsertFakeSample(sample_buffer, &sample3[0]);
2476 InsertFakeSample(sample_buffer, &sample4[0]);
2477
2478 // Generate source report for main.
2479 SourceReport sourceReport(SourceReport::kProfile);
2480 JSONStream js;
2481 sourceReport.PrintJSON(&js,
2482 script,
2483 do_work.token_pos(),
2484 main.end_token_pos());
2485
2486 // Verify positions in do_work.
2487 EXPECT_SUBSTRING("\"positions\":[\"ControlFlow\",6]", js.ToCString());
2488 // Verify exclusive ticks in do_work.
2489 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,2]", js.ToCString());
2490 // Verify inclusive ticks in do_work.
2491 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString());
2492
2493 // Verify positions in main.
2494 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString());
2495 // Verify exclusive ticks in main.
2496 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString());
2497 // Verify inclusive ticks in main.
2498 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString());
2499 }
2500
2302 #endif // !PRODUCT 2501 #endif // !PRODUCT
2303 2502
2304 } // namespace dart 2503 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler_service.cc ('k') | runtime/vm/service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698