1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/bard/story.h"
16 :
17 : #include "syzygy/bard/events/heap_alloc_event.h"
18 : #include "syzygy/bard/events/heap_create_event.h"
19 : #include "syzygy/bard/events/heap_destroy_event.h"
20 : #include "syzygy/bard/events/heap_free_event.h"
21 : #include "syzygy/bard/events/heap_realloc_event.h"
22 : #include "syzygy/bard/events/heap_set_information_event.h"
23 : #include "syzygy/bard/events/heap_size_event.h"
24 : #include "syzygy/bard/events/linked_event.h"
25 :
26 : namespace bard {
27 :
28 : namespace {
29 :
30 : using events::LinkedEvent;
31 :
32 : } // namespace
33 :
34 E : Story::PlotLine* Story::AddPlotLine(scoped_ptr<PlotLine> plot_line) {
35 E : PlotLine* pl = plot_line.get();
36 E : plot_lines_.push_back(plot_line.Pass());
37 E : return pl;
38 E : }
39 :
40 E : Story::PlotLine* Story::CreatePlotLine() {
41 E : PlotLine* plot_line = new PlotLine();
42 E : plot_lines_.push_back(plot_line);
43 E : return plot_line;
44 E : }
45 :
46 E : bool Story::Save(core::OutArchive* out_archive) const {
47 E : std::map<const LinkedEvent*, size_t> linked_event_ids;
48 :
49 : // Serialize the number of plot lines.
50 E : out_archive->Save(plot_lines_.size());
51 :
52 : // Save each plot line.
53 E : for (PlotLine* plot_line : plot_lines_) {
54 E : if (!out_archive->Save(plot_line->size())) {
55 i : return false;
56 : }
57 :
58 E : for (const EventInterface* event : *plot_line) {
59 E : if (!EventInterface::Save(event, out_archive))
60 i : return false;
61 :
62 : // Assign an integer ID to linked events so that the connections
63 : // between them can be expressed.
64 E : if (event->type() == EventInterface::kLinkedEvent) {
65 : const LinkedEvent* linked_event =
66 E : reinterpret_cast<const LinkedEvent*>(event);
67 : linked_event_ids.insert(
68 E : std::make_pair(linked_event, linked_event_ids.size()));
69 : }
70 : }
71 E : }
72 :
73 : // Serialize the linked event connections.
74 E : for (auto event_id_pair : linked_event_ids) {
75 E : const LinkedEvent* linked_event = event_id_pair.first;
76 :
77 : // Save the ID of this event and the number of input dependencies.
78 E : if (!out_archive->Save(event_id_pair.second))
79 i : return false;
80 E : if (!out_archive->Save(linked_event->deps().size()))
81 i : return false;
82 :
83 : // Save the ID of each input dependency.
84 E : for (auto dep : linked_event->deps()) {
85 E : auto it = linked_event_ids.find(dep);
86 E : DCHECK(it != linked_event_ids.end());
87 E : if (!out_archive->Save(it->second))
88 i : return false;
89 : }
90 E : }
91 :
92 E : return true;
93 E : }
94 :
95 E : bool Story::Load(core::InArchive* in_archive) {
96 E : std::vector<LinkedEvent*> linked_events_by_id;
97 :
98 E : size_t plot_line_count = 0;
99 E : if (!in_archive->Load(&plot_line_count))
100 i : return false;
101 :
102 : // Read the plot lines.
103 E : for (size_t i = 0; i < plot_line_count; ++i) {
104 E : scoped_ptr<PlotLine> plot_line(new PlotLine());
105 :
106 : // Read the events.
107 E : size_t event_count = 0;
108 E : if (!in_archive->Load(&event_count))
109 i : return false;
110 E : for (size_t j = 0; j < event_count; ++j) {
111 E : scoped_ptr<EventInterface> event = EventInterface::Load(in_archive);
112 E : if (!event.get())
113 i : return false;
114 :
115 E : if (event->type() == EventInterface::kLinkedEvent) {
116 E : LinkedEvent* linked_event = reinterpret_cast<LinkedEvent*>(event.get());
117 E : linked_events_by_id.push_back(linked_event);
118 : }
119 :
120 E : plot_line->push_back(event.Pass());
121 E : }
122 :
123 E : plot_lines_.push_back(plot_line.Pass());
124 E : }
125 :
126 : // Deserialize event dependencies.
127 E : for (size_t i = 0; i < linked_events_by_id.size(); ++i) {
128 E : size_t event_id = 0;
129 E : if (!in_archive->Load(&event_id))
130 i : return false;
131 E : DCHECK_GT(linked_events_by_id.size(), event_id);
132 E : LinkedEvent* event = linked_events_by_id[event_id];
133 :
134 E : size_t dep_count = 0;
135 E : if (!in_archive->Load(&dep_count))
136 i : return false;
137 :
138 : // Deserialize the dependencies and emit them.
139 E : for (size_t j = 0; j < dep_count; ++j) {
140 E : size_t dep_id = 0;
141 E : if (!in_archive->Load(&dep_id))
142 i : return false;
143 E : DCHECK_GT(linked_events_by_id.size(), dep_id);
144 E : LinkedEvent* dep = linked_events_by_id[dep_id];
145 E : event->AddDep(dep);
146 E : }
147 E : }
148 :
149 E : return true;
150 E : }
151 :
152 : } // namespace bard
|