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

Side by Side Diff: chrome_linux/resources/inspector/HeapSnapshotWorker.js

Issue 7192017: Update reference builds to r89207. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/reference_builds/
Patch Set: '' Created 9 years, 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
1
2
3
4 WebInspector = {};
5 WebInspector.UIString = function(s) { return s; };
6
7
8
9 function binarySearch(object, array, comparator)
10 {
11 var first = 0;
12 var last = array.length - 1;
13
14 while (first <= last) {
15 var mid = (first + last) >> 1;
16 var c = comparator(object, array[mid]);
17 if (c > 0)
18 first = mid + 1;
19 else if (c < 0)
20 last = mid - 1;
21 else
22 return mid;
23 }
24
25
26 return -(first + 1);
27 }
28
29 Object.defineProperty(Array.prototype, "binaryIndexOf", { value: function(value, comparator)
30 {
31 var result = binarySearch(value, this, comparator);
32 return result >= 0 ? result : -1;
33 }});
34
35 function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunctio n)
36 {
37 var index = binarySearch(anObject, aList, aFunction);
38 if (index < 0)
39
40 return -index - 1;
41 else {
42
43 while (index > 0 && aFunction(anObject, aList[index - 1]) === 0)
44 index--;
45 return index;
46 }
47 }
48 ;
49
50
51 WebInspector.HeapSnapshotLoader = function()
52 {
53 this._json = "";
54 this._state = "find-snapshot-info";
55 this._snapshot = {};
56 }
57
58 WebInspector.HeapSnapshotLoader.prototype = {
59 _findBalancedCurlyBrackets: function()
60 {
61 var counter = 0;
62 var openingBracket = "{".charCodeAt(0), closingBracket = "}".charCodeAt(0);
63 for (var i = 0, l = this._json.length; i < l; ++i) {
64 var character = this._json.charCodeAt(i);
65 if (character === openingBracket)
66 ++counter;
67 else if (character === closingBracket) {
68 if (--counter === 0)
69 return i + 1;
70 }
71 }
72 return -1;
73 },
74
75 finishLoading: function()
76 {
77 if (!this._json)
78 return null;
79 this._parseStringsArray();
80 this._json = "";
81 var result = new WebInspector.HeapSnapshot(this._snapshot);
82 this._json = "";
83 this._snapshot = {};
84 return result;
85 },
86
87 _parseNodes: function()
88 {
89 var index = 0;
90 var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".c harCodeAt(0);
91 var length = this._json.length;
92 while (true) {
93 while (index < length) {
94 var code = this._json.charCodeAt(index);
95 if (char0 <= code && code <= char9)
96 break;
97 else if (code === closingBracket) {
98 this._json = this._json.slice(index + 1);
99
100 this._snapshot.nodes = this._snapshot.nodes.slice(0);
101 return false;
102 }
103 ++index;
104 }
105 if (index === length) {
106 this._json = "";
107 return true;
108 }
109 var startIndex = index;
110 while (index < length) {
111 var code = this._json.charCodeAt(index);
112 if (char0 > code || code > char9)
113 break;
114 ++index;
115 }
116 if (index === length) {
117 this._json = this._json.slice(startIndex);
118 return true;
119 }
120 this._snapshot.nodes.push(parseInt(this._json.slice(startIndex, index)));
121 }
122 },
123
124 _parseStringsArray: function()
125 {
126 var closingBracketIndex = this._json.lastIndexOf("]");
127 if (closingBracketIndex === -1)
128 throw new Error("Incomplete JSON");
129 this._json = this._json.slice(0, closingBracketIndex + 1);
130 this._snapshot.strings = JSON.parse(this._json);
131 },
132
133 pushJSONChunk: function(chunk)
134 {
135 this._json += chunk;
136 switch (this._state) {
137 case "find-snapshot-info": {
138 var snapshotToken = "\"snapshot\"";
139 var snapshotTokenIndex = this._json.indexOf(snapshotToken);
140 if (snapshotTokenIndex === -1)
141 throw new Error("Snapshot token not found");
142 this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
143 this._state = "parse-snapshot-info";
144 this.pushJSONChunk("");
145 break;
146 }
147 case "parse-snapshot-info": {
148 var closingBracketIndex = this._findBalancedCurlyBrackets();
149 if (closingBracketIndex === -1)
150 return;
151 this._snapshot.snapshot = JSON.parse(this._json.slice(0, closingBracketIndex));
152 this._json = this._json.slice(closingBracketIndex);
153 this._state = "find-nodes";
154 this.pushJSONChunk("");
155 break;
156 }
157 case "find-nodes": {
158 var nodesToken = "\"nodes\"";
159 var nodesTokenIndex = this._json.indexOf(nodesToken);
160 if (nodesTokenIndex === -1)
161 return;
162 var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
163 if (bracketIndex === -1)
164 return;
165 this._json = this._json.slice(bracketIndex + 1);
166 this._state = "parse-nodes-meta-info";
167 this.pushJSONChunk("");
168 break;
169 }
170 case "parse-nodes-meta-info": {
171 var closingBracketIndex = this._findBalancedCurlyBrackets();
172 if (closingBracketIndex === -1)
173 return;
174 this._snapshot.nodes = [JSON.parse(this._json.slice(0, closingBracketIndex))];
175 this._json = this._json.slice(closingBracketIndex);
176 this._state = "parse-nodes";
177 this.pushJSONChunk("");
178 break;
179 }
180 case "parse-nodes": {
181 if (this._parseNodes())
182 return;
183 this._state = "find-strings";
184 this.pushJSONChunk("");
185 break;
186 }
187 case "find-strings": {
188 var stringsToken = "\"strings\"";
189 var stringsTokenIndex = this._json.indexOf(stringsToken);
190 if (stringsTokenIndex === -1)
191 return;
192 var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
193 if (bracketIndex === -1)
194 return;
195 this._json = this._json.slice(bracketIndex);
196 this._state = "accumulate-strings";
197 break;
198 }
199 case "accumulate-strings":
200 break;
201 }
202 }
203 };
204
205 WebInspector.HeapSnapshotArraySlice = function(snapshot, arrayName, start, end)
206 {
207
208
209 this._snapshot = snapshot;
210 this._arrayName = arrayName;
211 this._start = start;
212 this.length = end - start;
213 }
214
215 WebInspector.HeapSnapshotArraySlice.prototype = {
216 item: function(index)
217 {
218 return this._snapshot[this._arrayName][this._start + index];
219 }
220 }
221
222 WebInspector.HeapSnapshotEdge = function(snapshot, edges, edgeIndex)
223 {
224 this._snapshot = snapshot;
225 this._edges = edges;
226 this.edgeIndex = edgeIndex || 0;
227 }
228
229 WebInspector.HeapSnapshotEdge.prototype = {
230 clone: function()
231 {
232 return new WebInspector.HeapSnapshotEdge(this._snapshot, this._edges, this.edgeI ndex);
233 },
234
235 get hasStringName()
236 {
237 if (!this.isShortcut)
238 return this._hasStringName;
239 return isNaN(parseInt(this._name, 10));
240 },
241
242 get isElement()
243 {
244 return this._type() === this._snapshot._edgeElementType;
245 },
246
247 get isHidden()
248 {
249 return this._type() === this._snapshot._edgeHiddenType;
250 },
251
252 get isInternal()
253 {
254 return this._type() === this._snapshot._edgeInternalType;
255 },
256
257 get isInvisible()
258 {
259 return this._type() === this._snapshot._edgeInvisibleType;
260 },
261
262 get isShortcut()
263 {
264 return this._type() === this._snapshot._edgeShortcutType;
265 },
266
267 get name()
268 {
269 if (!this.isShortcut)
270 return this._name;
271 var numName = parseInt(this._name, 10);
272 return isNaN(numName) ? this._name : numName;
273 },
274
275 get node()
276 {
277 return new WebInspector.HeapSnapshotNode(this._snapshot, this.nodeIndex);
278 },
279
280 get nodeIndex()
281 {
282 return this._edges.item(this.edgeIndex + this._snapshot._edgeToNodeOffset);
283 },
284
285 get rawEdges()
286 {
287 return this._edges;
288 },
289
290 toString: function()
291 {
292 switch (this.type) {
293 case "context": return "->" + this.name;
294 case "element": return "[" + this.name + "]";
295 case "property":
296 return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\" ]";
297 case "shortcut":
298 var name = this.name;
299 if (typeof name === "string")
300 return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\" ]";
301 else
302 return "[" + this.name + "]";
303 case "internal":
304 case "hidden":
305 case "invisible":
306 return "{" + this.name + "}";
307 };
308 return "?" + this.name + "?";
309 },
310
311 get type()
312 {
313 return this._snapshot._edgeTypes[this._type()];
314 },
315
316 get _hasStringName()
317 {
318 return !this.isElement && !this.isHidden;
319 },
320
321 get _name()
322 {
323 return this._hasStringName ? this._snapshot._strings[this._nameOrIndex] : this._ nameOrIndex;
324 },
325
326 get _nameOrIndex()
327 {
328 return this._edges.item(this.edgeIndex + this._snapshot._edgeNameOffset);
329 },
330
331 _type: function()
332 {
333 return this._edges.item(this.edgeIndex + this._snapshot._edgeTypeOffset);
334 }
335 };
336
337 WebInspector.HeapSnapshotEdgeIterator = function(edge)
338 {
339 this.edge = edge;
340 }
341
342 WebInspector.HeapSnapshotEdgeIterator.prototype = {
343 first: function()
344 {
345 this.edge.edgeIndex = 0;
346 },
347
348 hasNext: function()
349 {
350 return this.edge.edgeIndex < this.edge._edges.length;
351 },
352
353 get index()
354 {
355 return this.edge.edgeIndex;
356 },
357
358 set index(newIndex)
359 {
360 this.edge.edgeIndex = newIndex;
361 },
362
363 get item()
364 {
365 return this.edge;
366 },
367
368 next: function()
369 {
370 this.edge.edgeIndex += this.edge._snapshot._edgeFieldsCount;
371 }
372 };
373
374 WebInspector.HeapSnapshotRetainerEdge = function(snapshot, retainers, retainerIn dex)
375 {
376 this._snapshot = snapshot;
377 this._retainers = retainers;
378 this.retainerIndex = retainerIndex || 0;
379 }
380
381 WebInspector.HeapSnapshotRetainerEdge.prototype = {
382 clone: function()
383 {
384 return new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._retainers , this.retainerIndex);
385 },
386
387 get hasStringName()
388 {
389 return this._edge.hasStringName;
390 },
391
392 get isElement()
393 {
394 return this._edge.isElement;
395 },
396
397 get isHidden()
398 {
399 return this._edge.isHidden;
400 },
401
402 get isInternal()
403 {
404 return this._edge.isInternal;
405 },
406
407 get isInvisible()
408 {
409 return this._edge.isInvisible;
410 },
411
412 get isShortcut()
413 {
414 return this._edge.isShortcut;
415 },
416
417 get name()
418 {
419 return this._edge.name;
420 },
421
422 get node()
423 {
424 return this._node;
425 },
426
427 get nodeIndex()
428 {
429 return this._nodeIndex;
430 },
431
432 get retainerIndex()
433 {
434 return this._retainerIndex;
435 },
436
437 set retainerIndex(newIndex)
438 {
439 if (newIndex !== this._retainerIndex) {
440 this._retainerIndex = newIndex;
441 this._setupEdge();
442 }
443 },
444
445 _setupEdge: function()
446 {
447 var globalEdgeIndex = this._retainers.item(this._retainerIndex);
448 this._nodeIndex = this._snapshot._findNearestNodeIndex(globalEdgeIndex);
449 this._node = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
450 var edgeIndex = globalEdgeIndex - this._nodeIndex - this._snapshot._firstEdgeOff set;
451 this._edge = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdg es, edgeIndex);
452 },
453
454 toString: function()
455 {
456 return this._edge.toString();
457 },
458
459 get type()
460 {
461 return this._edge.type;
462 }
463 }
464
465 WebInspector.HeapSnapshotRetainerEdgeIterator = function(retainer)
466 {
467 this.retainer = retainer;
468 }
469
470 WebInspector.HeapSnapshotRetainerEdgeIterator.prototype = {
471 first: function()
472 {
473 this.retainer.retainerIndex = 0;
474 },
475
476 hasNext: function()
477 {
478 return this.retainer.retainerIndex < this.retainer._retainers.length;
479 },
480
481 get index()
482 {
483 return this.retainer.retainerIndex;
484 },
485
486 set index(newIndex)
487 {
488 this.retainer.retainerIndex = newIndex;
489 },
490
491 get item()
492 {
493 return this.retainer;
494 },
495
496 next: function()
497 {
498 ++this.retainer.retainerIndex;
499 }
500 };
501
502 WebInspector.HeapSnapshotNode = function(snapshot, nodeIndex)
503 {
504 this._snapshot = snapshot;
505 this._firstNodeIndex = nodeIndex;
506 this.nodeIndex = nodeIndex;
507 }
508
509 WebInspector.HeapSnapshotNode.prototype = {
510 get className()
511 {
512 switch (this.type) {
513 case "hidden":
514 return WebInspector.UIString("(system)");
515 case "object": {
516 var commentPos = this.name.indexOf("/");
517 return commentPos !== -1 ? this.name.substring(0, commentPos).trimRight() : this .name;
518 }
519 case "native": {
520 var entitiesCountPos = this.name.indexOf("/");
521 return entitiesCountPos !== -1 ? this.name.substring(0, entitiesCountPos).trimRi ght() : this.name;
522 }
523 case "code":
524 return WebInspector.UIString("(compiled code)");
525 default:
526 return "(" + this.type + ")";
527 }
528 },
529
530 get dominatorIndex()
531 {
532 return this._nodes[this.nodeIndex + this._snapshot._dominatorOffset];
533 },
534
535 get edges()
536 {
537 return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEd ge(this._snapshot, this.rawEdges));
538 },
539
540 get edgesCount()
541 {
542 return this._nodes[this.nodeIndex + this._snapshot._edgesCountOffset];
543 },
544
545 get id()
546 {
547 return this._nodes[this.nodeIndex + this._snapshot._nodeIdOffset];
548 },
549
550 get instancesCount()
551 {
552 return this._nodes[this.nodeIndex + this._snapshot._nodeInstancesCountOffset];
553 },
554
555 get isHidden()
556 {
557 return this._type() === this._snapshot._nodeHiddenType;
558 },
559
560 get isRoot()
561 {
562 return this.nodeIndex === this._snapshot._rootNodeIndex;
563 },
564
565 get name()
566 {
567 return this._snapshot._strings[this._name()];
568 },
569
570 get rawEdges()
571 {
572 var firstEdgeIndex = this._firstEdgeIndex();
573 return new WebInspector.HeapSnapshotArraySlice(this._snapshot, "_nodes", firstEd geIndex, firstEdgeIndex + this.edgesCount * this._snapshot._edgeFieldsCount);
574 },
575
576 get retainedSize()
577 {
578 return this._nodes[this.nodeIndex + this._snapshot._nodeRetainedSizeOffset];
579 },
580
581 get retainers()
582 {
583 return new WebInspector.HeapSnapshotRetainerEdgeIterator(new WebInspector.HeapSn apshotRetainerEdge(this._snapshot, this._snapshot._retainersForNode(this)));
584 },
585
586 get selfSize()
587 {
588 return this._nodes[this.nodeIndex + this._snapshot._nodeSelfSizeOffset];
589 },
590
591 get type()
592 {
593 return this._snapshot._nodeTypes[this._type()];
594 },
595
596 _name: function()
597 {
598 return this._nodes[this.nodeIndex + this._snapshot._nodeNameOffset];
599 },
600
601 get _nodes()
602 {
603 return this._snapshot._nodes;
604 },
605
606 _firstEdgeIndex: function()
607 {
608 return this.nodeIndex + this._snapshot._firstEdgeOffset;
609 },
610
611 get _nextNodeIndex()
612 {
613 return this._firstEdgeIndex() + this.edgesCount * this._snapshot._edgeFieldsCoun t;
614 },
615
616 _type: function()
617 {
618 return this._nodes[this.nodeIndex + this._snapshot._nodeTypeOffset];
619 }
620 };
621
622 WebInspector.HeapSnapshotNodeIterator = function(node)
623 {
624 this.node = node;
625 }
626
627 WebInspector.HeapSnapshotNodeIterator.prototype = {
628 first: function()
629 {
630 this.node.nodeIndex = this.node._firstNodeIndex;
631 },
632
633 hasNext: function()
634 {
635 return this.node.nodeIndex < this.node._nodes.length;
636 },
637
638 get index()
639 {
640 return this.node.nodeIndex;
641 },
642
643 set index(newIndex)
644 {
645 this.node.nodeIndex = newIndex;
646 },
647
648 get item()
649 {
650 return this.node;
651 },
652
653 next: function()
654 {
655 this.node.nodeIndex = this.node._nextNodeIndex;
656 }
657 }
658
659 WebInspector.HeapSnapshot = function(profile)
660 {
661 this.uid = profile.snapshot.uid;
662 this._nodes = profile.nodes;
663 this._strings = profile.strings;
664
665 this._init();
666 }
667
668 WebInspector.HeapSnapshot.prototype = {
669 _init: function()
670 {
671 this._metaNodeIndex = 0;
672 this._rootNodeIndex = 1;
673 var meta = this._nodes[this._metaNodeIndex];
674 this._nodeTypeOffset = meta.fields.indexOf("type");
675 this._nodeNameOffset = meta.fields.indexOf("name");
676 this._nodeIdOffset = meta.fields.indexOf("id");
677 this._nodeInstancesCountOffset = this._nodeIdOffset;
678 this._nodeSelfSizeOffset = meta.fields.indexOf("self_size");
679 this._nodeRetainedSizeOffset = meta.fields.indexOf("retained_size");
680 this._dominatorOffset = meta.fields.indexOf("dominator");
681 this._edgesCountOffset = meta.fields.indexOf("children_count");
682 this._firstEdgeOffset = meta.fields.indexOf("children");
683 this._nodeTypes = meta.types[this._nodeTypeOffset];
684 this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
685 var edgesMeta = meta.types[this._firstEdgeOffset];
686 this._edgeFieldsCount = edgesMeta.fields.length;
687 this._edgeTypeOffset = edgesMeta.fields.indexOf("type");
688 this._edgeNameOffset = edgesMeta.fields.indexOf("name_or_index");
689 this._edgeToNodeOffset = edgesMeta.fields.indexOf("to_node");
690 this._edgeTypes = edgesMeta.types[this._edgeTypeOffset];
691 this._edgeElementType = this._edgeTypes.indexOf("element");
692 this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
693 this._edgeInternalType = this._edgeTypes.indexOf("internal");
694 this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
695 this._edgeInvisibleType = this._edgeTypes.length;
696 this._edgeTypes.push("invisible");
697
698 this._markInvisibleEdges();
699 },
700
701 dispose: function()
702 {
703 delete this._nodes;
704 delete this._strings;
705 delete this._retainers;
706 delete this._retainerIndex;
707 delete this._nodeIndex;
708 if (this._aggregates) {
709 delete this._aggregates;
710 this._aggregatesIndexesSorted = false;
711 }
712 delete this._baseNodeIds;
713 },
714
715 get _allNodes()
716 {
717 return new WebInspector.HeapSnapshotNodeIterator(this.rootNode);
718 },
719
720 get nodeCount()
721 {
722 if (this._nodeCount)
723 return this._nodeCount;
724
725 this._nodeCount = 0;
726 for (var iter = this._allNodes; iter.hasNext(); iter.next())
727 ++this._nodeCount;
728 return this._nodeCount;
729 },
730
731 nodeFieldValuesByIndex: function(fieldName, indexes)
732 {
733 var node = new WebInspector.HeapSnapshotNode(this);
734 var result = new Array(indexes.length);
735 for (var i = 0, l = indexes.length; i < l; ++i) {
736 node.nodeIndex = indexes[i];
737 result[i] = node[fieldName];
738 }
739 return result;
740 },
741
742 get rootNode()
743 {
744 return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
745 },
746
747 get rootNodeIndex()
748 {
749 return this._rootNodeIndex;
750 },
751
752 get totalSize()
753 {
754 return this.rootNode.retainedSize;
755 },
756
757 _retainersForNode: function(node)
758 {
759 if (!this._retainers)
760 this._buildRetainers();
761
762 var retIndexFrom = this._getRetainerIndex(node.nodeIndex);
763 var retIndexTo = this._getRetainerIndex(node._nextNodeIndex);
764 return new WebInspector.HeapSnapshotArraySlice(this, "_retainers", retIndexFrom, retIndexTo);
765 },
766
767 aggregates: function(sortedIndexes)
768 {
769 if (!this._aggregates)
770 this._buildAggregates();
771 if (sortedIndexes && !this._aggregatesIndexesSorted)
772 this._sortAggregateIndexes();
773 return this._aggregates;
774 },
775
776 _buildRetainers: function()
777 {
778 if (!this._nodeIndex)
779 this._buildNodeIndex();
780
781 this._retainerIndex = new Array(this._nodeIndex.length);
782 for (var i = 0, l = this._retainerIndex.length; i < l; ++i)
783 this._retainerIndex[i] = 0;
784 for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
785 var node = nodesIter.node;
786 for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
787 var edge = edgesIter.edge;
788 var nodeIndex = edge.nodeIndex;
789 var position = this._findNodePositionInIndex(nodeIndex);
790 ++this._retainerIndex[position];
791 }
792 }
793 var retainerCount = 0;
794 for (i = 0, l = this._retainerIndex.length; i < l; ++i)
795 retainerCount += this._retainerIndex[i];
796 this._retainers = new Array(retainerCount + 1);
797 var retainerPosition = 0;
798 for (i = 0, l = this._retainerIndex.length; i < l; ++i) {
799 retainerCount = this._retainers[retainerPosition] = this._retainerIndex[i];
800 this._retainerIndex[i] = retainerPosition;
801 retainerPosition += retainerCount;
802 }
803 for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
804 var node = nodesIter.node;
805 for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
806 var edge = edgesIter.edge;
807 var nodeIndex = edge.nodeIndex;
808 var retIndex = this._getRetainerIndex(nodeIndex);
809 var idx = retIndex + (--this._retainers[retIndex]);
810 this._retainers[idx] = node.nodeIndex + this._firstEdgeOffset + edge.edgeIndex;
811 }
812 }
813 },
814
815 _buildAggregates: function()
816 {
817 this._aggregates = {};
818 for (var iter = this._allNodes; iter.hasNext(); iter.next()) {
819 var node = iter.node;
820 var className = node.className;
821 var nameMatters = node.type === "object" || node.type === "native";
822 if (node.type !== "native" && node.selfSize === 0)
823 continue;
824 if (!(className in this._aggregates))
825 this._aggregates[className] = { count: 0, self: 0, maxRet: 0, type: node.type, n ame: nameMatters ? node.name : null, idxs: [] };
826 var clss = this._aggregates[className];
827 ++clss.count;
828 clss.self += node.selfSize;
829 if (node.retainedSize > clss.maxRet)
830 clss.maxRet = node.retainedSize;
831 clss.idxs.push(node.nodeIndex);
832 }
833
834 for (var className in this._aggregates)
835 this._aggregates[className].idxs = this._aggregates[className].idxs.slice(0);
836 },
837
838 _sortAggregateIndexes: function()
839 {
840 var nodeA = new WebInspector.HeapSnapshotNode(this);
841 var nodeB = new WebInspector.HeapSnapshotNode(this);
842 for (var clss in this._aggregates)
843 this._aggregates[clss].idxs.sort(
844 function(idxA, idxB) {
845 nodeA.nodeIndex = idxA;
846 nodeB.nodeIndex = idxB;
847 return nodeA.id < nodeB.id ? -1 : 1;
848 });
849
850 this._aggregatesIndexesSorted = true;
851 },
852
853 _buildNodeIndex: function()
854 {
855 var count = 0;
856 for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next(), ++co unt);
857 this._nodeIndex = new Array(count + 1);
858 count = 0;
859 for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next(), ++count)
860 this._nodeIndex[count] = nodesIter.index;
861 this._nodeIndex[count] = this._nodes.length;
862 },
863
864 _findNodePositionInIndex: function(index)
865 {
866 return binarySearch(index, this._nodeIndex, this._numbersComparator);
867 },
868
869 _findNearestNodeIndex: function(index)
870 {
871 var result = this._findNodePositionInIndex(index);
872 if (result < 0) {
873 result = -result - 1;
874 nodeIndex = this._nodeIndex[result];
875
876 if (nodeIndex > index)
877 nodeIndex = this._nodeIndex[result - 1];
878 } else
879 var nodeIndex = this._nodeIndex[result];
880 return nodeIndex;
881 },
882
883 _getRetainerIndex: function(nodeIndex)
884 {
885 var nodePosition = this._findNodePositionInIndex(nodeIndex);
886 return this._retainerIndex[nodePosition];
887 },
888
889 _markInvisibleEdges: function()
890 {
891
892
893
894 for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
895 var edge = iter.edge;
896 if (!edge.isShortcut)
897 continue;
898 var node = edge.node;
899 var propNames = {};
900 for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
901 var globalObjEdge = innerIter.edge;
902 if (globalObjEdge.isShortcut)
903 propNames[globalObjEdge._nameOrIndex] = true;
904 }
905 for (innerIter.first(); innerIter.hasNext(); innerIter.next()) {
906 var globalObjEdge = innerIter.edge;
907 if (!globalObjEdge.isShortcut
908 && globalObjEdge.node.isHidden
909 && globalObjEdge._hasStringName
910 && (globalObjEdge._nameOrIndex in propNames))
911 this._nodes[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTy peOffset] = this._edgeInvisibleType;
912 }
913 }
914 },
915
916 _numbersComparator: function(a, b)
917 {
918 return a < b ? -1 : (a > b ? 1 : 0);
919 },
920
921 baseSnapshotHasNode: function(baseSnapshotId, className, nodeId)
922 {
923 return this._baseNodeIds[baseSnapshotId][className].binaryIndexOf(nodeId, this._ numbersComparator) !== -1;
924 },
925
926 pushBaseIds: function(baseSnapshotId, className, nodeIds)
927 {
928 if (!this._baseNodeIds)
929 this._baseNodeIds = [];
930 if (!this._baseNodeIds[baseSnapshotId])
931 this._baseNodeIds[baseSnapshotId] = {};
932 this._baseNodeIds[baseSnapshotId][className] = nodeIds;
933 },
934
935 createDiff: function(className)
936 {
937 return new WebInspector.HeapSnapshotsDiff(this, className);
938 },
939
940 _parseFilter: function(filter)
941 {
942 if (!filter)
943 return null;
944 var parsedFilter = eval("(function(){return " + filter + "})()");
945 return parsedFilter.bind(this);
946 },
947
948 createEdgesProvider: function(nodeIndex, filter)
949 {
950 return new WebInspector.HeapSnapshotEdgesProvider(this, nodeIndex, this._parseFi lter(filter));
951 },
952
953 createNodesProvider: function(filter)
954 {
955 return new WebInspector.HeapSnapshotNodesProvider(this, this._parseFilter(filter ));
956 },
957
958 createNodesProviderForClass: function(className)
959 {
960 return new WebInspector.HeapSnapshotNodesProvider(this, null, className);
961 },
962
963 createPathFinder: function(targetNodeIndex, skipHidden)
964 {
965 return new WebInspector.HeapSnapshotPathFinder(this, targetNodeIndex, skipHidden );
966 },
967
968 updateStaticData: function()
969 {
970 return {nodeCount: this.nodeCount, rootNodeIndex: this._rootNodeIndex, totalSize : this.totalSize, uid: this.uid};
971 }
972 };
973
974 WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter, it erationOrder)
975 {
976 this._filter = filter;
977 this._iterator = iterator;
978 this._iterationOrder = iterationOrder ? iterationOrder.slice(0) : null;
979 this._position = 0;
980 this._lastComparator = null;
981 }
982
983 WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
984 _createIterationOrder: function()
985 {
986 this._iterationOrder = [];
987 var iterator = this._iterator;
988 if (!this._filter) {
989 for (iterator.first(); iterator.hasNext(); iterator.next())
990 this._iterationOrder.push(iterator.index);
991 } else {
992 for (iterator.first(); iterator.hasNext(); iterator.next()) {
993 if (this._filter(iterator.item))
994 this._iterationOrder.push(iterator.index);
995 }
996 }
997 },
998
999 first: function()
1000 {
1001 this._position = 0;
1002 },
1003
1004 hasNext: function()
1005 {
1006 return this._position < this._iterationOrder.length;
1007 },
1008
1009 get isEmpty()
1010 {
1011 if (this._iterationOrder)
1012 return !this._iterationOrder.length;
1013 var iterator = this._iterator;
1014 if (!this._filter) {
1015 iterator.first();
1016 return !iterator.hasNext();
1017 }
1018 for (iterator.first(); iterator.hasNext(); iterator.next())
1019 if (this._filter(iterator.item)) return false;
1020 return true;
1021 },
1022
1023 get item()
1024 {
1025 this._iterator.index = this._iterationOrder[this._position];
1026 return this._iterator.item;
1027 },
1028
1029 get length()
1030 {
1031 if (!this._iterationOrder)
1032 this._createIterationOrder();
1033 return this._iterationOrder.length;
1034 },
1035
1036 next: function()
1037 {
1038 ++this._position;
1039 },
1040
1041 serializeNextItems: function(count)
1042 {
1043 var result = new Array(count);
1044 for (var i = 0 ; i < count && this.hasNext(); ++i, this.next())
1045 result[i] = this._serialize(this.item);
1046 result.length = i;
1047 result.hasNext = this.hasNext();
1048 result.totalLength = this.length;
1049 return result;
1050 },
1051
1052 sortAndRewind: function(comparator)
1053 {
1054 var result = this.sort(comparator);
1055 if (result)
1056 this.first();
1057 return result;
1058 }
1059 }
1060
1061 WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = fu nction(fieldNames)
1062 {
1063 return {fieldName1:fieldNames[0], ascending1:fieldNames[1], fieldName2:fieldName s[2], ascending2:fieldNames[3]};
1064 }
1065
1066 WebInspector.HeapSnapshotEdgesProvider = function(snapshot, nodeIndex, filter)
1067 {
1068 this.snapshot = snapshot;
1069 var node = new WebInspector.HeapSnapshotNode(snapshot, nodeIndex);
1070 WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, new WebInspector.Hea pSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, node.rawEdges) ), filter);
1071 }
1072
1073 WebInspector.HeapSnapshotEdgesProvider.prototype = {
1074 _serialize: function(edge)
1075 {
1076 return {name: edge.name, node: WebInspector.HeapSnapshotNodesProvider.prototype. _serialize(edge.node), nodeIndex: edge.nodeIndex, type: edge.type};
1077 },
1078
1079 sort: function(comparator)
1080 {
1081 if (this._lastComparator === comparator)
1082 return false;
1083 this._lastComparator = comparator;
1084 var fieldName1 = comparator.fieldName1;
1085 var fieldName2 = comparator.fieldName2;
1086 var ascending1 = comparator.ascending1;
1087 var ascending2 = comparator.ascending2;
1088
1089 var edgeA = this._iterator.item.clone();
1090 var edgeB = edgeA.clone();
1091 var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
1092 var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
1093
1094 function sortByEdgeFieldName(ascending, indexA, indexB)
1095 {
1096 edgeA.edgeIndex = indexA;
1097 edgeB.edgeIndex = indexB;
1098 if (edgeB.name === "__proto__") return -1;
1099 if (edgeA.name === "__proto__") return 1;
1100 var result =
1101 edgeA.hasStringName === edgeB.hasStringName ?
1102 (edgeA.name < edgeB.name ? -1 : (edgeA.name > edgeB.name ? 1 : 0)) :
1103 (edgeA.hasStringName ? -1 : 1);
1104 return ascending ? result : -result;
1105 }
1106
1107 function sortByNodeField(fieldName, ascending, indexA, indexB)
1108 {
1109 edgeA.edgeIndex = indexA;
1110 edgeB.edgeIndex = indexB;
1111 nodeA.nodeIndex = edgeA.nodeIndex;
1112 nodeB.nodeIndex = edgeB.nodeIndex;
1113 var valueA = nodeA[fieldName];
1114 var valueB = nodeB[fieldName];
1115 var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
1116 return ascending ? result : -result;
1117 }
1118
1119 if (!this._iterationOrder)
1120 this._createIterationOrder();
1121
1122 function sortByEdgeAndNode(indexA, indexB) {
1123 var result = sortByEdgeFieldName(ascending1, indexA, indexB);
1124 if (result === 0)
1125 result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
1126 return result;
1127 }
1128
1129 function sortByNodeAndEdge(indexA, indexB) {
1130 var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
1131 if (result === 0)
1132 result = sortByEdgeFieldName(ascending2, indexA, indexB);
1133 return result;
1134 }
1135
1136 function sortByNodeAndNode(indexA, indexB) {
1137 var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
1138 if (result === 0)
1139 result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
1140 return result;
1141 }
1142
1143 if (fieldName1 === "!edgeName")
1144 this._iterationOrder.sort(sortByEdgeAndNode);
1145 else if (fieldName2 === "!edgeName")
1146 this._iterationOrder.sort(sortByNodeAndEdge);
1147 else
1148 this._iterationOrder.sort(sortByNodeAndNode);
1149 return true;
1150 }
1151 };
1152
1153 WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSn apshotFilteredOrderedIterator.prototype;
1154
1155 WebInspector.HeapSnapshotNodesProvider = function(snapshot, filter, className)
1156 {
1157 this.snapshot = snapshot;
1158 if (!className)
1159 WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, filter);
1160 else
1161 WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, null, snapshot.aggregates(false)[className].idxs);
1162 }
1163
1164 WebInspector.HeapSnapshotNodesProvider.prototype = {
1165 _serialize: function(node)
1166 {
1167 return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: n ode.retainedSize, selfSize: node.selfSize, type: node.type};
1168 },
1169
1170 sort: function(comparator)
1171 {
1172 if (this._lastComparator === comparator)
1173 return false;
1174 this._lastComparator = comparator;
1175 var fieldName1 = comparator.fieldName1;
1176 var fieldName2 = comparator.fieldName2;
1177 var ascending1 = comparator.ascending1;
1178 var ascending2 = comparator.ascending2;
1179
1180 var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
1181 var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
1182
1183 function sortByNodeField(fieldName, ascending, indexA, indexB)
1184 {
1185 nodeA.nodeIndex = indexA;
1186 nodeB.nodeIndex = indexB;
1187 var valueA = nodeA[fieldName];
1188 var valueB = nodeB[fieldName];
1189 var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
1190 return ascending ? result : -result;
1191 }
1192
1193 if (!this._iterationOrder)
1194 this._createIterationOrder();
1195
1196 function sortByComparator(indexA, indexB) {
1197 var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
1198 if (result === 0)
1199 result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
1200 return result;
1201 }
1202
1203 this._iterationOrder.sort(sortByComparator);
1204 return true;
1205 }
1206 };
1207
1208 WebInspector.HeapSnapshotNodesProvider.prototype.__proto__ = WebInspector.HeapSn apshotFilteredOrderedIterator.prototype;
1209
1210 WebInspector.HeapSnapshotPathFinder = function(snapshot, targetNodeIndex, skipHi dden)
1211 {
1212 this._snapshot = snapshot;
1213 this._maxLength = 1;
1214 this._lengthLimit = 15;
1215 this._targetNodeIndex = targetNodeIndex;
1216 this._currentPath = null;
1217 this._skipHidden = skipHidden;
1218 this._rootChildren = this._fillRootChildren();
1219 }
1220
1221 WebInspector.HeapSnapshotPathFinder.prototype = {
1222 findNext: function()
1223 {
1224 for (var i = 0; i < 100000; ++i) {
1225 if (!this._buildNextPath()) {
1226 if (++this._maxLength >= this._lengthLimit)
1227 return null;
1228 this._currentPath = null;
1229 if (!this._buildNextPath())
1230 return null;
1231 }
1232 if (this._isPathFound())
1233 return {path:this._pathToString(this._currentPath), route:this._pathToRoute(this ._currentPath), len:this._currentPath.length};
1234 }
1235
1236 return false;
1237 },
1238
1239 updateRoots: function(filter)
1240 {
1241 if (filter)
1242 filter = eval("(function(){return " + filter + "})()");
1243 this._rootChildren = this._fillRootChildren(filter);
1244 this._reset();
1245 },
1246
1247 _reset: function()
1248 {
1249 this._maxLength = 1;
1250 this._currentPath = null;
1251 },
1252
1253 _fillRootChildren: function(filter)
1254 {
1255 var result = [];
1256 for (var iter = this._snapshot.rootNode.edges; iter.hasNext(); iter.next()) {
1257 if (!filter || filter(iter.edge.node))
1258 result[iter.edge.nodeIndex] = true;
1259 }
1260 return result;
1261 },
1262
1263 _appendToCurrentPath: function(iter)
1264 {
1265 this._currentPath._cache[this._lastEdge.nodeIndex] = true;
1266 this._currentPath.push(iter);
1267 },
1268
1269 _removeLastFromCurrentPath: function()
1270 {
1271 this._currentPath.pop();
1272 delete this._currentPath._cache[this._lastEdge.nodeIndex];
1273 },
1274
1275 _hasInPath: function(nodeIndex)
1276 {
1277 return this._targetNodeIndex === nodeIndex
1278 || !!this._currentPath._cache[nodeIndex];
1279 },
1280
1281 _isPathFound: function()
1282 {
1283 return this._currentPath.length === this._maxLength
1284 && this._lastEdge.nodeIndex in this._rootChildren;
1285 },
1286
1287 get _lastEdgeIter()
1288 {
1289 return this._currentPath[this._currentPath.length - 1];
1290 },
1291
1292 get _lastEdge()
1293 {
1294 return this._lastEdgeIter.item;
1295 },
1296
1297 _skipEdge: function(edge)
1298 {
1299 return edge.isInvisible
1300 || (this._skipHidden && (edge.isHidden || edge.node.isHidden))
1301 || this._hasInPath(edge.nodeIndex);
1302 },
1303
1304 _nextEdgeIter: function()
1305 {
1306 var iter = this._lastEdgeIter;
1307 while (iter.hasNext() && this._skipEdge(iter.item))
1308 iter.next();
1309 return iter;
1310 },
1311
1312 _buildNextPath: function()
1313 {
1314 if (this._currentPath !== null) {
1315 var iter = this._lastEdgeIter;
1316 while (true) {
1317 iter.next();
1318 iter = this._nextEdgeIter();
1319 if (iter.hasNext())
1320 return true;
1321 while (true) {
1322 if (this._currentPath.length > 1) {
1323 this._removeLastFromCurrentPath();
1324 iter = this._lastEdgeIter;
1325 iter.next();
1326 iter = this._nextEdgeIter();
1327 if (iter.hasNext()) {
1328 while (this._currentPath.length < this._maxLength) {
1329 iter = this._nextEdgeIter();
1330 if (iter.hasNext())
1331 this._appendToCurrentPath(iter.item.node.retainers);
1332 else
1333 return true;
1334 }
1335 return true;
1336 }
1337 } else
1338 return false;
1339 }
1340 }
1341 } else {
1342 var node = new WebInspector.HeapSnapshotNode(this._snapshot, this._targetNodeInd ex);
1343 this._currentPath = [node.retainers];
1344 this._currentPath._cache = {};
1345 while (this._currentPath.length < this._maxLength) {
1346 var iter = this._nextEdgeIter();
1347 if (iter.hasNext())
1348 this._appendToCurrentPath(iter.item.node.retainers);
1349 else
1350 break;
1351 }
1352 return true;
1353 }
1354 },
1355
1356 _nodeToString: function(node)
1357 {
1358 if (node.id === 1)
1359 return node.name;
1360 else
1361 return node.name + "@" + node.id;
1362 },
1363
1364 _pathToString: function(path)
1365 {
1366 if (!path)
1367 return "";
1368 var sPath = [];
1369 for (var j = 0; j < path.length; ++j)
1370 sPath.push(path[j].item.toString());
1371 sPath.push(this._nodeToString(path[path.length - 1].item.node));
1372 sPath.reverse();
1373 return sPath.join("");
1374 },
1375
1376 _pathToRoute: function(path)
1377 {
1378 if (!path)
1379 return [];
1380 var route = [];
1381 route.push(this._targetNodeIndex);
1382 for (var i = 0; i < path.length; ++i)
1383 route.push(path[i].item.nodeIndex);
1384 route.reverse();
1385 return route;
1386 }
1387 };
1388
1389 WebInspector.HeapSnapshotsDiff = function(snapshot, className)
1390 {
1391 this._snapshot = snapshot;
1392 this._className = className;
1393 };
1394
1395 WebInspector.HeapSnapshotsDiff.prototype = {
1396 calculate: function()
1397 {
1398 var aggregates = this._snapshot.aggregates(true)[this._className];
1399 var indexes = aggregates ? aggregates.idxs : [];
1400 var i = 0, l = this._baseIds.length;
1401 var j = 0, m = indexes.length;
1402 var diff = { addedCount: 0, removedCount: 0, addedSize: 0, removedSize: 0 };
1403
1404 var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot, indexes[j]);
1405 while (i < l && j < m) {
1406 var nodeAId = this._baseIds[i];
1407 if (nodeAId < nodeB.id) {
1408 diff.removedCount++;
1409 diff.removedSize += this._baseSelfSizes[i];
1410 ++i;
1411 } else if (nodeAId > nodeB.id) {
1412 diff.addedCount++;
1413 diff.addedSize += nodeB.selfSize;
1414 nodeB.nodeIndex = indexes[++j];
1415 } else {
1416 ++i;
1417 nodeB.nodeIndex = indexes[++j];
1418 }
1419 }
1420 while (i < l) {
1421 diff.removedCount++;
1422 diff.removedSize += this._baseSelfSizes[i];
1423 ++i;
1424 }
1425 while (j < m) {
1426 diff.addedCount++;
1427 diff.addedSize += nodeB.selfSize;
1428 nodeB.nodeIndex = indexes[++j];
1429 }
1430 diff.countDelta = diff.addedCount - diff.removedCount;
1431 diff.sizeDelta = diff.addedSize - diff.removedSize;
1432 return diff;
1433 },
1434
1435 pushBaseIds: function(baseIds)
1436 {
1437 this._baseIds = baseIds;
1438 },
1439
1440 pushBaseSelfSizes: function(baseSelfSizes)
1441 {
1442 this._baseSelfSizes = baseSelfSizes;
1443 }
1444 };
1445 ;
1446
1447
1448 WebInspector.HeapSnapshotWorkerDispatcher = function(globalObject, postMessage)
1449 {
1450 this._objects = [];
1451 this._global = globalObject;
1452 this._postMessage = postMessage;
1453 }
1454
1455 WebInspector.HeapSnapshotWorkerDispatcher.prototype = {
1456 _findFunction: function(name)
1457 {
1458 var path = name.split(".");
1459 var result = this._global;
1460 for (var i = 0; i < path.length; ++i)
1461 result = result[path[i]];
1462 return result;
1463 },
1464
1465 dispatchMessage: function(event)
1466 {
1467 var data = event.data;
1468 switch (data.disposition) {
1469 case "create": {
1470 var constructorFunction = this._findFunction(data.methodName);
1471 this._objects[data.objectId] = new constructorFunction();
1472 this._postMessage({callId: data.callId});
1473 break;
1474 }
1475 case "dispose": {
1476 delete this._objects[data.objectId];
1477 this._postMessage({callId: data.callId});
1478 break;
1479 }
1480 case "getter": {
1481 var object = this._objects[data.objectId];
1482 var result = object[data.methodName];
1483 this._postMessage({callId: data.callId, result: result});
1484 break;
1485 }
1486 case "factory": {
1487 var object = this._objects[data.objectId];
1488 var result = object[data.methodName].apply(object, data.methodArguments);
1489 if (result)
1490 this._objects[data.newObjectId] = result;
1491 this._postMessage({callId: data.callId, result: !!result});
1492 break;
1493 }
1494 case "method": {
1495 var object = this._objects[data.objectId];
1496 var result = object[data.methodName].apply(object, data.methodArguments);
1497 this._postMessage({callId: data.callId, result: result});
1498 break;
1499 }
1500 }
1501 }
1502 };
1503 ;
1504
1505 function postMessageWrapper(message)
1506 {
1507 postMessage(message);
1508 }
1509
1510 var dispatcher = new WebInspector.HeapSnapshotWorkerDispatcher(this, postMessage Wrapper);
1511 addEventListener("message", dispatcher.dispatchMessage.bind(dispatcher), false);
OLDNEW
« no previous file with comments | « chrome_linux/resources.pak ('k') | chrome_linux/resources/inspector/Images/applicationCache.png » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698