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

Side by Side Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 2646443005: Track async causal stack traces (Closed)
Patch Set: Observatory UI support Created 3 years, 11 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library debugger_page_element; 5 library debugger_page_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:svg'; 8 import 'dart:svg';
9 import 'dart:html'; 9 import 'dart:html';
10 import 'dart:math'; 10 import 'dart:math';
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 'break-on-exception': [ 597 'break-on-exception': [
598 _boeValues, 598 _boeValues,
599 _setBreakOnException, 599 _setBreakOnException,
600 (debugger, _) => debugger.breakOnException 600 (debugger, _) => debugger.breakOnException
601 ], 601 ],
602 'up-is-down': [ 602 'up-is-down': [
603 _boolValues, 603 _boolValues,
604 _setUpIsDown, 604 _setUpIsDown,
605 (debugger, _) => debugger.upIsDown 605 (debugger, _) => debugger.upIsDown
606 ], 606 ],
607 'sane-async-stacks': [
608 _boolValues,
609 _setSaneAsyncStacks,
610 (debugger, _) => debugger.saneAsyncStacks
611 ],
607 }; 612 };
608 613
609 static Future _setBreakOnException(debugger, name, value) async { 614 static Future _setBreakOnException(debugger, name, value) async {
610 var result = await debugger.isolate.setExceptionPauseMode(value); 615 var result = await debugger.isolate.setExceptionPauseMode(value);
611 if (result.isError) { 616 if (result.isError) {
612 debugger.console.print(result.toString()); 617 debugger.console.print(result.toString());
613 } else { 618 } else {
614 // Printing will occur elsewhere. 619 // Printing will occur elsewhere.
615 debugger.breakOnException = value; 620 debugger.breakOnException = value;
616 } 621 }
617 } 622 }
618 623
619 static Future _setUpIsDown(debugger, name, value) async { 624 static Future _setUpIsDown(debugger, name, value) async {
620 if (value == 'true') { 625 if (value == 'true') {
621 debugger.upIsDown = true; 626 debugger.upIsDown = true;
622 } else { 627 } else {
623 debugger.upIsDown = false; 628 debugger.upIsDown = false;
624 } 629 }
625 debugger.console.print('${name} = ${value}'); 630 debugger.console.print('${name} = ${value}');
626 } 631 }
627 632
633 static Future _setSaneAsyncStacks(debugger, name, value) async {
634 if (value == 'true') {
635 debugger.saneAsyncStacks = true;
636 } else {
637 debugger.saneAsyncStacks = false;
638 }
639 debugger.refreshStack();
640 debugger.console.print('${name} = ${value}');
641 }
642
628 Future run(List<String> args) async { 643 Future run(List<String> args) async {
629 if (args.length == 0) { 644 if (args.length == 0) {
630 for (var name in _options.keys) { 645 for (var name in _options.keys) {
631 var getHandler = _options[name][2]; 646 var getHandler = _options[name][2];
632 var value = await getHandler(debugger, name); 647 var value = await getHandler(debugger, name);
633 debugger.console.print("${name} = ${value}"); 648 debugger.console.print("${name} = ${value}");
634 } 649 }
635 } else if (args.length == 1) { 650 } else if (args.length == 1) {
636 var name = args[0].trim(); 651 var name = args[0].trim();
637 var optionInfo = _options[name]; 652 var optionInfo = _options[name];
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
1374 int _currentFrame = null; 1389 int _currentFrame = null;
1375 1390
1376 bool get upIsDown => _upIsDown; 1391 bool get upIsDown => _upIsDown;
1377 void set upIsDown(bool value) { 1392 void set upIsDown(bool value) {
1378 settings.set('up-is-down', value); 1393 settings.set('up-is-down', value);
1379 _upIsDown = value; 1394 _upIsDown = value;
1380 } 1395 }
1381 1396
1382 bool _upIsDown; 1397 bool _upIsDown;
1383 1398
1399 bool get saneAsyncStacks => _saneAsyncStacks;
1400 void set saneAsyncStacks(bool value) {
1401 settings.set('sane-async-stacks', value);
1402 _saneAsyncStacks = value;
1403 }
1404
1405 bool _saneAsyncStacks;
1406
1407 static const String kAsyncCausalStackFrames = 'asyncCausalFrames';
1408 static const String kStackFrames = 'frames';
1409
1384 void upFrame(int count) { 1410 void upFrame(int count) {
1385 if (_upIsDown) { 1411 if (_upIsDown) {
1386 currentFrame += count; 1412 currentFrame += count;
1387 } else { 1413 } else {
1388 currentFrame -= count; 1414 currentFrame -= count;
1389 } 1415 }
1390 } 1416 }
1391 1417
1392 void downFrame(int count) { 1418 void downFrame(int count) {
1393 if (_upIsDown) { 1419 if (_upIsDown) {
1394 currentFrame -= count; 1420 currentFrame -= count;
1395 } else { 1421 } else {
1396 currentFrame += count; 1422 currentFrame += count;
1397 } 1423 }
1398 } 1424 }
1399 1425
1400 int get stackDepth => stack['frames'].length; 1426 int get stackDepth {
1427 if (saneAsyncStacks) {
1428 var asyncCausalStackFrames = stack[kAsyncCausalStackFrames];
1429 var stackFrames = stack[kStackFrames];
1430 if (asyncCausalStackFrames == null) {
1431 // No causal frames.
1432 return stackFrames.length;
1433 }
1434 return asyncCausalStackFrames.length;
1435 } else {
1436 return stack[kStackFrames].length;
1437 }
1438 }
1439
1440 List get stackFrames {
1441 if (saneAsyncStacks) {
1442 var asyncCausalStackFrames = stack[kAsyncCausalStackFrames];
1443 var stackFrames = stack[kStackFrames];
1444 if (asyncCausalStackFrames == null) {
1445 // No causal frames.
1446 return stackFrames ?? [];
1447 }
1448 return asyncCausalStackFrames;
1449 } else {
1450 return stack[kStackFrames] ?? [];
1451 }
1452 }
1401 1453
1402 static final _history = ['']; 1454 static final _history = [''];
1403 1455
1404 ObservatoryDebugger(this.isolate) { 1456 ObservatoryDebugger(this.isolate) {
1405 _loadSettings(); 1457 _loadSettings();
1406 cmd = new RootCommand([ 1458 cmd = new RootCommand([
1407 new AsyncNextCommand(this), 1459 new AsyncNextCommand(this),
1408 new BreakCommand(this), 1460 new BreakCommand(this),
1409 new ClearCommand(this), 1461 new ClearCommand(this),
1410 new ClsCommand(this), 1462 new ClsCommand(this),
(...skipping 16 matching lines...) Expand all
1427 new StepCommand(this), 1479 new StepCommand(this),
1428 new SyncNextCommand(this), 1480 new SyncNextCommand(this),
1429 new UpCommand(this), 1481 new UpCommand(this),
1430 new VmCommand(this), 1482 new VmCommand(this),
1431 ], _history); 1483 ], _history);
1432 _consolePrinter = new _ConsoleStreamPrinter(this); 1484 _consolePrinter = new _ConsoleStreamPrinter(this);
1433 } 1485 }
1434 1486
1435 void _loadSettings() { 1487 void _loadSettings() {
1436 _upIsDown = settings.get('up-is-down'); 1488 _upIsDown = settings.get('up-is-down');
1489 _saneAsyncStacks = settings.get('sane-async-stacks') ?? true;
1437 } 1490 }
1438 1491
1439 S.VM get vm => page.app.vm; 1492 S.VM get vm => page.app.vm;
1440 1493
1441 void init() { 1494 void init() {
1442 console.printBold('Debugging isolate isolate ${isolate.number} ' 1495 console.printBold('Debugging isolate isolate ${isolate.number} '
1443 '\'${isolate.name}\' '); 1496 '\'${isolate.name}\' ');
1444 console.printBold('Type \'h\' for help'); 1497 console.printBold('Type \'h\' for help');
1445 // Wait a bit and if polymer still hasn't set up the isolate, 1498 // Wait a bit and if polymer still hasn't set up the isolate,
1446 // report this to the user. 1499 // report this to the user.
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 li.classes.add('list-group-item'); 2297 li.classes.add('list-group-item');
2245 li.children.insert(0, messageElement); 2298 li.children.insert(0, messageElement);
2246 2299
2247 messageList.add(li); 2300 messageList.add(li);
2248 } 2301 }
2249 2302
2250 ObservatoryApplication get app => ObservatoryApplication.app; 2303 ObservatoryApplication get app => ObservatoryApplication.app;
2251 2304
2252 void updateStackFrames(S.ServiceMap newStack) { 2305 void updateStackFrames(S.ServiceMap newStack) {
2253 List frameElements = _frameList.children; 2306 List frameElements = _frameList.children;
2254 List newFrames = newStack['frames']; 2307 List newFrames;
2308 if (_debugger.saneAsyncStacks &&
2309 (newStack[ObservatoryDebugger.kAsyncCausalStackFrames] != null)) {
2310 newFrames = newStack[ObservatoryDebugger.kAsyncCausalStackFrames];
2311 } else {
2312 newFrames = newStack[ObservatoryDebugger.kStackFrames];
2313 }
2255 2314
2256 // Remove any frames whose functions don't match, starting from 2315 // Remove any frames whose functions don't match, starting from
2257 // bottom of stack. 2316 // bottom of stack.
2258 int oldPos = frameElements.length - 1; 2317 int oldPos = frameElements.length - 1;
2259 int newPos = newFrames.length - 1; 2318 int newPos = newFrames.length - 1;
2260 while (oldPos >= 0 && newPos >= 0) { 2319 while (oldPos >= 0 && newPos >= 0) {
2261 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) { 2320 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) {
2262 // The rest of the frame elements no longer match. Remove them. 2321 // The rest of the frame elements no longer match. Remove them.
2263 for (int i = 0; i <= oldPos; i++) { 2322 for (int i = 0; i <= oldPos; i++) {
2264 // NOTE(turnidge): removeRange is missing, sadly. 2323 // NOTE(turnidge): removeRange is missing, sadly.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2372 2431
2373 // Is this the current frame? 2432 // Is this the current frame?
2374 bool _current = false; 2433 bool _current = false;
2375 2434
2376 // Has this frame been pinned open? 2435 // Has this frame been pinned open?
2377 bool _pinned = false; 2436 bool _pinned = false;
2378 2437
2379 bool _expanded = false; 2438 bool _expanded = false;
2380 2439
2381 void setCurrent(bool value) { 2440 void setCurrent(bool value) {
2382 _frame.function.load().then((func) { 2441 Future load =
2442 (_frame.function != null) ?
2443 _frame.function.load() :
2444 new Future.value(null);
2445 load.then((func) {
2383 _current = value; 2446 _current = value;
2384 if (_current) { 2447 if (_current) {
2385 _expand(); 2448 _expand();
2386 scrollIntoView(); 2449 scrollIntoView();
2387 } else { 2450 } else {
2388 if (_pinned) { 2451 if (_pinned) {
2389 _expand(); 2452 _expand();
2390 } else { 2453 } else {
2391 _unexpand(); 2454 _unexpand();
2392 } 2455 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2425 if (_pinned) { 2488 if (_pinned) {
2426 classes.add('shadow'); 2489 classes.add('shadow');
2427 } else { 2490 } else {
2428 classes.remove('shadow'); 2491 classes.remove('shadow');
2429 } 2492 }
2430 if (_current) { 2493 if (_current) {
2431 classes.add('current'); 2494 classes.add('current');
2432 } else { 2495 } else {
2433 classes.remove('current'); 2496 classes.remove('current');
2434 } 2497 }
2498 if ((_frame.kind == M.FrameKind.asyncSuspensionMarker) ||
2499 (_frame.kind == M.FrameKind.asyncCausal)) {
2500 classes.add('causalFrame');
2501 }
2502 if (_frame.kind == M.FrameKind.asyncSuspensionMarker) {
2503 final content = <Element>[
2504 new SpanElement()
2505 ..children = _createMarkerHeader(_frame.marker)
2506 ];
2507 children = content;
2508 return;
2509 }
2435 ButtonElement expandButton; 2510 ButtonElement expandButton;
2436 final content = <Element>[ 2511 final content = <Element>[
2437 expandButton = new ButtonElement() 2512 expandButton = new ButtonElement()
2438 ..children = _createHeader() 2513 ..children = _createHeader()
2439 ..onClick.listen((e) async { 2514 ..onClick.listen((e) async {
2440 if (e.target is AnchorElement) { 2515 if (e.target is AnchorElement) {
2441 return; 2516 return;
2442 } 2517 }
2443 expandButton.disabled = true; 2518 expandButton.disabled = true;
2444 await _toggleExpand(); 2519 await _toggleExpand();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2527 collapseButton.disabled = false; 2602 collapseButton.disabled = false;
2528 }) 2603 })
2529 ..children = [iconExpandLess.clone(true)] 2604 ..children = [iconExpandLess.clone(true)]
2530 ] 2605 ]
2531 ] 2606 ]
2532 ]); 2607 ]);
2533 } 2608 }
2534 children = content; 2609 children = content;
2535 } 2610 }
2536 2611
2612 List<Element> _createMarkerHeader(String marker) {
2613 final content = [
2614 new DivElement()
2615 ..classes = ['frameSummaryText']
2616 ..children = [
2617 new DivElement()
2618 ..classes = ['frameId']
2619 ..text = 'Frame ${_frame.index}',
2620 new SpanElement()..text = '$marker',
2621 ]
2622 ];
2623 return [
2624 new DivElement()
2625 ..classes = ['frameSummary']
2626 ..children = content
2627 ];
2628 }
2629
2537 List<Element> _createHeader() { 2630 List<Element> _createHeader() {
2538 final content = [ 2631 final content = [
2539 new DivElement() 2632 new DivElement()
2540 ..classes = ['frameSummaryText'] 2633 ..classes = ['frameSummaryText']
2541 ..children = [ 2634 ..children = [
2542 new DivElement() 2635 new DivElement()
2543 ..classes = ['frameId'] 2636 ..classes = ['frameId']
2544 ..text = 'Frame ${_frame.index}', 2637 ..text = 'Frame ${_frame.index}',
2545 new SpanElement() 2638 new SpanElement()
2546 ..children = _frame.function == null 2639 ..children = _frame.function == null
(...skipping 24 matching lines...) Expand all
2571 ..classes = ['frameSummary'] 2664 ..classes = ['frameSummary']
2572 ..children = content 2665 ..children = content
2573 ]; 2666 ];
2574 } 2667 }
2575 2668
2576 String makeExpandKey(String key) { 2669 String makeExpandKey(String key) {
2577 return '${_frame.function.qualifiedName}/${key}'; 2670 return '${_frame.function.qualifiedName}/${key}';
2578 } 2671 }
2579 2672
2580 bool matchFrame(S.Frame newFrame) { 2673 bool matchFrame(S.Frame newFrame) {
2674 if (newFrame.kind != _frame.kind) {
2675 return false;
2676 }
2677 if (newFrame.function == null) {
2678 return frame.function == null;
2679 }
2581 return (newFrame.function.id == _frame.function.id && 2680 return (newFrame.function.id == _frame.function.id &&
2582 newFrame.location.script.id == 2681 newFrame.location.script.id ==
2583 frame.location.script.id); 2682 frame.location.script.id);
2584 } 2683 }
2585 2684
2586 void updateFrame(S.Frame newFrame) { 2685 void updateFrame(S.Frame newFrame) {
2587 assert(matchFrame(newFrame)); 2686 assert(matchFrame(newFrame));
2588 _frame = newFrame; 2687 _frame = newFrame;
2589 } 2688 }
2590 2689
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 ..setAttribute('height', '24') 3356 ..setAttribute('height', '24')
3258 ..children = [ 3357 ..children = [
3259 new PathElement() 3358 new PathElement()
3260 ..setAttribute( 3359 ..setAttribute(
3261 'd', 3360 'd',
3262 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 ' 3361 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
3263 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 ' 3362 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
3264 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 ' 3363 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
3265 '9h2V7h-2v2z') 3364 '9h2V7h-2v2z')
3266 ]; 3365 ];
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698