1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5'use strict';
6
7base.require('tracing.trace_model.object_instance');
8base.require('cc.util');
9
10base.exportTo('tcmalloc', function() {
11  var ObjectSnapshot = tracing.trace_model.ObjectSnapshot;
12
13  /**
14   * @constructor
15   */
16  function HeapSnapshot() {
17    ObjectSnapshot.apply(this, arguments);
18  }
19
20  HeapSnapshot.prototype = {
21    __proto__: ObjectSnapshot.prototype,
22
23    preInitialize: function() {
24      cc.preInitializeObject(this);
25
26      // TODO(jamescook): Any generic field setup can go here.
27    },
28
29    // TODO(jamescook): This seems to be called before the green dot is clicked.
30    // Consider doing it in heap_view.js.
31    initialize: function() {
32      if (this.args.length == 0)
33        throw new Error('No heap snapshot data.');
34
35      // The first entry is total allocations across all stack traces.
36      this.total_ = this.args[0];
37      // The rest is a list of allocations.
38      var allocs = this.args.slice(1);
39
40      // Build a nested dictionary of trace event names.
41      this.heap_ = {
42        children: {},
43        currentBytes: 0,
44        currentAllocs: 0,
45        totalBytes: 0,
46        totalAllocs: 0
47      };
48      for (var i = 0; i < allocs.length; i++) {
49        var alloc = allocs[i];
50        var traceNames = alloc.trace.split(' ');
51        // We don't want to record allocations caused by the heap profiling
52        // system itself, so skip allocations with this special name.
53        if (traceNames.indexOf('trace-memory-ignore') != -1)
54          continue;
55        var heapEntry = this.heap_;
56        // Walk down into the heap of stack traces.
57        for (var j = 0; j < traceNames.length; j++) {
58          // Look for existing children with this trace.
59          var traceName = traceNames[j];
60          // The empty trace name means "(here)", so don't roll those up into
61          // parent traces because they have already been counted.
62          if (traceName.length != 0) {
63            // Add up the total memory for intermediate entries, so the top of
64            // each subtree is the total memory for that tree.
65            heapEntry.currentBytes += alloc.currentBytes;
66            heapEntry.currentAllocs += alloc.currentAllocs;
67            heapEntry.totalBytes += alloc.totalBytes;
68            heapEntry.totalAllocs += alloc.totalAllocs;
69          }
70          if (!heapEntry.children[traceName]) {
71            // New trace entry at this depth, so create a child for it.
72            heapEntry.children[traceName] = {
73              children: {},
74              currentBytes: alloc.currentBytes,
75              currentAllocs: alloc.currentAllocs,
76              totalBytes: alloc.totalBytes,
77              totalAllocs: alloc.totalAllocs
78            };
79          }
80          // Descend into the children.
81          heapEntry = heapEntry.children[traceName];
82        }
83      }
84    }
85
86  };
87
88  ObjectSnapshot.register('memory::Heap', HeapSnapshot);
89
90  return {
91    HeapSnapshot: HeapSnapshot
92  };
93});
94