comparison visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java @ 4512:015fb895586b

Moved visualizer to new directory.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 07 Feb 2012 22:41:09 +0100
parents
children
comparison
equal deleted inserted replaced
4511:6cb549627941 4512:015fb895586b
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.*;
27 import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler;
28 import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler;
29 import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor;
30 import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler;
31 import com.sun.hotspot.igv.data.services.GroupCallback;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.Map;
37 import javax.swing.SwingUtilities;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.parsers.SAXParserFactory;
40 import javax.xml.transform.Source;
41 import javax.xml.transform.stream.StreamSource;
42 import javax.xml.validation.SchemaFactory;
43 import org.xml.sax.InputSource;
44 import org.xml.sax.SAXException;
45 import org.xml.sax.XMLReader;
46
47 /**
48 *
49 * @author Thomas Wuerthinger
50 */
51 public class Parser {
52
53 public static final String INDENT = " ";
54 public static final String TOP_ELEMENT = "graphDocument";
55 public static final String GROUP_ELEMENT = "group";
56 public static final String GRAPH_ELEMENT = "graph";
57 public static final String ROOT_ELEMENT = "graphDocument";
58 public static final String PROPERTIES_ELEMENT = "properties";
59 public static final String EDGES_ELEMENT = "edges";
60 public static final String PROPERTY_ELEMENT = "p";
61 public static final String EDGE_ELEMENT = "edge";
62 public static final String NODE_ELEMENT = "node";
63 public static final String NODES_ELEMENT = "nodes";
64 public static final String REMOVE_EDGE_ELEMENT = "removeEdge";
65 public static final String REMOVE_NODE_ELEMENT = "removeNode";
66 public static final String METHOD_NAME_PROPERTY = "name";
67 public static final String GROUP_NAME_PROPERTY = "name";
68 public static final String METHOD_IS_PUBLIC_PROPERTY = "public";
69 public static final String METHOD_IS_STATIC_PROPERTY = "static";
70 public static final String TRUE_VALUE = "true";
71 public static final String NODE_NAME_PROPERTY = "name";
72 public static final String EDGE_NAME_PROPERTY = "name";
73 public static final String NODE_ID_PROPERTY = "id";
74 public static final String FROM_PROPERTY = "from";
75 public static final String TO_PROPERTY = "to";
76 public static final String PROPERTY_NAME_PROPERTY = "name";
77 public static final String GRAPH_NAME_PROPERTY = "name";
78 public static final String FROM_INDEX_PROPERTY = "fromIndex";
79 public static final String TO_INDEX_PROPERTY = "toIndex";
80 public static final String TO_INDEX_ALT_PROPERTY = "index";
81 public static final String LABEL_PROPERTY = "label";
82 public static final String METHOD_ELEMENT = "method";
83 public static final String INLINE_ELEMENT = "inline";
84 public static final String BYTECODES_ELEMENT = "bytecodes";
85 public static final String METHOD_BCI_PROPERTY = "bci";
86 public static final String METHOD_SHORT_NAME_PROPERTY = "shortName";
87 public static final String CONTROL_FLOW_ELEMENT = "controlFlow";
88 public static final String BLOCK_NAME_PROPERTY = "name";
89 public static final String BLOCK_ELEMENT = "block";
90 public static final String SUCCESSORS_ELEMENT = "successors";
91 public static final String SUCCESSOR_ELEMENT = "successor";
92 public static final String ASSEMBLY_ELEMENT = "assembly";
93 public static final String DIFFERENCE_PROPERTY = "difference";
94 private TopElementHandler<GraphDocument> xmlDocument = new TopElementHandler<>();
95 private Map<Group, Boolean> differenceEncoding = new HashMap<>();
96 private Map<Group, InputGraph> lastParsedGraph = new HashMap<>();
97 private GroupCallback groupCallback;
98 private HashMap<String, Integer> idCache = new HashMap<>();
99 private ArrayList<Pair<String, String>> blockConnections = new ArrayList<>();
100 private int maxId = 0;
101 private GraphDocument graphDocument;
102
103 private int lookupID(String i) {
104 try {
105 return Integer.parseInt(i);
106 } catch (NumberFormatException nfe) {
107 // ignore
108 }
109 Integer id = idCache.get(i);
110 if (id == null) {
111 id = maxId++;
112 idCache.put(i, id);
113 }
114 return id.intValue();
115 }
116
117 // <graphDocument>
118 private ElementHandler<GraphDocument, Object> topHandler = new ElementHandler<GraphDocument, Object>(TOP_ELEMENT) {
119
120 @Override
121 protected GraphDocument start() throws SAXException {
122 graphDocument = new GraphDocument();
123 return graphDocument;
124 }
125 };
126 // <group>
127 private ElementHandler<Group, Folder> groupHandler = new XMLParser.ElementHandler<Group, Folder>(GROUP_ELEMENT) {
128
129 @Override
130 protected Group start() throws SAXException {
131 final Group group = new Group(this.getParentObject());
132
133 String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY);
134 Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true"))));
135
136 ParseMonitor monitor = getMonitor();
137 if (monitor != null) {
138 monitor.setState(group.getName());
139 }
140
141 final Folder parent = getParentObject();
142 if (groupCallback == null || parent instanceof Group) {
143 SwingUtilities.invokeLater(new Runnable(){
144 @Override
145 public void run() {
146 parent.addElement(group);
147 }
148 });
149 }
150
151 return group;
152 }
153
154 @Override
155 protected void end(String text) throws SAXException {
156 }
157 };
158 // <method>
159 private ElementHandler<InputMethod, Group> methodHandler = new XMLParser.ElementHandler<InputMethod, Group>(METHOD_ELEMENT) {
160
161 @Override
162 protected InputMethod start() throws SAXException {
163
164 InputMethod method = parseMethod(this, getParentObject());
165 getParentObject().setMethod(method);
166 return method;
167 }
168 };
169
170 private InputMethod parseMethod(XMLParser.ElementHandler<?,?> handler, Group group) throws SAXException {
171 String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY);
172 int bci = 0;
173 try {
174 bci = Integer.parseInt(s);
175 } catch (NumberFormatException e) {
176 throw new SAXException(e);
177 }
178 InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci);
179 return method;
180 }
181 // <bytecodes>
182 private HandoverElementHandler<InputMethod> bytecodesHandler = new XMLParser.HandoverElementHandler<InputMethod>(BYTECODES_ELEMENT, true) {
183
184 @Override
185 protected void end(String text) throws SAXException {
186 getParentObject().setBytecodes(text);
187 }
188 };
189 // <inlined>
190 private HandoverElementHandler<InputMethod> inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT);
191 // <inlined><method>
192 private ElementHandler<InputMethod, InputMethod> inlinedMethodHandler = new XMLParser.ElementHandler<InputMethod, InputMethod>(METHOD_ELEMENT) {
193
194 @Override
195 protected InputMethod start() throws SAXException {
196 InputMethod method = parseMethod(this, getParentObject().getGroup());
197 getParentObject().addInlined(method);
198 return method;
199 }
200 };
201 // <graph>
202 private ElementHandler<InputGraph, Group> graphHandler = new XMLParser.ElementHandler<InputGraph, Group>(GRAPH_ELEMENT) {
203
204 @Override
205 protected InputGraph start() throws SAXException {
206 String name = readAttribute(GRAPH_NAME_PROPERTY);
207 InputGraph curGraph = new InputGraph(name);
208 if (differenceEncoding.get(getParentObject())) {
209 InputGraph previous = lastParsedGraph.get(getParentObject());
210 lastParsedGraph.put(getParentObject(), curGraph);
211 if (previous != null) {
212 for (InputNode n : previous.getNodes()) {
213 curGraph.addNode(n);
214 }
215 for (InputEdge e : previous.getEdges()) {
216 curGraph.addEdge(e);
217 }
218 }
219 }
220 return curGraph;
221 }
222
223 @Override
224 protected void end(String text) throws SAXException {
225 // NOTE: Some graphs intentionally don't provide blocks. Instead
226 // they later generate the blocks from other information such
227 // as node properties (example: ServerCompilerScheduler).
228 // Thus, we shouldn't assign nodes that don't belong to any
229 // block to some artificial block below unless blocks are
230 // defined and nodes are assigned to them.
231
232 final InputGraph graph = getObject();
233 final Group parent = getParentObject();
234 if (graph.getBlocks().size() > 0) {
235 boolean blocksContainNodes = false;
236 for (InputBlock b : graph.getBlocks()) {
237 if (b.getNodes().size() > 0) {
238 blocksContainNodes = true;
239 break;
240 }
241 }
242
243 if (!blocksContainNodes) {
244 graph.clearBlocks();
245 blockConnections.clear();
246 } else {
247 // Blocks and their nodes defined: add other nodes to an
248 // artificial "no block" block
249 InputBlock noBlock = null;
250 for (InputNode n : graph.getNodes()) {
251 if (graph.getBlock(n) == null) {
252 if (noBlock == null) {
253 noBlock = graph.addBlock("(no block)");
254 }
255
256 noBlock.addNode(n.getId());
257 }
258
259 assert graph.getBlock(n) != null;
260 }
261 }
262 }
263
264 // Resolve block successors
265 for (Pair<String, String> p : blockConnections) {
266 final InputBlock left = graph.getBlock(p.getLeft());
267 assert left != null;
268 final InputBlock right = graph.getBlock(p.getRight());
269 assert right != null;
270 graph.addBlockEdge(left, right);
271 }
272 blockConnections.clear();
273
274 SwingUtilities.invokeLater(new Runnable(){
275
276 @Override
277 public void run() {
278 // Add to group
279 parent.addElement(graph);
280 }
281 });
282 }
283 };
284 // <nodes>
285 private HandoverElementHandler<InputGraph> nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
286 // <controlFlow>
287 private HandoverElementHandler<InputGraph> controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT);
288 // <block>
289 private ElementHandler<InputBlock, InputGraph> blockHandler = new ElementHandler<InputBlock, InputGraph>(BLOCK_ELEMENT) {
290
291 @Override
292 protected InputBlock start() throws SAXException {
293 InputGraph graph = getParentObject();
294 String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
295 InputBlock b = graph.addBlock(name);
296 for (InputNode n : b.getNodes()) {
297 assert graph.getBlock(n).equals(b);
298 }
299 return b;
300 }
301 };
302 // <nodes>
303 private HandoverElementHandler<InputBlock> blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT);
304 // <node>
305 private ElementHandler<InputBlock, InputBlock> blockNodeHandler = new ElementHandler<InputBlock, InputBlock>(NODE_ELEMENT) {
306
307 @Override
308 protected InputBlock start() throws SAXException {
309 String s = readRequiredAttribute(NODE_ID_PROPERTY);
310
311 int id = 0;
312 try {
313 id = lookupID(s);
314 } catch (NumberFormatException e) {
315 throw new SAXException(e);
316 }
317 getParentObject().addNode(id);
318 return getParentObject();
319 }
320 };
321 // <successors>
322 private HandoverElementHandler<InputBlock> successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT);
323 // <successor>
324 private ElementHandler<InputBlock, InputBlock> successorHandler = new ElementHandler<InputBlock, InputBlock>(SUCCESSOR_ELEMENT) {
325
326 @Override
327 protected InputBlock start() throws SAXException {
328 String name = readRequiredAttribute(BLOCK_NAME_PROPERTY);
329 blockConnections.add(new Pair<>(getParentObject().getName(), name));
330 return getParentObject();
331 }
332 };
333 // <node>
334 private ElementHandler<InputNode, InputGraph> nodeHandler = new ElementHandler<InputNode, InputGraph>(NODE_ELEMENT) {
335
336 @Override
337 protected InputNode start() throws SAXException {
338 String s = readRequiredAttribute(NODE_ID_PROPERTY);
339 int id = 0;
340 try {
341 id = lookupID(s);
342 } catch (NumberFormatException e) {
343 throw new SAXException(e);
344 }
345 InputNode node = new InputNode(id);
346 getParentObject().addNode(node);
347 return node;
348 }
349 };
350 // <removeNode>
351 private ElementHandler<InputNode, InputGraph> removeNodeHandler = new ElementHandler<InputNode, InputGraph>(REMOVE_NODE_ELEMENT) {
352
353 @Override
354 protected InputNode start() throws SAXException {
355 String s = readRequiredAttribute(NODE_ID_PROPERTY);
356 int id = 0;
357 try {
358 id = lookupID(s);
359 } catch (NumberFormatException e) {
360 throw new SAXException(e);
361 }
362 return getParentObject().removeNode(id);
363 }
364 };
365 // <graph>
366 private HandoverElementHandler<InputGraph> edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT);
367
368 // Local class for edge elements
369 private class EdgeElementHandler extends ElementHandler<InputEdge, InputGraph> {
370
371 public EdgeElementHandler(String name) {
372 super(name);
373 }
374
375 @Override
376 protected InputEdge start() throws SAXException {
377 int fromIndex = 0;
378 int toIndex = 0;
379 int from = -1;
380 int to = -1;
381 String label = null;
382
383 try {
384 String fromIndexString = readAttribute(FROM_INDEX_PROPERTY);
385 if (fromIndexString != null) {
386 fromIndex = Integer.parseInt(fromIndexString);
387 }
388
389 String toIndexString = readAttribute(TO_INDEX_PROPERTY);
390 if (toIndexString == null) {
391 toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY);
392 }
393 if (toIndexString != null) {
394 toIndex = Integer.parseInt(toIndexString);
395 }
396
397 label = readAttribute(LABEL_PROPERTY);
398
399 from = lookupID(readRequiredAttribute(FROM_PROPERTY));
400 to = lookupID(readRequiredAttribute(TO_PROPERTY));
401 } catch (NumberFormatException e) {
402 throw new SAXException(e);
403 }
404
405 InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label);
406 return start(conn);
407 }
408
409 protected InputEdge start(InputEdge conn) throws SAXException {
410 return conn;
411 }
412 }
413 // <edge>
414 private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) {
415
416 @Override
417 protected InputEdge start(InputEdge conn) throws SAXException {
418 getParentObject().addEdge(conn);
419 return conn;
420 }
421 };
422 // <removeEdge>
423 private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) {
424
425 @Override
426 protected InputEdge start(InputEdge conn) throws SAXException {
427 getParentObject().removeEdge(conn);
428 return conn;
429 }
430 };
431 // <properties>
432 private HandoverElementHandler<Properties.Provider> propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT);
433 // <properties>
434 private HandoverElementHandler<Group> groupPropertiesHandler = new HandoverElementHandler<Group>(PROPERTIES_ELEMENT) {
435
436 @Override
437 public void end(String text) throws SAXException {
438 if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) {
439 final Group group = getParentObject();
440 SwingUtilities.invokeLater(new Runnable() {
441 @Override
442 public void run() {
443 groupCallback.started(group);
444 }
445 });
446 }
447 }
448 };
449 // <property>
450 private ElementHandler<String, Properties.Provider> propertyHandler = new XMLParser.ElementHandler<String, Properties.Provider>(PROPERTY_ELEMENT, true) {
451
452 @Override
453 public String start() throws SAXException {
454 return readRequiredAttribute(PROPERTY_NAME_PROPERTY);
455 }
456
457 @Override
458 public void end(String text) {
459 getParentObject().getProperties().setProperty(getObject(), text.trim());
460 }
461 };
462
463 public Parser() {
464 this(null);
465 }
466
467 public Parser(GroupCallback groupCallback) {
468
469 this.groupCallback = groupCallback;
470
471 // Initialize dependencies
472 xmlDocument.addChild(topHandler);
473 topHandler.addChild(groupHandler);
474
475 groupHandler.addChild(methodHandler);
476 groupHandler.addChild(graphHandler);
477 groupHandler.addChild(groupHandler);
478
479 methodHandler.addChild(inlinedHandler);
480 methodHandler.addChild(bytecodesHandler);
481
482 inlinedHandler.addChild(inlinedMethodHandler);
483 inlinedMethodHandler.addChild(bytecodesHandler);
484 inlinedMethodHandler.addChild(inlinedHandler);
485
486 graphHandler.addChild(nodesHandler);
487 graphHandler.addChild(edgesHandler);
488 graphHandler.addChild(controlFlowHandler);
489
490 controlFlowHandler.addChild(blockHandler);
491
492 blockHandler.addChild(successorsHandler);
493 successorsHandler.addChild(successorHandler);
494 blockHandler.addChild(blockNodesHandler);
495 blockNodesHandler.addChild(blockNodeHandler);
496
497 nodesHandler.addChild(nodeHandler);
498 nodesHandler.addChild(removeNodeHandler);
499 edgesHandler.addChild(edgeHandler);
500 edgesHandler.addChild(removeEdgeHandler);
501
502 methodHandler.addChild(propertiesHandler);
503 inlinedMethodHandler.addChild(propertiesHandler);
504 topHandler.addChild(propertiesHandler);
505 groupHandler.addChild(groupPropertiesHandler);
506 graphHandler.addChild(propertiesHandler);
507 nodeHandler.addChild(propertiesHandler);
508 propertiesHandler.addChild(propertyHandler);
509 groupPropertiesHandler.addChild(propertyHandler);
510 }
511
512 // Returns a new GraphDocument object deserialized from an XML input source.
513 public GraphDocument parse(InputSource source, XMLParser.ParseMonitor monitor) throws SAXException {
514 XMLReader reader = createReader();
515
516 reader.setContentHandler(new XMLParser(xmlDocument, monitor));
517 try {
518 reader.parse(source);
519 } catch (IOException ex) {
520 throw new SAXException(ex);
521 }
522
523 return graphDocument;
524 }
525
526 private XMLReader createReader() throws SAXException {
527 try {
528 SAXParserFactory pfactory = SAXParserFactory.newInstance();
529 pfactory.setValidating(false);
530 pfactory.setNamespaceAware(true);
531
532 // Enable schema validation
533 SchemaFactory sfactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
534 InputStream stream = Parser.class.getResourceAsStream("graphdocument.xsd");
535 pfactory.setSchema(sfactory.newSchema(new Source[]{new StreamSource(stream)}));
536
537 return pfactory.newSAXParser().getXMLReader();
538 } catch (ParserConfigurationException ex) {
539 throw new SAXException(ex);
540 }
541 }
542 }