Mercurial > hg > truffle
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 } |