3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
7 <link rel="import" href="/base/range.html">
8 <link rel="import" href="/base/sorted_array_utils.html">
14 * @fileoverview Provides the TimeToObjectInstanceMap class.
16 tv.exportTo('tracing.trace_model', function() {
18 * Tracks all the instances associated with a given ID over its lifetime.
20 * An id can be used multiple times throughout a trace, referring to different
21 * objects at different times. This data structure does the bookkeeping to
22 * figure out what ObjectInstance is referred to at a given timestamp.
26 function TimeToObjectInstanceMap(createObjectInstanceFunction, parent, id) {
27 this.createObjectInstanceFunction_ = createObjectInstanceFunction;
33 TimeToObjectInstanceMap.prototype = {
34 idWasCreated: function(category, name, ts) {
35 if (this.instances.length == 0) {
36 this.instances.push(this.createObjectInstanceFunction_(
37 this.parent, this.id, category, name, ts));
38 this.instances[0].creationTsWasExplicit = true;
39 return this.instances[0];
42 var lastInstance = this.instances[this.instances.length - 1];
43 if (ts < lastInstance.deletionTs) {
44 throw new Error('Mutation of the TimeToObjectInstanceMap must be ' +
45 'done in ascending timestamp order.');
47 lastInstance = this.createObjectInstanceFunction_(
48 this.parent, this.id, category, name, ts);
49 lastInstance.creationTsWasExplicit = true;
50 this.instances.push(lastInstance);
54 addSnapshot: function(category, name, ts, args, opt_baseTypeName) {
55 if (this.instances.length == 0) {
56 this.instances.push(this.createObjectInstanceFunction_(
57 this.parent, this.id, category, name, ts, opt_baseTypeName));
60 var i = tv.findLowIndexInSortedIntervals(
62 function(inst) { return inst.creationTs; },
63 function(inst) { return inst.deletionTs - inst.creationTs; },
68 instance = this.instances[0];
69 if (ts > instance.deletionTs ||
70 instance.creationTsWasExplicit) {
72 'At the provided timestamp, no instance was still alive');
75 if (instance.snapshots.length != 0) {
77 'Cannot shift creationTs forward, ' +
78 'snapshots have been added. First snap was at ts=' +
79 instance.snapshots[0].ts + ' and creationTs was ' +
82 instance.creationTs = ts;
83 } else if (i >= this.instances.length) {
84 instance = this.instances[this.instances.length - 1];
85 if (ts >= instance.deletionTs) {
86 // The snap is added after our oldest and deleted instance. This means
87 // that this is a new implicit instance.
88 instance = this.createObjectInstanceFunction_(
89 this.parent, this.id, category, name, ts, opt_baseTypeName);
90 this.instances.push(instance);
92 // If the ts is before the last objects deletion time, then the caller
93 // is trying to add a snapshot when there may have been an instance
94 // alive. In that case, try to move an instance's creationTs to
95 // include this ts, provided that it has an implicit creationTs.
97 // Search backward from the right for an instance that was definitely
98 // deleted before this ts. Any time an instance is found that has a
99 // moveable creationTs
101 for (var i = this.instances.length - 1; i >= 0; i--) {
102 var tmp = this.instances[i];
103 if (ts >= tmp.deletionTs)
105 if (tmp.creationTsWasExplicit == false && tmp.snapshots.length == 0)
108 if (lastValidIndex === undefined) {
110 'Cannot add snapshot. No instance was alive that was mutable.');
112 instance = this.instances[lastValidIndex];
113 instance.creationTs = ts;
116 instance = this.instances[i];
119 return instance.addSnapshot(ts, args, name, opt_baseTypeName);
123 if (this.instances.length == 0)
125 return this.instances[this.instances.length - 1];
128 idWasDeleted: function(category, name, ts) {
129 if (this.instances.length == 0) {
130 this.instances.push(this.createObjectInstanceFunction_(
131 this.parent, this.id, category, name, ts));
133 var lastInstance = this.instances[this.instances.length - 1];
134 if (ts < lastInstance.creationTs)
135 throw new Error('Cannot delete a id before it was crated');
136 if (lastInstance.deletionTs == Number.MAX_VALUE) {
137 lastInstance.wasDeleted(ts);
141 if (ts < lastInstance.deletionTs)
142 throw new Error('id was already deleted earlier.');
144 // A new instance was deleted with no snapshots in-between.
145 // Create an instance then kill it.
146 lastInstance = this.createObjectInstanceFunction_(
147 this.parent, this.id, category, name, ts);
148 this.instances.push(lastInstance);
149 lastInstance.wasDeleted(ts);
153 getInstanceAt: function(ts) {
154 var i = tv.findLowIndexInSortedIntervals(
156 function(inst) { return inst.creationTs; },
157 function(inst) { return inst.deletionTs - inst.creationTs; },
160 if (this.instances[0].creationTsWasExplicit)
162 return this.instances[0];
163 } else if (i >= this.instances.length) {
166 return this.instances[i];
169 logToConsole: function() {
170 for (var i = 0; i < this.instances.length; i++) {
171 var instance = this.instances[i];
174 if (instance.creationTsWasExplicit)
176 if (instance.deletionTsWasExplicit)
178 console.log(instance.creationTs, cEF,
179 instance.deletionTs, dEF,
182 instance.snapshots.length + ' snapshots');
188 TimeToObjectInstanceMap: TimeToObjectInstanceMap