blob: 3c83aee1fe71cc5cec1ad4ee5ed9eea06582e478 [file] [log] [blame]
Chris Craik93216d02015-03-05 13:58:42 -08001<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/base/extension_registry.html">
9<link rel="import" href="/core/trace_model/event.html">
10<link rel="import" href="/core/trace_model/object_snapshot.html">
11<link rel="import" href="/base/range.html">
12<link rel="import" href="/base/sorted_array_utils.html">
13
14<script>
15'use strict';
16
17/**
18 * @fileoverview Provides the ObjectSnapshot and ObjectHistory classes.
19 */
20tv.exportTo('tv.c.trace_model', function() {
21 var ObjectSnapshot = tv.c.trace_model.ObjectSnapshot;
22
23 /**
24 * An object with a specific id, whose state has been snapshotted several
25 * times.
26 *
27 * @constructor
28 */
29 function ObjectInstance(
30 parent, id, category, name, creationTs, opt_baseTypeName) {
31 tv.c.trace_model.Event.call(this);
32 this.parent = parent;
33 this.id = id;
34 this.category = category;
35 this.baseTypeName = opt_baseTypeName ? opt_baseTypeName : name;
36 this.name = name;
37 this.creationTs = creationTs;
38 this.creationTsWasExplicit = false;
39 this.deletionTs = Number.MAX_VALUE;
40 this.deletionTsWasExplicit = false;
41 this.colorId = 0;
42 this.bounds = new tv.b.Range();
43 this.snapshots = [];
44 this.hasImplicitSnapshots = false;
45 }
46
47 ObjectInstance.prototype = {
48 __proto__: tv.c.trace_model.Event.prototype,
49
50 get typeName() {
51 return this.name;
52 },
53
54 addBoundsToRange: function(range) {
55 range.addRange(this.bounds);
56 },
57
58 addSnapshot: function(ts, args, opt_name, opt_baseTypeName) {
59 if (ts < this.creationTs)
60 throw new Error('Snapshots must be >= instance.creationTs');
61 if (ts >= this.deletionTs)
62 throw new Error('Snapshots cannot be added after ' +
63 'an objects deletion timestamp.');
64
65 var lastSnapshot;
66 if (this.snapshots.length > 0) {
67 lastSnapshot = this.snapshots[this.snapshots.length - 1];
68 if (lastSnapshot.ts == ts)
69 throw new Error('Snapshots already exists at this time!');
70 if (ts < lastSnapshot.ts) {
71 throw new Error(
72 'Snapshots must be added in increasing timestamp order');
73 }
74 }
75
76 // Update baseTypeName if needed.
77 if (opt_name &&
78 (this.name != opt_name)) {
79 if (!opt_baseTypeName)
80 throw new Error('Must provide base type name for name update');
81 if (this.baseTypeName != opt_baseTypeName)
82 throw new Error('Cannot update type name: base types dont match');
83 this.name = opt_name;
84 }
85
86 var snapshotConstructor =
87 tv.c.trace_model.ObjectSnapshot.getConstructor(
88 this.category, this.name);
89 var snapshot = new snapshotConstructor(this, ts, args);
90 this.snapshots.push(snapshot);
91 return snapshot;
92 },
93
94 wasDeleted: function(ts) {
95 var lastSnapshot;
96 if (this.snapshots.length > 0) {
97 lastSnapshot = this.snapshots[this.snapshots.length - 1];
98 if (lastSnapshot.ts > ts)
99 throw new Error(
100 'Instance cannot be deleted at ts=' +
101 ts + '. A snapshot exists that is older.');
102 }
103 this.deletionTs = ts;
104 this.deletionTsWasExplicit = true;
105 },
106
107 /**
108 * See ObjectSnapshot constructor notes on object initialization.
109 */
110 preInitialize: function() {
111 for (var i = 0; i < this.snapshots.length; i++)
112 this.snapshots[i].preInitialize();
113 },
114
115 /**
116 * See ObjectSnapshot constructor notes on object initialization.
117 */
118 initialize: function() {
119 for (var i = 0; i < this.snapshots.length; i++)
120 this.snapshots[i].initialize();
121 },
122
123 getSnapshotAt: function(ts) {
124 if (ts < this.creationTs) {
125 if (this.creationTsWasExplicit)
126 throw new Error('ts must be within lifetime of this instance');
127 return this.snapshots[0];
128 }
129 if (ts > this.deletionTs)
130 throw new Error('ts must be within lifetime of this instance');
131
132 var snapshots = this.snapshots;
133 var i = tv.b.findLowIndexInSortedIntervals(
134 snapshots,
135 function(snapshot) { return snapshot.ts; },
136 function(snapshot, i) {
137 if (i == snapshots.length - 1)
138 return snapshots[i].objectInstance.deletionTs;
139 return snapshots[i + 1].ts - snapshots[i].ts;
140 },
141 ts);
142 if (i < 0) {
143 // Note, this is a little bit sketchy: this lets early ts point at the
144 // first snapshot, even before it is taken. We do this because raster
145 // tasks usually post before their tile snapshots are dumped. This may
146 // be a good line of code to re-visit if we start seeing strange and
147 // confusing object references showing up in the traces.
148 return this.snapshots[0];
149 }
150 if (i >= this.snapshots.length)
151 return this.snapshots[this.snapshots.length - 1];
152 return this.snapshots[i];
153 },
154
155 updateBounds: function() {
156 this.bounds.reset();
157 this.bounds.addValue(this.creationTs);
158 if (this.deletionTs != Number.MAX_VALUE)
159 this.bounds.addValue(this.deletionTs);
160 else if (this.snapshots.length > 0)
161 this.bounds.addValue(this.snapshots[this.snapshots.length - 1].ts);
162 },
163
164 shiftTimestampsForward: function(amount) {
165 this.creationTs += amount;
166 if (this.deletionTs != Number.MAX_VALUE)
167 this.deletionTs += amount;
168 this.snapshots.forEach(function(snapshot) {
169 snapshot.ts += amount;
170 });
171 }
172 };
173
174 tv.c.trace_model.EventRegistry.register(
175 ObjectInstance,
176 {
177 name: 'objectInstance',
178 pluralName: 'objectInstances',
179 singleViewElementName: 'tv-c-single-object-instance-sub-view',
180 multiViewElementName: 'tv-c-multi-object-sub-view'
181 });
182
183 var options = new tv.b.ExtensionRegistryOptions(
184 tv.b.TYPE_BASED_REGISTRY_MODE);
185 options.mandatoryBaseClass = ObjectInstance;
186 options.defaultConstructor = ObjectInstance;
187 tv.b.decorateExtensionRegistry(ObjectInstance, options);
188
189 return {
190 ObjectInstance: ObjectInstance
191 };
192});
193</script>