23 package org.graalvm.compiler.printer; 24 25 import static org.graalvm.compiler.graph.Edges.Type.Inputs; 26 import static org.graalvm.compiler.graph.Edges.Type.Successors; 27 28 import java.io.IOException; 29 import java.nio.ByteBuffer; 30 import java.nio.channels.WritableByteChannel; 31 import java.nio.charset.Charset; 32 import java.util.Arrays; 33 import java.util.HashMap; 34 import java.util.LinkedHashMap; 35 import java.util.LinkedList; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Map.Entry; 39 40 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 41 import org.graalvm.compiler.bytecode.Bytecode; 42 import org.graalvm.compiler.core.common.cfg.BlockMap; 43 import org.graalvm.compiler.debug.Debug; 44 import org.graalvm.compiler.debug.GraalDebugConfig.Options; 45 import org.graalvm.compiler.graph.CachedGraph; 46 import org.graalvm.compiler.graph.Edges; 47 import org.graalvm.compiler.graph.Graph; 48 import org.graalvm.compiler.graph.InputEdges; 49 import org.graalvm.compiler.graph.Node; 50 import org.graalvm.compiler.graph.NodeClass; 51 import org.graalvm.compiler.graph.NodeList; 52 import org.graalvm.compiler.graph.NodeMap; 53 import org.graalvm.compiler.nodes.AbstractBeginNode; 54 import org.graalvm.compiler.nodes.AbstractEndNode; 55 import org.graalvm.compiler.nodes.AbstractMergeNode; 56 import org.graalvm.compiler.nodes.ConstantNode; 57 import org.graalvm.compiler.nodes.ControlSinkNode; 58 import org.graalvm.compiler.nodes.ControlSplitNode; 59 import org.graalvm.compiler.nodes.FixedNode; 60 import org.graalvm.compiler.nodes.PhiNode; 61 import org.graalvm.compiler.nodes.ProxyNode; 62 import org.graalvm.compiler.nodes.StructuredGraph; 63 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 64 import org.graalvm.compiler.nodes.VirtualState; 65 import org.graalvm.compiler.nodes.cfg.Block; 66 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 67 import org.graalvm.compiler.phases.schedule.SchedulePhase; 68 69 import jdk.vm.ci.meta.JavaType; 70 import jdk.vm.ci.meta.ResolvedJavaField; 71 import jdk.vm.ci.meta.ResolvedJavaMethod; 72 import jdk.vm.ci.meta.Signature; 73 import org.graalvm.compiler.graph.NodeSourcePosition; 74 75 public class BinaryGraphPrinter implements GraphPrinter { 76 77 private static final int CONSTANT_POOL_MAX_SIZE = 8000; 78 79 private static final int BEGIN_GROUP = 0x00; 80 private static final int BEGIN_GRAPH = 0x01; 81 private static final int CLOSE_GROUP = 0x02; 82 83 private static final int POOL_NEW = 0x00; 84 private static final int POOL_STRING = 0x01; 85 private static final int POOL_ENUM = 0x02; 86 private static final int POOL_CLASS = 0x03; 87 private static final int POOL_METHOD = 0x04; 135 return false; 136 } 137 138 private Character nextAvailableId() { 139 if (!availableIds.isEmpty()) { 140 return availableIds.removeFirst(); 141 } 142 return nextId++; 143 } 144 145 public char add(Object obj) { 146 Character id = nextAvailableId(); 147 put(obj, id); 148 return id; 149 } 150 } 151 152 private final ConstantPool constantPool; 153 private final ByteBuffer buffer; 154 private final WritableByteChannel channel; 155 private SnippetReflectionProvider snippetReflection; 156 157 private static final Charset utf8 = Charset.forName("UTF-8"); 158 159 public BinaryGraphPrinter(WritableByteChannel channel) throws IOException { 160 constantPool = new ConstantPool(); 161 buffer = ByteBuffer.allocateDirect(256 * 1024); 162 this.channel = channel; 163 writeVersion(); 164 } 165 166 @Override 167 public void setSnippetReflectionProvider(SnippetReflectionProvider snippetReflection) { 168 this.snippetReflection = snippetReflection; 169 } 170 171 @Override 172 public SnippetReflectionProvider getSnippetReflectionProvider() { 173 return snippetReflection; 174 } 175 176 @SuppressWarnings("all") 177 @Override 178 public void print(Graph graph, Map<Object, Object> properties, int id, String format, Object... args) throws IOException { 179 writeByte(BEGIN_GRAPH); 180 if (CURRENT_MAJOR_VERSION >= 3) { 181 writeInt(id); 182 writeString(format); 183 writeInt(args.length); 184 for (Object a : args) { 185 writePropertyObject(a); 186 } 187 } else { 188 writePoolObject(formatTitle(id, format, args)); 189 } 190 writeGraph(graph, properties); 191 flush(); 192 } 193 194 private void writeGraph(Graph graph, Map<Object, Object> properties) throws IOException { 195 ScheduleResult scheduleResult = null; 196 if (graph instanceof StructuredGraph) { 197 198 StructuredGraph structuredGraph = (StructuredGraph) graph; 199 scheduleResult = structuredGraph.getLastSchedule(); 200 if (scheduleResult == null) { 201 202 // Also provide a schedule when an error occurs 203 if (Options.PrintGraphWithSchedule.getValue(graph.getOptions()) || Debug.contextLookup(Throwable.class) != null) { 204 try { 205 SchedulePhase schedule = new SchedulePhase(graph.getOptions()); 206 schedule.apply(structuredGraph); 207 scheduleResult = structuredGraph.getLastSchedule(); 208 } catch (Throwable t) { 209 } 210 } 211 212 } 213 } 214 ControlFlowGraph cfg = scheduleResult == null ? Debug.contextLookup(ControlFlowGraph.class) : scheduleResult.getCFG(); 215 BlockMap<List<Node>> blockToNodes = scheduleResult == null ? null : scheduleResult.getBlockToNodesMap(); 216 NodeMap<Block> nodeToBlocks = scheduleResult == null ? null : scheduleResult.getNodeToBlockMap(); 217 List<Block> blocks = cfg == null ? null : Arrays.asList(cfg.getBlocks()); 218 writeProperties(properties); 219 writeNodes(graph, nodeToBlocks, cfg); 220 writeBlocks(blocks, blockToNodes); 221 } 222 223 private void flush() throws IOException { 224 buffer.flip(); 225 /* 226 * Try not to let interrupted threads aborting the write. There's still a race here but an 227 * interrupt that's been pending for a long time shouldn't stop this writing. 228 */ 229 boolean interrupted = Thread.interrupted(); 230 try { 231 channel.write(buffer); 232 } finally { 233 if (interrupted) { 234 Thread.currentThread().interrupt(); 235 } 236 } 237 buffer.compact(); 238 } 239 240 private void ensureAvailable(int i) throws IOException { 241 assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small"; 242 while (buffer.remaining() < i) { 243 flush(); 244 } 245 } 246 421 writePoolObject(field.getType().getName()); 422 writeInt(field.getModifiers()); 423 } else if (object instanceof Signature) { 424 writeByte(POOL_SIGNATURE); 425 Signature signature = ((Signature) object); 426 int args = signature.getParameterCount(false); 427 writeShort((char) args); 428 for (int i = 0; i < args; i++) { 429 writePoolObject(signature.getParameterType(i, null).getName()); 430 } 431 writePoolObject(signature.getReturnType(null).getName()); 432 } else if (CURRENT_MAJOR_VERSION >= 4 && object instanceof NodeSourcePosition) { 433 writeByte(POOL_NODE_SOURCE_POSITION); 434 NodeSourcePosition pos = (NodeSourcePosition) object; 435 ResolvedJavaMethod method = pos.getMethod(); 436 writePoolObject(method); 437 final int bci = pos.getBCI(); 438 writeInt(bci); 439 StackTraceElement ste = method.asStackTraceElement(bci); 440 if (ste != null) { 441 writePoolObject(ste.getFileName()); 442 writeInt(ste.getLineNumber()); 443 } else { 444 writePoolObject(null); 445 } 446 writePoolObject(pos.getCaller()); 447 } else { 448 writeByte(POOL_STRING); 449 writeString(object.toString()); 450 } 451 } 452 453 private void writeEdgesInfo(NodeClass<?> nodeClass, Edges.Type type) throws IOException { 454 Edges edges = nodeClass.getEdges(type); 455 writeShort((char) edges.getCount()); 456 for (int i = 0; i < edges.getCount(); i++) { 457 writeByte(i < edges.getDirectCount() ? 0 : 1); 458 writePoolObject(edges.getName(i)); 459 if (type == Inputs) { 460 writePoolObject(((InputEdges) edges).getInputType(i)); 461 } 462 } 463 } 464 465 private void writePropertyObject(Object obj) throws IOException { 466 if (obj instanceof Integer) { 467 writeByte(PROPERTY_INT); 468 writeInt(((Integer) obj).intValue()); 469 } else if (obj instanceof Long) { 470 writeByte(PROPERTY_LONG); 471 writeLong(((Long) obj).longValue()); 472 } else if (obj instanceof Double) { 473 writeByte(PROPERTY_DOUBLE); 474 writeDouble(((Double) obj).doubleValue()); 475 } else if (obj instanceof Float) { 476 writeByte(PROPERTY_FLOAT); 477 writeFloat(((Float) obj).floatValue()); 478 } else if (obj instanceof Boolean) { 479 if (((Boolean) obj).booleanValue()) { 480 writeByte(PROPERTY_TRUE); 481 } else { 482 writeByte(PROPERTY_FALSE); 483 } 484 } else if (obj instanceof Graph) { 485 writeByte(PROPERTY_SUBGRAPH); 486 writeGraph((Graph) obj, null); 487 } else if (obj instanceof CachedGraph) { 488 writeByte(PROPERTY_SUBGRAPH); 489 writeGraph(((CachedGraph<?>) obj).getReadonlyCopy(), null); 490 } else if (obj != null && obj.getClass().isArray()) { 491 Class<?> componentType = obj.getClass().getComponentType(); 492 if (componentType.isPrimitive()) { 493 if (componentType == Double.TYPE) { 494 writeByte(PROPERTY_ARRAY); 495 writeByte(PROPERTY_DOUBLE); 496 writeDoubles((double[]) obj); 497 } else if (componentType == Integer.TYPE) { 498 writeByte(PROPERTY_ARRAY); 499 writeByte(PROPERTY_INT); 500 writeInts((int[]) obj); 501 } else { 502 writeByte(PROPERTY_POOL); 503 writePoolObject(obj); 504 } 505 } else { 506 writeByte(PROPERTY_ARRAY); 507 writeByte(PROPERTY_POOL); 508 Object[] array = (Object[]) obj; 509 writeInt(array.length); 519 520 @SuppressWarnings("deprecation") 521 private static int getNodeId(Node node) { 522 return node.getId(); 523 } 524 525 private Object getBlockForNode(Node node, NodeMap<Block> nodeToBlocks) { 526 if (nodeToBlocks.isNew(node)) { 527 return "NEW (not in schedule)"; 528 } else { 529 Block block = nodeToBlocks.get(node); 530 if (block != null) { 531 return block.getId(); 532 } else if (node instanceof PhiNode) { 533 return getBlockForNode(((PhiNode) node).merge(), nodeToBlocks); 534 } 535 } 536 return null; 537 } 538 539 private void writeNodes(Graph graph, NodeMap<Block> nodeToBlocks, ControlFlowGraph cfg) throws IOException { 540 Map<Object, Object> props = new HashMap<>(); 541 542 writeInt(graph.getNodeCount()); 543 544 for (Node node : graph.getNodes()) { 545 NodeClass<?> nodeClass = node.getNodeClass(); 546 node.getDebugProperties(props); 547 if (cfg != null && Options.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) { 548 try { 549 props.put("probability", cfg.blockFor(node).probability()); 550 } catch (Throwable t) { 551 props.put("probability", 0.0); 552 props.put("probability-exception", t); 553 } 554 } 555 556 try { 557 props.put("NodeCost-Size", node.estimatedNodeSize()); 558 props.put("NodeCost-Cycles", node.estimatedNodeCycles()); 559 } catch (Throwable t) { 560 props.put("node-cost-exception", t.getMessage()); 561 } 562 563 if (nodeToBlocks != null) { 564 Object block = getBlockForNode(node, nodeToBlocks); 565 if (block != null) { 566 props.put("node-to-block", block); 567 } 579 props.put("category", "end"); 580 } else if (node instanceof FixedNode) { 581 props.put("category", "fixed"); 582 } else if (node instanceof VirtualState) { 583 props.put("category", "state"); 584 } else if (node instanceof PhiNode) { 585 props.put("category", "phi"); 586 } else if (node instanceof ProxyNode) { 587 props.put("category", "proxy"); 588 } else { 589 if (node instanceof ConstantNode) { 590 ConstantNode cn = (ConstantNode) node; 591 updateStringPropertiesForConstant(props, cn); 592 } 593 props.put("category", "floating"); 594 } 595 596 writeInt(getNodeId(node)); 597 writePoolObject(nodeClass); 598 writeByte(node.predecessor() == null ? 0 : 1); 599 writeProperties(props); 600 writeEdges(node, Inputs); 601 writeEdges(node, Successors); 602 603 props.clear(); 604 } 605 } 606 607 private void writeProperties(Map<Object, Object> props) throws IOException { 608 if (props == null) { 609 writeShort((char) 0); 610 return; 611 } 612 // properties 613 writeShort((char) props.size()); 614 for (Entry<Object, Object> entry : props.entrySet()) { 615 String key = entry.getKey().toString(); 616 writePoolObject(key); 617 writePropertyObject(entry.getValue()); 618 } 619 } 620 621 private void writeEdges(Node node, Edges.Type type) throws IOException { 622 NodeClass<?> nodeClass = node.getNodeClass(); 623 Edges edges = nodeClass.getEdges(type); 624 final long[] curOffsets = edges.getOffsets(); 625 for (int i = 0; i < edges.getDirectCount(); i++) { 626 writeNodeRef(Edges.getNode(node, curOffsets, i)); 627 } 628 for (int i = edges.getDirectCount(); i < edges.getCount(); i++) { 629 NodeList<Node> list = Edges.getNodeList(node, curOffsets, i); 630 if (list == null) { 631 writeShort((char) 0); 632 } else { 633 int listSize = list.count(); 634 assert listSize == ((char) listSize); 635 writeShort((char) listSize); 636 for (Node edge : list) { 637 writeNodeRef(edge); 673 } 674 } 675 writeInt(nodes.size() + extraNodes.size()); 676 for (Node node : nodes) { 677 writeInt(getNodeId(node)); 678 } 679 for (Node node : extraNodes) { 680 writeInt(getNodeId(node)); 681 } 682 writeInt(block.getSuccessors().length); 683 for (Block sux : block.getSuccessors()) { 684 writeInt(sux.getId()); 685 } 686 } 687 } else { 688 writeInt(0); 689 } 690 } 691 692 @Override 693 public void beginGroup(String name, String shortName, ResolvedJavaMethod method, int bci, Map<Object, Object> properties) throws IOException { 694 writeByte(BEGIN_GROUP); 695 writePoolObject(name); 696 writePoolObject(shortName); 697 writePoolObject(method); 698 writeInt(bci); 699 writeProperties(properties); 700 } 701 702 @Override 703 public void endGroup() throws IOException { 704 writeByte(CLOSE_GROUP); 705 } 706 707 @Override 708 public void close() { 709 try { 710 flush(); 711 channel.close(); 712 } catch (IOException ex) { 713 throw new Error(ex); 714 } 715 } 716 } | 23 package org.graalvm.compiler.printer; 24 25 import static org.graalvm.compiler.graph.Edges.Type.Inputs; 26 import static org.graalvm.compiler.graph.Edges.Type.Successors; 27 28 import java.io.IOException; 29 import java.nio.ByteBuffer; 30 import java.nio.channels.WritableByteChannel; 31 import java.nio.charset.Charset; 32 import java.util.Arrays; 33 import java.util.HashMap; 34 import java.util.LinkedHashMap; 35 import java.util.LinkedList; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.Map.Entry; 39 40 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 41 import org.graalvm.compiler.bytecode.Bytecode; 42 import org.graalvm.compiler.core.common.cfg.BlockMap; 43 import org.graalvm.compiler.debug.DebugContext; 44 import org.graalvm.compiler.debug.DebugOptions; 45 import org.graalvm.compiler.graph.CachedGraph; 46 import org.graalvm.compiler.graph.Edges; 47 import org.graalvm.compiler.graph.Graph; 48 import org.graalvm.compiler.graph.InputEdges; 49 import org.graalvm.compiler.graph.Node; 50 import org.graalvm.compiler.graph.NodeClass; 51 import org.graalvm.compiler.graph.NodeList; 52 import org.graalvm.compiler.graph.NodeMap; 53 import org.graalvm.compiler.nodes.AbstractBeginNode; 54 import org.graalvm.compiler.nodes.AbstractEndNode; 55 import org.graalvm.compiler.nodes.AbstractMergeNode; 56 import org.graalvm.compiler.nodes.ConstantNode; 57 import org.graalvm.compiler.nodes.ControlSinkNode; 58 import org.graalvm.compiler.nodes.ControlSplitNode; 59 import org.graalvm.compiler.nodes.FixedNode; 60 import org.graalvm.compiler.nodes.PhiNode; 61 import org.graalvm.compiler.nodes.ProxyNode; 62 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 63 import org.graalvm.compiler.nodes.VirtualState; 64 import org.graalvm.compiler.nodes.cfg.Block; 65 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 66 67 import jdk.vm.ci.meta.JavaType; 68 import jdk.vm.ci.meta.ResolvedJavaField; 69 import jdk.vm.ci.meta.ResolvedJavaMethod; 70 import jdk.vm.ci.meta.Signature; 71 import org.graalvm.compiler.graph.NodeSourcePosition; 72 73 public class BinaryGraphPrinter implements GraphPrinter { 74 75 private static final int CONSTANT_POOL_MAX_SIZE = 8000; 76 77 private static final int BEGIN_GROUP = 0x00; 78 private static final int BEGIN_GRAPH = 0x01; 79 private static final int CLOSE_GROUP = 0x02; 80 81 private static final int POOL_NEW = 0x00; 82 private static final int POOL_STRING = 0x01; 83 private static final int POOL_ENUM = 0x02; 84 private static final int POOL_CLASS = 0x03; 85 private static final int POOL_METHOD = 0x04; 133 return false; 134 } 135 136 private Character nextAvailableId() { 137 if (!availableIds.isEmpty()) { 138 return availableIds.removeFirst(); 139 } 140 return nextId++; 141 } 142 143 public char add(Object obj) { 144 Character id = nextAvailableId(); 145 put(obj, id); 146 return id; 147 } 148 } 149 150 private final ConstantPool constantPool; 151 private final ByteBuffer buffer; 152 private final WritableByteChannel channel; 153 private final SnippetReflectionProvider snippetReflection; 154 155 private static final Charset utf8 = Charset.forName("UTF-8"); 156 157 public BinaryGraphPrinter(WritableByteChannel channel, SnippetReflectionProvider snippetReflection) throws IOException { 158 constantPool = new ConstantPool(); 159 this.snippetReflection = snippetReflection; 160 buffer = ByteBuffer.allocateDirect(256 * 1024); 161 this.channel = channel; 162 writeVersion(); 163 } 164 165 @Override 166 public SnippetReflectionProvider getSnippetReflectionProvider() { 167 return snippetReflection; 168 } 169 170 @SuppressWarnings("all") 171 @Override 172 public void print(DebugContext debug, Graph graph, Map<Object, Object> properties, int id, String format, Object... args) throws IOException { 173 writeByte(BEGIN_GRAPH); 174 if (CURRENT_MAJOR_VERSION >= 3) { 175 writeInt(id); 176 writeString(format); 177 writeInt(args.length); 178 for (Object a : args) { 179 writePropertyObject(debug, a); 180 } 181 } else { 182 writePoolObject(id + ": " + String.format(format, simplifyClassArgs(args))); 183 } 184 writeGraph(debug, graph, properties); 185 flush(); 186 } 187 188 private void writeGraph(DebugContext debug, Graph graph, Map<Object, Object> properties) throws IOException { 189 boolean needSchedule = DebugOptions.PrintGraphWithSchedule.getValue(graph.getOptions()) || debug.contextLookup(Throwable.class) != null; 190 ScheduleResult scheduleResult = needSchedule ? GraphPrinter.getScheduleOrNull(graph) : null; 191 ControlFlowGraph cfg = scheduleResult == null ? debug.contextLookup(ControlFlowGraph.class) : scheduleResult.getCFG(); 192 BlockMap<List<Node>> blockToNodes = scheduleResult == null ? null : scheduleResult.getBlockToNodesMap(); 193 NodeMap<Block> nodeToBlocks = scheduleResult == null ? null : scheduleResult.getNodeToBlockMap(); 194 List<Block> blocks = cfg == null ? null : Arrays.asList(cfg.getBlocks()); 195 writeProperties(debug, properties); 196 writeNodes(debug, graph, nodeToBlocks, cfg); 197 writeBlocks(blocks, blockToNodes); 198 } 199 200 private void flush() throws IOException { 201 buffer.flip(); 202 /* 203 * Try not to let interrupted threads abort the write. There's still a race here but an 204 * interrupt that's been pending for a long time shouldn't stop this writing. 205 */ 206 boolean interrupted = Thread.interrupted(); 207 try { 208 channel.write(buffer); 209 } finally { 210 if (interrupted) { 211 Thread.currentThread().interrupt(); 212 } 213 } 214 buffer.compact(); 215 } 216 217 private void ensureAvailable(int i) throws IOException { 218 assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small"; 219 while (buffer.remaining() < i) { 220 flush(); 221 } 222 } 223 398 writePoolObject(field.getType().getName()); 399 writeInt(field.getModifiers()); 400 } else if (object instanceof Signature) { 401 writeByte(POOL_SIGNATURE); 402 Signature signature = ((Signature) object); 403 int args = signature.getParameterCount(false); 404 writeShort((char) args); 405 for (int i = 0; i < args; i++) { 406 writePoolObject(signature.getParameterType(i, null).getName()); 407 } 408 writePoolObject(signature.getReturnType(null).getName()); 409 } else if (CURRENT_MAJOR_VERSION >= 4 && object instanceof NodeSourcePosition) { 410 writeByte(POOL_NODE_SOURCE_POSITION); 411 NodeSourcePosition pos = (NodeSourcePosition) object; 412 ResolvedJavaMethod method = pos.getMethod(); 413 writePoolObject(method); 414 final int bci = pos.getBCI(); 415 writeInt(bci); 416 StackTraceElement ste = method.asStackTraceElement(bci); 417 if (ste != null) { 418 String fn = ste.getFileName(); 419 writePoolObject(fn); 420 if (fn != null) { 421 writeInt(ste.getLineNumber()); 422 } 423 } else { 424 writePoolObject(null); 425 } 426 writePoolObject(pos.getCaller()); 427 } else { 428 writeByte(POOL_STRING); 429 writeString(object.toString()); 430 } 431 } 432 433 private void writeEdgesInfo(NodeClass<?> nodeClass, Edges.Type type) throws IOException { 434 Edges edges = nodeClass.getEdges(type); 435 writeShort((char) edges.getCount()); 436 for (int i = 0; i < edges.getCount(); i++) { 437 writeByte(i < edges.getDirectCount() ? 0 : 1); 438 writePoolObject(edges.getName(i)); 439 if (type == Inputs) { 440 writePoolObject(((InputEdges) edges).getInputType(i)); 441 } 442 } 443 } 444 445 private void writePropertyObject(DebugContext debug, Object obj) throws IOException { 446 if (obj instanceof Integer) { 447 writeByte(PROPERTY_INT); 448 writeInt(((Integer) obj).intValue()); 449 } else if (obj instanceof Long) { 450 writeByte(PROPERTY_LONG); 451 writeLong(((Long) obj).longValue()); 452 } else if (obj instanceof Double) { 453 writeByte(PROPERTY_DOUBLE); 454 writeDouble(((Double) obj).doubleValue()); 455 } else if (obj instanceof Float) { 456 writeByte(PROPERTY_FLOAT); 457 writeFloat(((Float) obj).floatValue()); 458 } else if (obj instanceof Boolean) { 459 if (((Boolean) obj).booleanValue()) { 460 writeByte(PROPERTY_TRUE); 461 } else { 462 writeByte(PROPERTY_FALSE); 463 } 464 } else if (obj instanceof Graph) { 465 writeByte(PROPERTY_SUBGRAPH); 466 writeGraph(debug, (Graph) obj, null); 467 } else if (obj instanceof CachedGraph) { 468 writeByte(PROPERTY_SUBGRAPH); 469 writeGraph(debug, ((CachedGraph<?>) obj).getReadonlyCopy(), null); 470 } else if (obj != null && obj.getClass().isArray()) { 471 Class<?> componentType = obj.getClass().getComponentType(); 472 if (componentType.isPrimitive()) { 473 if (componentType == Double.TYPE) { 474 writeByte(PROPERTY_ARRAY); 475 writeByte(PROPERTY_DOUBLE); 476 writeDoubles((double[]) obj); 477 } else if (componentType == Integer.TYPE) { 478 writeByte(PROPERTY_ARRAY); 479 writeByte(PROPERTY_INT); 480 writeInts((int[]) obj); 481 } else { 482 writeByte(PROPERTY_POOL); 483 writePoolObject(obj); 484 } 485 } else { 486 writeByte(PROPERTY_ARRAY); 487 writeByte(PROPERTY_POOL); 488 Object[] array = (Object[]) obj; 489 writeInt(array.length); 499 500 @SuppressWarnings("deprecation") 501 private static int getNodeId(Node node) { 502 return node.getId(); 503 } 504 505 private Object getBlockForNode(Node node, NodeMap<Block> nodeToBlocks) { 506 if (nodeToBlocks.isNew(node)) { 507 return "NEW (not in schedule)"; 508 } else { 509 Block block = nodeToBlocks.get(node); 510 if (block != null) { 511 return block.getId(); 512 } else if (node instanceof PhiNode) { 513 return getBlockForNode(((PhiNode) node).merge(), nodeToBlocks); 514 } 515 } 516 return null; 517 } 518 519 private void writeNodes(DebugContext debug, Graph graph, NodeMap<Block> nodeToBlocks, ControlFlowGraph cfg) throws IOException { 520 Map<Object, Object> props = new HashMap<>(); 521 522 writeInt(graph.getNodeCount()); 523 524 for (Node node : graph.getNodes()) { 525 NodeClass<?> nodeClass = node.getNodeClass(); 526 node.getDebugProperties(props); 527 if (cfg != null && DebugOptions.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) { 528 try { 529 props.put("probability", cfg.blockFor(node).probability()); 530 } catch (Throwable t) { 531 props.put("probability", 0.0); 532 props.put("probability-exception", t); 533 } 534 } 535 536 try { 537 props.put("NodeCost-Size", node.estimatedNodeSize()); 538 props.put("NodeCost-Cycles", node.estimatedNodeCycles()); 539 } catch (Throwable t) { 540 props.put("node-cost-exception", t.getMessage()); 541 } 542 543 if (nodeToBlocks != null) { 544 Object block = getBlockForNode(node, nodeToBlocks); 545 if (block != null) { 546 props.put("node-to-block", block); 547 } 559 props.put("category", "end"); 560 } else if (node instanceof FixedNode) { 561 props.put("category", "fixed"); 562 } else if (node instanceof VirtualState) { 563 props.put("category", "state"); 564 } else if (node instanceof PhiNode) { 565 props.put("category", "phi"); 566 } else if (node instanceof ProxyNode) { 567 props.put("category", "proxy"); 568 } else { 569 if (node instanceof ConstantNode) { 570 ConstantNode cn = (ConstantNode) node; 571 updateStringPropertiesForConstant(props, cn); 572 } 573 props.put("category", "floating"); 574 } 575 576 writeInt(getNodeId(node)); 577 writePoolObject(nodeClass); 578 writeByte(node.predecessor() == null ? 0 : 1); 579 writeProperties(debug, props); 580 writeEdges(node, Inputs); 581 writeEdges(node, Successors); 582 583 props.clear(); 584 } 585 } 586 587 private void writeProperties(DebugContext debug, Map<Object, Object> props) throws IOException { 588 if (props == null) { 589 writeShort((char) 0); 590 return; 591 } 592 // properties 593 writeShort((char) props.size()); 594 for (Entry<Object, Object> entry : props.entrySet()) { 595 String key = entry.getKey().toString(); 596 writePoolObject(key); 597 writePropertyObject(debug, entry.getValue()); 598 } 599 } 600 601 private void writeEdges(Node node, Edges.Type type) throws IOException { 602 NodeClass<?> nodeClass = node.getNodeClass(); 603 Edges edges = nodeClass.getEdges(type); 604 final long[] curOffsets = edges.getOffsets(); 605 for (int i = 0; i < edges.getDirectCount(); i++) { 606 writeNodeRef(Edges.getNode(node, curOffsets, i)); 607 } 608 for (int i = edges.getDirectCount(); i < edges.getCount(); i++) { 609 NodeList<Node> list = Edges.getNodeList(node, curOffsets, i); 610 if (list == null) { 611 writeShort((char) 0); 612 } else { 613 int listSize = list.count(); 614 assert listSize == ((char) listSize); 615 writeShort((char) listSize); 616 for (Node edge : list) { 617 writeNodeRef(edge); 653 } 654 } 655 writeInt(nodes.size() + extraNodes.size()); 656 for (Node node : nodes) { 657 writeInt(getNodeId(node)); 658 } 659 for (Node node : extraNodes) { 660 writeInt(getNodeId(node)); 661 } 662 writeInt(block.getSuccessors().length); 663 for (Block sux : block.getSuccessors()) { 664 writeInt(sux.getId()); 665 } 666 } 667 } else { 668 writeInt(0); 669 } 670 } 671 672 @Override 673 public void beginGroup(DebugContext debug, String name, String shortName, ResolvedJavaMethod method, int bci, Map<Object, Object> properties) throws IOException { 674 writeByte(BEGIN_GROUP); 675 writePoolObject(name); 676 writePoolObject(shortName); 677 writePoolObject(method); 678 writeInt(bci); 679 writeProperties(debug, properties); 680 } 681 682 @Override 683 public void endGroup() throws IOException { 684 writeByte(CLOSE_GROUP); 685 } 686 687 @Override 688 public void close() { 689 try { 690 flush(); 691 channel.close(); 692 } catch (IOException ex) { 693 throw new Error(ex); 694 } 695 } 696 } |