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

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

Issue 2646443005: Track async causal stack traces (Closed)
Patch Set: rebase Created 3 years, 10 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 'causal-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('causal-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('causal-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 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 li.classes.add('list-group-item'); 2303 li.classes.add('list-group-item');
2251 li.children.insert(0, messageElement); 2304 li.children.insert(0, messageElement);
2252 2305
2253 messageList.add(li); 2306 messageList.add(li);
2254 } 2307 }
2255 2308
2256 ObservatoryApplication get app => ObservatoryApplication.app; 2309 ObservatoryApplication get app => ObservatoryApplication.app;
2257 2310
2258 void updateStackFrames(S.ServiceMap newStack) { 2311 void updateStackFrames(S.ServiceMap newStack) {
2259 List frameElements = _frameList.children; 2312 List frameElements = _frameList.children;
2260 List newFrames = newStack['frames']; 2313 List newFrames;
2314 if (_debugger.saneAsyncStacks &&
2315 (newStack[ObservatoryDebugger.kAsyncCausalStackFrames] != null)) {
2316 newFrames = newStack[ObservatoryDebugger.kAsyncCausalStackFrames];
2317 } else {
2318 newFrames = newStack[ObservatoryDebugger.kStackFrames];
2319 }
2261 2320
2262 // Remove any frames whose functions don't match, starting from 2321 // Remove any frames whose functions don't match, starting from
2263 // bottom of stack. 2322 // bottom of stack.
2264 int oldPos = frameElements.length - 1; 2323 int oldPos = frameElements.length - 1;
2265 int newPos = newFrames.length - 1; 2324 int newPos = newFrames.length - 1;
2266 while (oldPos >= 0 && newPos >= 0) { 2325 while (oldPos >= 0 && newPos >= 0) {
2267 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) { 2326 if (!frameElements[oldPos].children[0].matchFrame(newFrames[newPos])) {
2268 // The rest of the frame elements no longer match. Remove them. 2327 // The rest of the frame elements no longer match. Remove them.
2269 for (int i = 0; i <= oldPos; i++) { 2328 for (int i = 0; i <= oldPos; i++) {
2270 // NOTE(turnidge): removeRange is missing, sadly. 2329 // NOTE(turnidge): removeRange is missing, sadly.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 2437
2379 // Is this the current frame? 2438 // Is this the current frame?
2380 bool _current = false; 2439 bool _current = false;
2381 2440
2382 // Has this frame been pinned open? 2441 // Has this frame been pinned open?
2383 bool _pinned = false; 2442 bool _pinned = false;
2384 2443
2385 bool _expanded = false; 2444 bool _expanded = false;
2386 2445
2387 void setCurrent(bool value) { 2446 void setCurrent(bool value) {
2388 _frame.function.load().then((func) { 2447 Future load =
2448 (_frame.function != null) ?
2449 _frame.function.load() :
2450 new Future.value(null);
2451 load.then((func) {
2389 _current = value; 2452 _current = value;
2390 if (_current) { 2453 if (_current) {
2391 _expand(); 2454 _expand();
2392 scrollIntoView(); 2455 scrollIntoView();
2393 } else { 2456 } else {
2394 if (_pinned) { 2457 if (_pinned) {
2395 _expand(); 2458 _expand();
2396 } else { 2459 } else {
2397 _unexpand(); 2460 _unexpand();
2398 } 2461 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 if (_pinned) { 2494 if (_pinned) {
2432 classes.add('shadow'); 2495 classes.add('shadow');
2433 } else { 2496 } else {
2434 classes.remove('shadow'); 2497 classes.remove('shadow');
2435 } 2498 }
2436 if (_current) { 2499 if (_current) {
2437 classes.add('current'); 2500 classes.add('current');
2438 } else { 2501 } else {
2439 classes.remove('current'); 2502 classes.remove('current');
2440 } 2503 }
2504 if ((_frame.kind == M.FrameKind.asyncSuspensionMarker) ||
2505 (_frame.kind == M.FrameKind.asyncCausal)) {
2506 classes.add('causalFrame');
2507 }
2508 if (_frame.kind == M.FrameKind.asyncSuspensionMarker) {
2509 final content = <Element>[
2510 new SpanElement()
2511 ..children = _createMarkerHeader(_frame.marker)
2512 ];
2513 children = content;
2514 return;
2515 }
2441 ButtonElement expandButton; 2516 ButtonElement expandButton;
2442 final content = <Element>[ 2517 final content = <Element>[
2443 expandButton = new ButtonElement() 2518 expandButton = new ButtonElement()
2444 ..children = _createHeader() 2519 ..children = _createHeader()
2445 ..onClick.listen((e) async { 2520 ..onClick.listen((e) async {
2446 if (e.target is AnchorElement) { 2521 if (e.target is AnchorElement) {
2447 return; 2522 return;
2448 } 2523 }
2449 expandButton.disabled = true; 2524 expandButton.disabled = true;
2450 await _toggleExpand(); 2525 await _toggleExpand();
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2533 collapseButton.disabled = false; 2608 collapseButton.disabled = false;
2534 }) 2609 })
2535 ..children = [iconExpandLess.clone(true)] 2610 ..children = [iconExpandLess.clone(true)]
2536 ] 2611 ]
2537 ] 2612 ]
2538 ]); 2613 ]);
2539 } 2614 }
2540 children = content; 2615 children = content;
2541 } 2616 }
2542 2617
2618 List<Element> _createMarkerHeader(String marker) {
2619 final content = [
2620 new DivElement()
2621 ..classes = ['frameSummaryText']
2622 ..children = [
2623 new DivElement()
2624 ..classes = ['frameId']
2625 ..text = 'Frame ${_frame.index}',
2626 new SpanElement()..text = '$marker',
2627 ]
2628 ];
2629 return [
2630 new DivElement()
2631 ..classes = ['frameSummary']
2632 ..children = content
2633 ];
2634 }
2635
2543 List<Element> _createHeader() { 2636 List<Element> _createHeader() {
2544 final content = [ 2637 final content = [
2545 new DivElement() 2638 new DivElement()
2546 ..classes = ['frameSummaryText'] 2639 ..classes = ['frameSummaryText']
2547 ..children = [ 2640 ..children = [
2548 new DivElement() 2641 new DivElement()
2549 ..classes = ['frameId'] 2642 ..classes = ['frameId']
2550 ..text = 'Frame ${_frame.index}', 2643 ..text = 'Frame ${_frame.index}',
2551 new SpanElement() 2644 new SpanElement()
2552 ..children = _frame.function == null 2645 ..children = _frame.function == null
(...skipping 24 matching lines...) Expand all
2577 ..classes = ['frameSummary'] 2670 ..classes = ['frameSummary']
2578 ..children = content 2671 ..children = content
2579 ]; 2672 ];
2580 } 2673 }
2581 2674
2582 String makeExpandKey(String key) { 2675 String makeExpandKey(String key) {
2583 return '${_frame.function.qualifiedName}/${key}'; 2676 return '${_frame.function.qualifiedName}/${key}';
2584 } 2677 }
2585 2678
2586 bool matchFrame(S.Frame newFrame) { 2679 bool matchFrame(S.Frame newFrame) {
2680 if (newFrame.kind != _frame.kind) {
2681 return false;
2682 }
2683 if (newFrame.function == null) {
2684 return frame.function == null;
2685 }
2587 return (newFrame.function.id == _frame.function.id && 2686 return (newFrame.function.id == _frame.function.id &&
2588 newFrame.location.script.id == 2687 newFrame.location.script.id ==
2589 frame.location.script.id); 2688 frame.location.script.id);
2590 } 2689 }
2591 2690
2592 void updateFrame(S.Frame newFrame) { 2691 void updateFrame(S.Frame newFrame) {
2593 assert(matchFrame(newFrame)); 2692 assert(matchFrame(newFrame));
2594 _frame = newFrame; 2693 _frame = newFrame;
2595 } 2694 }
2596 2695
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
3263 ..setAttribute('height', '24') 3362 ..setAttribute('height', '24')
3264 ..children = [ 3363 ..children = [
3265 new PathElement() 3364 new PathElement()
3266 ..setAttribute( 3365 ..setAttribute(
3267 'd', 3366 'd',
3268 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 ' 3367 'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
3269 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 ' 3368 '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
3270 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 ' 3369 '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
3271 '9h2V7h-2v2z') 3370 '9h2V7h-2v2z')
3272 ]; 3371 ];
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/elements/css/shared.css ('k') | runtime/observatory/lib/src/models/objects/frame.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698