| OLD | NEW |
| 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 heap_map_element; | 5 library heap_map_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:html'; | 8 import 'dart:html'; |
| 9 import 'dart:math'; | 9 import 'dart:math'; |
| 10 import 'observatory_element.dart'; | 10 import 'observatory_element.dart'; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS); | 36 _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS); |
| 37 | 37 |
| 38 // Returns the next pixel in row-major order. | 38 // Returns the next pixel in row-major order. |
| 39 PixelReference next() => new PixelReference._fromDataIndex( | 39 PixelReference next() => new PixelReference._fromDataIndex( |
| 40 _data, _dataIndex + NUM_COLOR_COMPONENTS); | 40 _data, _dataIndex + NUM_COLOR_COMPONENTS); |
| 41 | 41 |
| 42 // The row-major index of this pixel. | 42 // The row-major index of this pixel. |
| 43 int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS; | 43 int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS; |
| 44 } | 44 } |
| 45 | 45 |
| 46 class ObjectInfo { |
| 47 final address; |
| 48 final size; |
| 49 ObjectInfo(this.address, this.size); |
| 50 } |
| 51 |
| 46 @CustomTag('heap-map') | 52 @CustomTag('heap-map') |
| 47 class HeapMapElement extends ObservatoryElement { | 53 class HeapMapElement extends ObservatoryElement { |
| 48 var _fragmentationCanvas; | 54 var _fragmentationCanvas; |
| 49 var _fragmentationData; | 55 var _fragmentationData; |
| 50 var _pageHeight; | 56 var _pageHeight; |
| 51 var _classIdToColor = {}; | 57 var _classIdToColor = {}; |
| 52 var _colorToClassId = {}; | 58 var _colorToClassId = {}; |
| 53 var _classIdToName = {}; | 59 var _classIdToName = {}; |
| 54 | 60 |
| 55 static final _freeColor = [255, 255, 255, 255]; | 61 static final _freeColor = [255, 255, 255, 255]; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 // TODO(koda): Pick random hue, but fixed saturation and value. | 108 // TODO(koda): Pick random hue, but fixed saturation and value. |
| 103 var rng = new Random(classId); | 109 var rng = new Random(classId); |
| 104 return [rng.nextInt(128), rng.nextInt(128), rng.nextInt(128), 255]; | 110 return [rng.nextInt(128), rng.nextInt(128), rng.nextInt(128), 255]; |
| 105 } | 111 } |
| 106 | 112 |
| 107 String _classNameAt(Point<int> point) { | 113 String _classNameAt(Point<int> point) { |
| 108 var color = new PixelReference(_fragmentationData, point).color; | 114 var color = new PixelReference(_fragmentationData, point).color; |
| 109 return _classIdToName[_colorToClassId[_packColor(color)]]; | 115 return _classIdToName[_colorToClassId[_packColor(color)]]; |
| 110 } | 116 } |
| 111 | 117 |
| 112 // TODO(koda): Find start of object. | 118 ObjectInfo _objectAt(Point<int> point) { |
| 113 int _addressAt(Point<int> point) { | |
| 114 var pagePixels = _pageHeight * _fragmentationData.width; | 119 var pagePixels = _pageHeight * _fragmentationData.width; |
| 115 var index = new PixelReference(_fragmentationData, point).index; | 120 var index = new PixelReference(_fragmentationData, point).index; |
| 116 var pageIndex = index ~/ pagePixels; | 121 var pageIndex = index ~/ pagePixels; |
| 117 var pageOffset = index % pagePixels; | 122 var pageOffset = index % pagePixels; |
| 118 var pages = fragmentation['pages']; | 123 var pages = fragmentation['pages']; |
| 119 if (0 <= pageIndex && pageIndex < pages.length) { | 124 if (pageIndex < 0 || pageIndex >= pages.length) { |
| 120 return int.parse(pages[pageIndex]['object_start']) + | 125 return null; |
| 121 pageOffset * fragmentation['unit_size_bytes']; | |
| 122 } else { | |
| 123 return 0; | |
| 124 } | 126 } |
| 127 // Scan the page to find start and size. |
| 128 var page = pages[pageIndex]; |
| 129 var objects = page['objects']; |
| 130 var offset = 0; |
| 131 var size = 0; |
| 132 for (var i = 0; i < objects.length; i += 2) { |
| 133 size = objects[i]; |
| 134 offset += size; |
| 135 if (offset > pageOffset) { |
| 136 pageOffset = offset - size; |
| 137 break; |
| 138 } |
| 139 } |
| 140 return new ObjectInfo(int.parse(page['object_start']) + |
| 141 pageOffset * fragmentation['unit_size_bytes'], |
| 142 size * fragmentation['unit_size_bytes']); |
| 125 } | 143 } |
| 126 | 144 |
| 127 void _handleMouseMove(MouseEvent event) { | 145 void _handleMouseMove(MouseEvent event) { |
| 128 var addressString = '@ 0x${_addressAt(event.offset).toRadixString(16)}'; | 146 var info = _objectAt(event.offset); |
| 147 var addressString = '${info.size}B @ 0x${info.address.toRadixString(16)}'; |
| 129 var className = _classNameAt(event.offset); | 148 var className = _classNameAt(event.offset); |
| 130 status = (className == '') ? '-' : '$className $addressString'; | 149 status = (className == '') ? '-' : '$className $addressString'; |
| 131 } | 150 } |
| 132 | 151 |
| 133 void _handleClick(MouseEvent event) { | 152 void _handleClick(MouseEvent event) { |
| 134 var address = _addressAt(event.offset).toRadixString(16); | 153 var address = _objectAt(event.offset).address.toRadixString(16); |
| 135 window.location.hash = "/${fragmentation.isolate.link}/address/$address"; | 154 window.location.hash = "/${fragmentation.isolate.link}/address/$address"; |
| 136 } | 155 } |
| 137 | 156 |
| 138 void _updateFragmentationData() { | 157 void _updateFragmentationData() { |
| 139 if (fragmentation == null || _fragmentationCanvas == null) { | 158 if (fragmentation == null || _fragmentationCanvas == null) { |
| 140 return; | 159 return; |
| 141 } | 160 } |
| 142 _updateClassList( | 161 _updateClassList( |
| 143 fragmentation['class_list'], fragmentation['free_class_id']); | 162 fragmentation['class_list'], fragmentation['free_class_id']); |
| 144 var pages = fragmentation['pages']; | 163 var pages = fragmentation['pages']; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 }).whenComplete(done); | 218 }).whenComplete(done); |
| 200 } | 219 } |
| 201 | 220 |
| 202 void fragmentationChanged(oldValue) { | 221 void fragmentationChanged(oldValue) { |
| 203 // Async, in case enteredView has not yet run (observed in JS version). | 222 // Async, in case enteredView has not yet run (observed in JS version). |
| 204 new Future(() { | 223 new Future(() { |
| 205 _updateFragmentationData(); | 224 _updateFragmentationData(); |
| 206 }); | 225 }); |
| 207 } | 226 } |
| 208 } | 227 } |
| OLD | NEW |