1 /*
2  * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 package com.sun.hotspot.igv.data.serialization;
25 
26 import com.sun.hotspot.igv.data.GraphDocument;
27 import com.sun.hotspot.igv.data.Group;
28 import com.sun.hotspot.igv.data.InputBlock;
29 import com.sun.hotspot.igv.data.InputBytecode;
30 import com.sun.hotspot.igv.data.InputEdge;
31 import com.sun.hotspot.igv.data.InputGraph;
32 import com.sun.hotspot.igv.data.InputMethod;
33 import com.sun.hotspot.igv.data.InputNode;
34 import com.sun.hotspot.igv.data.Properties;
35 import com.sun.hotspot.igv.data.Property;
36 import java.io.IOException;
37 import java.io.Writer;
38 import java.util.HashSet;
39 import java.util.Set;
40 
41 /**
42  *
43  * @author Thomas Wuerthinger
44  */
45 public class Printer {
46 
export(Writer writer, GraphDocument document)47     public void export(Writer writer, GraphDocument document) {
48 
49         XMLWriter xmlWriter = new XMLWriter(writer);
50 
51         try {
52             export(xmlWriter, document);
53         } catch (IOException ex) {
54         }
55     }
56 
export(XMLWriter xmlWriter, GraphDocument document)57     private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException {
58         xmlWriter.startTag(Parser.ROOT_ELEMENT);
59         xmlWriter.writeProperties(document.getProperties());
60         for (Group g : document.getGroups()) {
61             export(xmlWriter, g);
62         }
63 
64         xmlWriter.endTag();
65         xmlWriter.flush();
66     }
67 
export(XMLWriter writer, Group g)68     private void export(XMLWriter writer, Group g) throws IOException {
69         Properties attributes = new Properties();
70         attributes.setProperty("difference", Boolean.toString(true));
71         writer.startTag(Parser.GROUP_ELEMENT, attributes);
72         writer.writeProperties(g.getProperties());
73 
74         if (g.getMethod() != null) {
75             export(writer, g.getMethod());
76         }
77 
78         InputGraph previous = null;
79         for (InputGraph graph : g.getGraphs()) {
80             export(writer, graph, previous, true);
81             previous = graph;
82         }
83 
84         writer.endTag();
85     }
86 
export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference)87     public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException {
88 
89         writer.startTag(Parser.GRAPH_ELEMENT);
90         writer.writeProperties(graph.getProperties());
91         writer.startTag(Parser.NODES_ELEMENT);
92 
93         Set<InputNode> removed = new HashSet<InputNode>();
94         Set<InputNode> equal = new HashSet<InputNode>();
95 
96         if (previous != null) {
97             for (InputNode n : previous.getNodes()) {
98                 int id = n.getId();
99                 InputNode n2 = graph.getNode(id);
100                 if (n2 == null) {
101                     removed.add(n);
102                 } else if (n.equals(n2)) {
103                     equal.add(n);
104                 }
105             }
106         }
107 
108         if (difference) {
109             for (InputNode n : removed) {
110                 writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId())));
111             }
112         }
113 
114         for (InputNode n : graph.getNodes()) {
115             if (!difference || !equal.contains(n)) {
116                 writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId())));
117                 writer.writeProperties(n.getProperties());
118                 writer.endTag();
119             }
120         }
121 
122         writer.endTag();
123 
124         writer.startTag(Parser.EDGES_ELEMENT);
125         Set<InputEdge> removedEdges = new HashSet<InputEdge>();
126         Set<InputEdge> equalEdges = new HashSet<InputEdge>();
127 
128         if (previous != null) {
129             for (InputEdge e : previous.getEdges()) {
130                 if (graph.getEdges().contains(e)) {
131                     equalEdges.add(e);
132                 } else {
133                     removedEdges.add(e);
134                 }
135             }
136         }
137 
138         if (difference) {
139             for (InputEdge e : removedEdges) {
140                 writer.simpleTag(Parser.REMOVE_EDGE_ELEMENT, createProperties(e));
141             }
142         }
143 
144         for (InputEdge e : graph.getEdges()) {
145             if (!difference || !equalEdges.contains(e)) {
146                 if (!equalEdges.contains(e)) {
147                     writer.simpleTag(Parser.EDGE_ELEMENT, createProperties(e));
148                 }
149             }
150         }
151 
152         writer.endTag();
153 
154         writer.startTag(Parser.CONTROL_FLOW_ELEMENT);
155         for (InputBlock b : graph.getBlocks()) {
156 
157             writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName()));
158 
159             writer.startTag(Parser.SUCCESSORS_ELEMENT);
160             for (InputBlock s : b.getSuccessors()) {
161                 writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName()));
162             }
163             writer.endTag();
164 
165             writer.startTag(Parser.NODES_ELEMENT);
166             for (InputNode n : b.getNodes()) {
167                 writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + ""));
168             }
169             writer.endTag();
170 
171             writer.endTag();
172 
173         }
174 
175         writer.endTag();
176         writer.endTag();
177     }
178 
export(XMLWriter w, InputMethod method)179     private void export(XMLWriter w, InputMethod method) throws IOException {
180 
181         w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName()));
182 
183         w.writeProperties(method.getProperties());
184 
185         if (method.getInlined().size() > 0) {
186             w.startTag(Parser.INLINE_ELEMENT);
187             for (InputMethod m : method.getInlined()) {
188                 export(w, m);
189             }
190             w.endTag();
191         }
192 
193         w.startTag(Parser.BYTECODES_ELEMENT);
194 
195         StringBuilder b = new StringBuilder();
196         b.append("<![CDATA[\n");
197         for (InputBytecode code : method.getBytecodes()) {
198             b.append(code.getBci());
199             b.append(" ");
200             b.append(code.getName());
201             b.append("\n");
202 
203         }
204         b.append("]]>");
205         w.write(b.toString());
206         w.endTag();
207         w.endTag();
208     }
209 
createProperties(InputEdge edge)210     private Properties createProperties(InputEdge edge) {
211         Properties p = new Properties();
212         p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex()));
213         p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo()));
214         p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom()));
215         return p;
216     }
217 }
218