Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / trace_model / time_to_object_instance_map.js
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
7 /**
8  * @fileoverview Provides the TimeToObjectInstanceMap class.
9  */
10 tvcm.require('tvcm.range');
11 tvcm.require('tvcm.sorted_array_utils');
12
13 tvcm.exportTo('tracing.trace_model', function() {
14
15   /**
16    * Tracks all the instances associated with a given ID over its lifetime.
17    *
18    * An id can be used multiple times throughout a trace, referring to different
19    * objects at different times. This data structure does the bookkeeping to
20    * figure out what ObjectInstance is referred to at a given timestamp.
21    *
22    * @constructor
23    */
24   function TimeToObjectInstanceMap(createObjectInstanceFunction, parent, id) {
25     this.createObjectInstanceFunction_ = createObjectInstanceFunction;
26     this.parent = parent;
27     this.id = id;
28     this.instances = [];
29   }
30
31   TimeToObjectInstanceMap.prototype = {
32     idWasCreated: function(category, name, ts) {
33       if (this.instances.length == 0) {
34         this.instances.push(this.createObjectInstanceFunction_(
35             this.parent, this.id, category, name, ts));
36         this.instances[0].creationTsWasExplicit = true;
37         return this.instances[0];
38       }
39
40       var lastInstance = this.instances[this.instances.length - 1];
41       if (ts < lastInstance.deletionTs) {
42         throw new Error('Mutation of the TimeToObjectInstanceMap must be ' +
43                         'done in ascending timestamp order.');
44       }
45       lastInstance = this.createObjectInstanceFunction_(
46           this.parent, this.id, category, name, ts);
47       lastInstance.creationTsWasExplicit = true;
48       this.instances.push(lastInstance);
49       return lastInstance;
50     },
51
52     addSnapshot: function(category, name, ts, args, opt_baseTypeName) {
53       if (this.instances.length == 0) {
54         this.instances.push(this.createObjectInstanceFunction_(
55             this.parent, this.id, category, name, ts, opt_baseTypeName));
56       }
57
58       var i = tvcm.findLowIndexInSortedIntervals(
59           this.instances,
60           function(inst) { return inst.creationTs; },
61           function(inst) { return inst.deletionTs - inst.creationTs; },
62           ts);
63
64       var instance;
65       if (i < 0) {
66         instance = this.instances[0];
67         if (ts > instance.deletionTs ||
68             instance.creationTsWasExplicit) {
69           throw new Error(
70               'At the provided timestamp, no instance was still alive');
71         }
72
73         if (instance.snapshots.length != 0) {
74           throw new Error(
75               'Cannot shift creationTs forward, ' +
76               'snapshots have been added. First snap was at ts=' +
77               instance.snapshots[0].ts + ' and creationTs was ' +
78               instance.creationTs);
79         }
80         instance.creationTs = ts;
81       } else if (i >= this.instances.length) {
82         instance = this.instances[this.instances.length - 1];
83         if (ts >= instance.deletionTs) {
84           // The snap is added after our oldest and deleted instance. This means
85           // that this is a new implicit instance.
86           instance = this.createObjectInstanceFunction_(
87               this.parent, this.id, category, name, ts, opt_baseTypeName);
88           this.instances.push(instance);
89         } else {
90           // If the ts is before the last objects deletion time, then the caller
91           // is trying to add a snapshot when there may have been an instance
92           // alive. In that case, try to move an instance's creationTs to
93           // include this ts, provided that it has an implicit creationTs.
94
95           // Search backward from the right for an instance that was definitely
96           // deleted before this ts. Any time an instance is found that has a
97           // moveable creationTs
98           var lastValidIndex;
99           for (var i = this.instances.length - 1; i >= 0; i--) {
100             var tmp = this.instances[i];
101             if (ts >= tmp.deletionTs)
102               break;
103             if (tmp.creationTsWasExplicit == false && tmp.snapshots.length == 0)
104               lastValidIndex = i;
105           }
106           if (lastValidIndex === undefined) {
107             throw new Error(
108                 'Cannot add snapshot. No instance was alive that was mutable.');
109           }
110           instance = this.instances[lastValidIndex];
111           instance.creationTs = ts;
112         }
113       } else {
114         instance = this.instances[i];
115       }
116
117       return instance.addSnapshot(ts, args, name, opt_baseTypeName);
118     },
119
120     get lastInstance() {
121       if (this.instances.length == 0)
122         return undefined;
123       return this.instances[this.instances.length - 1];
124     },
125
126     idWasDeleted: function(category, name, ts) {
127       if (this.instances.length == 0) {
128         this.instances.push(this.createObjectInstanceFunction_(
129             this.parent, this.id, category, name, ts));
130       }
131       var lastInstance = this.instances[this.instances.length - 1];
132       if (ts < lastInstance.creationTs)
133         throw new Error('Cannot delete a id before it was crated');
134       if (lastInstance.deletionTs == Number.MAX_VALUE) {
135         lastInstance.wasDeleted(ts);
136         return lastInstance;
137       }
138
139       if (ts < lastInstance.deletionTs)
140         throw new Error('id was already deleted earlier.');
141
142       // A new instance was deleted with no snapshots in-between.
143       // Create an instance then kill it.
144       lastInstance = this.createObjectInstanceFunction_(
145           this.parent, this.id, category, name, ts);
146       this.instances.push(lastInstance);
147       lastInstance.wasDeleted(ts);
148       return lastInstance;
149     },
150
151     getInstanceAt: function(ts) {
152       var i = tvcm.findLowIndexInSortedIntervals(
153           this.instances,
154           function(inst) { return inst.creationTs; },
155           function(inst) { return inst.deletionTs - inst.creationTs; },
156           ts);
157       if (i < 0) {
158         if (this.instances[0].creationTsWasExplicit)
159           return undefined;
160         return this.instances[0];
161       } else if (i >= this.instances.length) {
162         return undefined;
163       }
164       return this.instances[i];
165     },
166
167     logToConsole: function() {
168       for (var i = 0; i < this.instances.length; i++) {
169         var instance = this.instances[i];
170         var cEF = '';
171         var dEF = '';
172         if (instance.creationTsWasExplicit)
173           cEF = '(explicitC)';
174         if (instance.deletionTsWasExplicit)
175           dEF = '(explicit)';
176         console.log(instance.creationTs, cEF,
177                     instance.deletionTs, dEF,
178                     instance.category,
179                     instance.name,
180                     instance.snapshots.length + ' snapshots');
181       }
182     }
183   };
184
185   return {
186     TimeToObjectInstanceMap: TimeToObjectInstanceMap
187   };
188 });