< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java

Print this page




  35 
  36 abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> implements Closeable {
  37     private static final Charset UTF8 = Charset.forName("UTF-8");
  38 
  39     private static final int CONSTANT_POOL_MAX_SIZE = 8000;
  40 
  41     private static final int BEGIN_GROUP = 0x00;
  42     private static final int BEGIN_GRAPH = 0x01;
  43     private static final int CLOSE_GROUP = 0x02;
  44 
  45     private static final int POOL_NEW = 0x00;
  46     private static final int POOL_STRING = 0x01;
  47     private static final int POOL_ENUM = 0x02;
  48     private static final int POOL_CLASS = 0x03;
  49     private static final int POOL_METHOD = 0x04;
  50     private static final int POOL_NULL = 0x05;
  51     private static final int POOL_NODE_CLASS = 0x06;
  52     private static final int POOL_FIELD = 0x07;
  53     private static final int POOL_SIGNATURE = 0x08;
  54     private static final int POOL_NODE_SOURCE_POSITION = 0x09;

  55 
  56     private static final int PROPERTY_POOL = 0x00;
  57     private static final int PROPERTY_INT = 0x01;
  58     private static final int PROPERTY_LONG = 0x02;
  59     private static final int PROPERTY_DOUBLE = 0x03;
  60     private static final int PROPERTY_FLOAT = 0x04;
  61     private static final int PROPERTY_TRUE = 0x05;
  62     private static final int PROPERTY_FALSE = 0x06;
  63     private static final int PROPERTY_ARRAY = 0x07;
  64     private static final int PROPERTY_SUBGRAPH = 0x08;
  65 
  66     private static final int KLASS = 0x00;
  67     private static final int ENUM_KLASS = 0x01;
  68 
  69     private static final byte[] MAGIC_BYTES = {'B', 'I', 'G', 'V'};
  70 
  71     private final ConstantPool constantPool;
  72     private final ByteBuffer buffer;
  73     private final WritableByteChannel channel;
  74     private final int versionMajor;
  75     private final int versionMinor;
  76 
  77     protected GraphProtocol(WritableByteChannel channel) throws IOException {
  78         this(channel, 4, 0);
  79     }
  80 
  81     private GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
  82         if (major > 4) {
  83             throw new IllegalArgumentException();
  84         }
  85         if (major == 4 && minor > 0) {
  86             throw new IllegalArgumentException();
  87         }
  88         this.versionMajor = major;
  89         this.versionMinor = minor;
  90         this.constantPool = new ConstantPool();
  91         this.buffer = ByteBuffer.allocateDirect(256 * 1024);
  92         this.channel = channel;
  93         writeVersion();
  94     }
  95 








  96     @SuppressWarnings("all")
  97     public final void print(Graph graph, Map<? extends Object, ? extends Object> properties, int id, String format, Object... args) throws IOException {
  98         writeByte(BEGIN_GRAPH);
  99         if (versionMajor >= 3) {
 100             writeInt(id);
 101             writeString(format);
 102             writeInt(args.length);
 103             for (Object a : args) {
 104                 writePropertyObject(graph, a);
 105             }
 106         } else {
 107             writePoolObject(formatTitle(graph, id, format, args));
 108         }
 109         writeGraph(graph, properties);
 110         flush();
 111     }
 112 
 113     public final void beginGroup(Graph noGraph, String name, String shortName, ResolvedJavaMethod method, int bci, Map<? extends Object, ? extends Object> properties) throws IOException {
 114         writeByte(BEGIN_GROUP);
 115         writePoolObject(name);


 120     }
 121 
 122     public final void endGroup() throws IOException {
 123         writeByte(CLOSE_GROUP);
 124     }
 125 
 126     @Override
 127     public final void close() {
 128         try {
 129             flush();
 130             channel.close();
 131         } catch (IOException ex) {
 132             throw new Error(ex);
 133         }
 134     }
 135 
 136     protected abstract Graph findGraph(Graph current, Object obj);
 137 
 138     protected abstract ResolvedJavaMethod findMethod(Object obj);
 139 
















 140     protected abstract NodeClass findNodeClass(Object obj);
 141 
 142     /**








 143      * Find a Java class. The returned object must be acceptable by
 144      * {@link #findJavaTypeName(java.lang.Object)} and return valid name for the class.
 145      *
 146      * @param clazz node class object
 147      * @return object representing the class, for example {@link Class}
 148      */
 149     protected abstract Object findJavaClass(NodeClass clazz);
 150 
 151     protected abstract Object findEnumClass(Object enumValue);
 152 
 153     protected abstract String findNameTemplate(NodeClass clazz);
 154 
 155     protected abstract Edges findClassEdges(NodeClass nodeClass, boolean dumpInputs);
 156 
 157     protected abstract int findNodeId(Node n);
 158 
 159     protected abstract void findExtraNodes(Node node, Collection<? super Node> extraNodes);
 160 
 161     protected abstract boolean hasPredecessor(Node node);
 162 


 222 
 223     protected abstract NodeSourcePosition findNodeSourcePosition(Object object);
 224 
 225     protected abstract ResolvedJavaMethod findNodeSourcePositionMethod(NodeSourcePosition pos);
 226 
 227     protected abstract NodeSourcePosition findNodeSourcePositionCaller(NodeSourcePosition pos);
 228 
 229     protected abstract int findNodeSourcePositionBCI(NodeSourcePosition pos);
 230 
 231     protected abstract StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
 232 
 233     private void writeVersion() throws IOException {
 234         writeBytesRaw(MAGIC_BYTES);
 235         writeByte(versionMajor);
 236         writeByte(versionMinor);
 237     }
 238 
 239     private void flush() throws IOException {
 240         buffer.flip();
 241         /*
 242          * Try not to let interrupted threads aborting the write. There's still a race here but an
 243          * interrupt that's been pending for a long time shouldn't stop this writing.
 244          */
 245         boolean interrupted = Thread.interrupted();
 246         try {
 247             channel.write(buffer);
 248         } finally {
 249             if (interrupted) {
 250                 Thread.currentThread().interrupt();
 251             }
 252         }
 253         buffer.compact();
 254     }
 255 
 256     private void ensureAvailable(int i) throws IOException {
 257         assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small";
 258         while (buffer.remaining() < i) {
 259             flush();
 260         }
 261     }
 262 


 321             writeInt(b.length);
 322             int sizeInBytes = b.length * 4;
 323             ensureAvailable(sizeInBytes);
 324             buffer.asIntBuffer().put(b);
 325             buffer.position(buffer.position() + sizeInBytes);
 326         }
 327     }
 328 
 329     private void writeDoubles(double[] b) throws IOException {
 330         if (b == null) {
 331             writeInt(-1);
 332         } else {
 333             writeInt(b.length);
 334             int sizeInBytes = b.length * 8;
 335             ensureAvailable(sizeInBytes);
 336             buffer.asDoubleBuffer().put(b);
 337             buffer.position(buffer.position() + sizeInBytes);
 338         }
 339     }
 340 
 341     private void writePoolObject(Object object) throws IOException {

 342         if (object == null) {
 343             writeByte(POOL_NULL);
 344             return;
 345         }
 346         Character id = constantPool.get(object);
 347         if (id == null) {
 348             addPoolEntry(object);
 349         } else {
 350             if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
 351                 writeByte(POOL_ENUM);
 352             } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
 353                 writeByte(POOL_CLASS);
 354             } else if (findJavaField(object) != null) {
 355                 writeByte(POOL_FIELD);
 356             } else if (findSignature(object) != null) {
 357                 writeByte(POOL_SIGNATURE);
 358             } else if (versionMajor >= 4 && findNodeSourcePosition(object) != null) {
 359                 writeByte(POOL_NODE_SOURCE_POSITION);
 360             } else {




 361                 if (findNodeClass(object) != null) {
 362                     writeByte(POOL_NODE_CLASS);


 363                 } else if (findMethod(object) != null) {
 364                     writeByte(POOL_METHOD);
 365                 } else {





 366                     writeByte(POOL_STRING);
 367                 }
 368             }

 369             writeShort(id.charValue());
 370         }
 371     }
 372 
 373     private void writeGraph(Graph graph, Map<? extends Object, ? extends Object> properties) throws IOException {
 374         writeProperties(graph, properties);
 375         writeNodes(graph);
 376         writeBlocks(findBlocks(graph), graph);
 377     }
 378 
 379     private void writeNodes(Graph info) throws IOException {
 380         Map<String, Object> props = new HashMap<>();
 381 
 382         final int size = findNodesCount(info);
 383         writeInt(size);
 384         int cnt = 0;
 385         for (Node node : findNodes(info)) {
 386             NodeClass nodeClass = findNodeClass(node);
 387             if (nodeClass == null) {
 388                 throw new IOException("No class for " + node);
 389             }
 390             findNodeProperties(node, props, info);
 391 
 392             writeInt(findNodeId(node));
 393             writePoolObject(nodeClass);
 394             writeByte(hasPredecessor(node) ? 1 : 0);
 395             writeProperties(info, props);
 396             writeEdges(info, node, true);
 397             writeEdges(info, node, false);
 398 
 399             props.clear();
 400             cnt++;
 401         }
 402         if (size != cnt) {
 403             throw new IOException("Expecting " + size + " nodes, but found " + cnt);
 404         }
 405     }
 406 
 407     private void writeEdges(Graph graph, Node node, boolean dumpInputs) throws IOException {
 408         NodeClass clazz = findNodeClass(node);
 409         Edges edges = findClassEdges(clazz, dumpInputs);
 410         int size = findSize(edges);
 411         for (int i = 0; i < size; i++) {
 412             Collection<? extends Node> list = findNodes(graph, node, edges, i);
 413             if (isDirect(edges, i)) {
 414                 if (list != null && list.size() != 1) {
 415                     throw new IOException("Edge " + i + " in " + edges + " is direct, but list isn't singleton: " + list);
 416                 }
 417                 Node n = null;
 418                 if (list != null && !list.isEmpty()) {
 419                     n = list.iterator().next();
 420                 }
 421                 writeNodeRef(n);
 422             } else {
 423                 if (list == null) {
 424                     writeShort((char) 0);
 425                 } else {
 426                     int listSize = list.size();
 427                     assert listSize == ((char) listSize);
 428                     writeShort((char) listSize);
 429                     for (Node edge : list) {
 430                         writeNodeRef(edge);
 431                     }
 432                 }
 433             }
 434         }
 435     }
 436 








 437     private void writeNodeRef(Node node) throws IOException {
 438         writeInt(findNodeId(node));
 439     }
 440 
 441     private void writeBlocks(Collection<? extends Block> blocks, Graph info) throws IOException {
 442         if (blocks != null) {
 443             for (Block block : blocks) {
 444                 Collection<? extends Node> nodes = findBlockNodes(info, block);
 445                 if (nodes == null) {
 446                     writeInt(0);
 447                     return;
 448                 }
 449             }
 450             writeInt(blocks.size());
 451             for (Block block : blocks) {
 452                 Collection<? extends Node> nodes = findBlockNodes(info, block);
 453                 writeInt(findBlockId(block));
 454                 writeInt(nodes.size());
 455                 for (Node node : nodes) {
 456                     writeInt(findNodeId(node));


 463             }
 464         } else {
 465             writeInt(0);
 466         }
 467     }
 468 
 469     private void writeEdgesInfo(NodeClass nodeClass, boolean dumpInputs) throws IOException {
 470         Edges edges = findClassEdges(nodeClass, dumpInputs);
 471         int size = findSize(edges);
 472         writeShort((char) size);
 473         for (int i = 0; i < size; i++) {
 474             writeByte(isDirect(edges, i) ? 0 : 1);
 475             writePoolObject(findName(edges, i));
 476             if (dumpInputs) {
 477                 writePoolObject(findType(edges, i));
 478             }
 479         }
 480     }
 481 
 482     @SuppressWarnings("all")
 483     private void addPoolEntry(Object object) throws IOException {

 484         ResolvedJavaField field;
 485         String typeName;
 486         Signature signature;
 487         NodeSourcePosition pos;
 488         int enumOrdinal;
 489         char index = constantPool.add(object);
 490         writeByte(POOL_NEW);
 491         writeShort(index);
 492         if ((typeName = findJavaTypeName(object)) != null) {
 493             writeByte(POOL_CLASS);
 494             writeString(typeName);
 495             String[] enumValueNames = findEnumTypeValues(object);
 496             if (enumValueNames != null) {
 497                 writeByte(ENUM_KLASS);
 498                 writeInt(enumValueNames.length);
 499                 for (String o : enumValueNames) {
 500                     writePoolObject(o);
 501                 }
 502             } else {
 503                 writeByte(KLASS);
 504             }
 505         } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
 506             writeByte(POOL_ENUM);
 507             writePoolObject(findEnumClass(object));
 508             writeInt(enumOrdinal);
 509         } else if ((field = findJavaField(object)) != null) {
 510             writeByte(POOL_FIELD);
 511             writePoolObject(findFieldDeclaringClass(field));
 512             writePoolObject(findFieldName(field));
 513             writePoolObject(findFieldTypeName(field));
 514             writeInt(findFieldModifiers(field));
 515         } else if ((signature = findSignature(object)) != null) {
 516             writeByte(POOL_SIGNATURE);
 517             int args = findSignatureParameterCount(signature);
 518             writeShort((char) args);
 519             for (int i = 0; i < args; i++) {
 520                 writePoolObject(findSignatureParameterTypeName(signature, i));
 521             }
 522             writePoolObject(findSignatureReturnTypeName(signature));
 523         } else if (versionMajor >= 4 && (pos = findNodeSourcePosition(object)) != null) {
 524             writeByte(POOL_NODE_SOURCE_POSITION);
 525             ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
 526             writePoolObject(method);
 527             final int bci = findNodeSourcePositionBCI(pos);
 528             writeInt(bci);
 529             StackTraceElement ste = findMethodStackTraceElement(method, bci, pos);
 530             if (ste != null && ste.getFileName() != null) {
 531                 writePoolObject(ste.getFileName());
 532                 writeInt(ste.getLineNumber());
 533             } else {
 534                 writePoolObject(null);
 535             }
 536             writePoolObject(findNodeSourcePositionCaller(pos));
 537         } else {












 538             NodeClass nodeClass = findNodeClass(object);
 539             if (nodeClass != null) {
 540                 writeByte(POOL_NODE_CLASS);
 541                 final Object clazz = findJavaClass(nodeClass);
 542                 if (versionMajor >= 3) {
 543                     writePoolObject(clazz);
 544                     writeString(findNameTemplate(nodeClass));
 545                 } else {
 546                     writeString(((Class<?>) clazz).getSimpleName());
 547                     String nameTemplate = findNameTemplate(nodeClass);
 548                     writeString(nameTemplate);
 549                 }
 550                 writeEdgesInfo(nodeClass, true);
 551                 writeEdgesInfo(nodeClass, false);
 552                 return;
 553             }
 554             ResolvedJavaMethod method = findMethod(object);
 555             if (method == null) {


















 556                 writeByte(POOL_STRING);
 557                 writeString(object.toString());

 558                 return;
 559             }
 560             writeByte(POOL_METHOD);
 561             writePoolObject(findMethodDeclaringClass(method));
 562             writePoolObject(findMethodName(method));
 563             writePoolObject(findMethodSignature(method));
 564             writeInt(findMethodModifiers(method));
 565             writeBytes(findMethodCode(method));
 566         }
 567     }
 568 
 569     private void writePropertyObject(Graph graph, Object obj) throws IOException {
 570         if (obj instanceof Integer) {
 571             writeByte(PROPERTY_INT);
 572             writeInt(((Integer) obj).intValue());
 573         } else if (obj instanceof Long) {
 574             writeByte(PROPERTY_LONG);
 575             writeLong(((Long) obj).longValue());
 576         } else if (obj instanceof Double) {
 577             writeByte(PROPERTY_DOUBLE);




  35 
  36 abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> implements Closeable {
  37     private static final Charset UTF8 = Charset.forName("UTF-8");
  38 
  39     private static final int CONSTANT_POOL_MAX_SIZE = 8000;
  40 
  41     private static final int BEGIN_GROUP = 0x00;
  42     private static final int BEGIN_GRAPH = 0x01;
  43     private static final int CLOSE_GROUP = 0x02;
  44 
  45     private static final int POOL_NEW = 0x00;
  46     private static final int POOL_STRING = 0x01;
  47     private static final int POOL_ENUM = 0x02;
  48     private static final int POOL_CLASS = 0x03;
  49     private static final int POOL_METHOD = 0x04;
  50     private static final int POOL_NULL = 0x05;
  51     private static final int POOL_NODE_CLASS = 0x06;
  52     private static final int POOL_FIELD = 0x07;
  53     private static final int POOL_SIGNATURE = 0x08;
  54     private static final int POOL_NODE_SOURCE_POSITION = 0x09;
  55     private static final int POOL_NODE = 0x0a;
  56 
  57     private static final int PROPERTY_POOL = 0x00;
  58     private static final int PROPERTY_INT = 0x01;
  59     private static final int PROPERTY_LONG = 0x02;
  60     private static final int PROPERTY_DOUBLE = 0x03;
  61     private static final int PROPERTY_FLOAT = 0x04;
  62     private static final int PROPERTY_TRUE = 0x05;
  63     private static final int PROPERTY_FALSE = 0x06;
  64     private static final int PROPERTY_ARRAY = 0x07;
  65     private static final int PROPERTY_SUBGRAPH = 0x08;
  66 
  67     private static final int KLASS = 0x00;
  68     private static final int ENUM_KLASS = 0x01;
  69 
  70     private static final byte[] MAGIC_BYTES = {'B', 'I', 'G', 'V'};
  71 
  72     private final ConstantPool constantPool;
  73     private final ByteBuffer buffer;
  74     private final WritableByteChannel channel;
  75     final int versionMajor;
  76     final int versionMinor;
  77 
  78     GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
  79         if (major > 5 || (major == 5 && minor > 0)) {
  80             throw new IllegalArgumentException("Unrecognized version " + major + "." + minor);







  81         }
  82         this.versionMajor = major;
  83         this.versionMinor = minor;
  84         this.constantPool = new ConstantPool();
  85         this.buffer = ByteBuffer.allocateDirect(256 * 1024);
  86         this.channel = channel;
  87         writeVersion();
  88     }
  89 
  90     GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
  91         this.versionMajor = parent.versionMajor;
  92         this.versionMinor = parent.versionMinor;
  93         this.constantPool = parent.constantPool;
  94         this.buffer = parent.buffer;
  95         this.channel = parent.channel;
  96     }
  97 
  98     @SuppressWarnings("all")
  99     public final void print(Graph graph, Map<? extends Object, ? extends Object> properties, int id, String format, Object... args) throws IOException {
 100         writeByte(BEGIN_GRAPH);
 101         if (versionMajor >= 3) {
 102             writeInt(id);
 103             writeString(format);
 104             writeInt(args.length);
 105             for (Object a : args) {
 106                 writePropertyObject(graph, a);
 107             }
 108         } else {
 109             writePoolObject(formatTitle(graph, id, format, args));
 110         }
 111         writeGraph(graph, properties);
 112         flush();
 113     }
 114 
 115     public final void beginGroup(Graph noGraph, String name, String shortName, ResolvedJavaMethod method, int bci, Map<? extends Object, ? extends Object> properties) throws IOException {
 116         writeByte(BEGIN_GROUP);
 117         writePoolObject(name);


 122     }
 123 
 124     public final void endGroup() throws IOException {
 125         writeByte(CLOSE_GROUP);
 126     }
 127 
 128     @Override
 129     public final void close() {
 130         try {
 131             flush();
 132             channel.close();
 133         } catch (IOException ex) {
 134             throw new Error(ex);
 135         }
 136     }
 137 
 138     protected abstract Graph findGraph(Graph current, Object obj);
 139 
 140     protected abstract ResolvedJavaMethod findMethod(Object obj);
 141 
 142     /**
 143      * Attempts to recognize the provided object as a node. Used to encode it with
 144      * {@link #POOL_NODE} pool type.
 145      * 
 146      * @param obj any object
 147      * @return <code>null</code> if it is not a node object, non-null otherwise
 148      */
 149     protected abstract Node findNode(Object obj);
 150 
 151     /**
 152      * Determines whether the provided object is node class or not.
 153      *
 154      * @param obj object to check
 155      * @return {@code null} if {@code obj} does not represent a NodeClass otherwise the NodeClass
 156      *         represented by {@code obj}
 157      */
 158     protected abstract NodeClass findNodeClass(Object obj);
 159 
 160     /**
 161      * Returns the NodeClass for a given Node {@code obj}.
 162      * 
 163      * @param obj instance of node
 164      * @return non-{@code null} instance of the node's class object
 165      */
 166     protected abstract NodeClass findClassForNode(Node obj);
 167 
 168     /**
 169      * Find a Java class. The returned object must be acceptable by
 170      * {@link #findJavaTypeName(java.lang.Object)} and return valid name for the class.
 171      *
 172      * @param clazz node class object
 173      * @return object representing the class, for example {@link Class}
 174      */
 175     protected abstract Object findJavaClass(NodeClass clazz);
 176 
 177     protected abstract Object findEnumClass(Object enumValue);
 178 
 179     protected abstract String findNameTemplate(NodeClass clazz);
 180 
 181     protected abstract Edges findClassEdges(NodeClass nodeClass, boolean dumpInputs);
 182 
 183     protected abstract int findNodeId(Node n);
 184 
 185     protected abstract void findExtraNodes(Node node, Collection<? super Node> extraNodes);
 186 
 187     protected abstract boolean hasPredecessor(Node node);
 188 


 248 
 249     protected abstract NodeSourcePosition findNodeSourcePosition(Object object);
 250 
 251     protected abstract ResolvedJavaMethod findNodeSourcePositionMethod(NodeSourcePosition pos);
 252 
 253     protected abstract NodeSourcePosition findNodeSourcePositionCaller(NodeSourcePosition pos);
 254 
 255     protected abstract int findNodeSourcePositionBCI(NodeSourcePosition pos);
 256 
 257     protected abstract StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
 258 
 259     private void writeVersion() throws IOException {
 260         writeBytesRaw(MAGIC_BYTES);
 261         writeByte(versionMajor);
 262         writeByte(versionMinor);
 263     }
 264 
 265     private void flush() throws IOException {
 266         buffer.flip();
 267         /*
 268          * Try not to let interrupted threads abort the write. There's still a race here but an
 269          * interrupt that's been pending for a long time shouldn't stop this writing.
 270          */
 271         boolean interrupted = Thread.interrupted();
 272         try {
 273             channel.write(buffer);
 274         } finally {
 275             if (interrupted) {
 276                 Thread.currentThread().interrupt();
 277             }
 278         }
 279         buffer.compact();
 280     }
 281 
 282     private void ensureAvailable(int i) throws IOException {
 283         assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small";
 284         while (buffer.remaining() < i) {
 285             flush();
 286         }
 287     }
 288 


 347             writeInt(b.length);
 348             int sizeInBytes = b.length * 4;
 349             ensureAvailable(sizeInBytes);
 350             buffer.asIntBuffer().put(b);
 351             buffer.position(buffer.position() + sizeInBytes);
 352         }
 353     }
 354 
 355     private void writeDoubles(double[] b) throws IOException {
 356         if (b == null) {
 357             writeInt(-1);
 358         } else {
 359             writeInt(b.length);
 360             int sizeInBytes = b.length * 8;
 361             ensureAvailable(sizeInBytes);
 362             buffer.asDoubleBuffer().put(b);
 363             buffer.position(buffer.position() + sizeInBytes);
 364         }
 365     }
 366 
 367     private void writePoolObject(Object obj) throws IOException {
 368         Object object = obj;
 369         if (object == null) {
 370             writeByte(POOL_NULL);
 371             return;
 372         }
 373         Character id = constantPool.get(object);
 374         if (id == null) {
 375             addPoolEntry(object);
 376         } else {
 377             if (findJavaField(object) != null) {




 378                 writeByte(POOL_FIELD);
 379             } else if (findSignature(object) != null) {
 380                 writeByte(POOL_SIGNATURE);
 381             } else if (versionMajor >= 4 && findNodeSourcePosition(object) != null) {
 382                 writeByte(POOL_NODE_SOURCE_POSITION);
 383             } else {
 384                 final Node node = findNode(object);
 385                 if (versionMajor == 4 && node != null) {
 386                     object = classForNode(node);
 387                 }
 388                 if (findNodeClass(object) != null) {
 389                     writeByte(POOL_NODE_CLASS);
 390                 } else if (versionMajor >= 5 && node != null) {
 391                     writeByte(POOL_NODE);
 392                 } else if (findMethod(object) != null) {
 393                     writeByte(POOL_METHOD);
 394                 } else {
 395                     if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
 396                         writeByte(POOL_ENUM);
 397                     } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
 398                         writeByte(POOL_CLASS);
 399                     } else {
 400                         writeByte(POOL_STRING);
 401                     }
 402                 }
 403             }
 404             writeShort(id.charValue());
 405         }
 406     }
 407 
 408     private void writeGraph(Graph graph, Map<? extends Object, ? extends Object> properties) throws IOException {
 409         writeProperties(graph, properties);
 410         writeNodes(graph);
 411         writeBlocks(findBlocks(graph), graph);
 412     }
 413 
 414     private void writeNodes(Graph info) throws IOException {
 415         Map<String, Object> props = new HashMap<>();
 416 
 417         final int size = findNodesCount(info);
 418         writeInt(size);
 419         int cnt = 0;
 420         for (Node node : findNodes(info)) {
 421             NodeClass nodeClass = classForNode(node);



 422             findNodeProperties(node, props, info);
 423 
 424             writeInt(findNodeId(node));
 425             writePoolObject(nodeClass);
 426             writeByte(hasPredecessor(node) ? 1 : 0);
 427             writeProperties(info, props);
 428             writeEdges(info, node, true);
 429             writeEdges(info, node, false);
 430 
 431             props.clear();
 432             cnt++;
 433         }
 434         if (size != cnt) {
 435             throw new IOException("Expecting " + size + " nodes, but found " + cnt);
 436         }
 437     }
 438 
 439     private void writeEdges(Graph graph, Node node, boolean dumpInputs) throws IOException {
 440         NodeClass clazz = classForNode(node);
 441         Edges edges = findClassEdges(clazz, dumpInputs);
 442         int size = findSize(edges);
 443         for (int i = 0; i < size; i++) {
 444             Collection<? extends Node> list = findNodes(graph, node, edges, i);
 445             if (isDirect(edges, i)) {
 446                 if (list != null && list.size() != 1) {
 447                     throw new IOException("Edge " + i + " in " + edges + " is direct, but list isn't singleton: " + list);
 448                 }
 449                 Node n = null;
 450                 if (list != null && !list.isEmpty()) {
 451                     n = list.iterator().next();
 452                 }
 453                 writeNodeRef(n);
 454             } else {
 455                 if (list == null) {
 456                     writeShort((char) 0);
 457                 } else {
 458                     int listSize = list.size();
 459                     assert listSize == ((char) listSize);
 460                     writeShort((char) listSize);
 461                     for (Node edge : list) {
 462                         writeNodeRef(edge);
 463                     }
 464                 }
 465             }
 466         }
 467     }
 468 
 469     private NodeClass classForNode(Node node) throws IOException {
 470         NodeClass clazz = findClassForNode(node);
 471         if (clazz == null) {
 472             throw new IOException("No class for " + node);
 473         }
 474         return clazz;
 475     }
 476 
 477     private void writeNodeRef(Node node) throws IOException {
 478         writeInt(findNodeId(node));
 479     }
 480 
 481     private void writeBlocks(Collection<? extends Block> blocks, Graph info) throws IOException {
 482         if (blocks != null) {
 483             for (Block block : blocks) {
 484                 Collection<? extends Node> nodes = findBlockNodes(info, block);
 485                 if (nodes == null) {
 486                     writeInt(0);
 487                     return;
 488                 }
 489             }
 490             writeInt(blocks.size());
 491             for (Block block : blocks) {
 492                 Collection<? extends Node> nodes = findBlockNodes(info, block);
 493                 writeInt(findBlockId(block));
 494                 writeInt(nodes.size());
 495                 for (Node node : nodes) {
 496                     writeInt(findNodeId(node));


 503             }
 504         } else {
 505             writeInt(0);
 506         }
 507     }
 508 
 509     private void writeEdgesInfo(NodeClass nodeClass, boolean dumpInputs) throws IOException {
 510         Edges edges = findClassEdges(nodeClass, dumpInputs);
 511         int size = findSize(edges);
 512         writeShort((char) size);
 513         for (int i = 0; i < size; i++) {
 514             writeByte(isDirect(edges, i) ? 0 : 1);
 515             writePoolObject(findName(edges, i));
 516             if (dumpInputs) {
 517                 writePoolObject(findType(edges, i));
 518             }
 519         }
 520     }
 521 
 522     @SuppressWarnings("all")
 523     private void addPoolEntry(Object obj) throws IOException {
 524         Object object = obj;
 525         ResolvedJavaField field;
 526         String typeName;
 527         Signature signature;
 528         NodeSourcePosition pos;
 529         int enumOrdinal;
 530         char index = constantPool.add(object);
 531         writeByte(POOL_NEW);
 532         writeShort(index);
 533         if ((field = findJavaField(object)) != null) {

















 534             writeByte(POOL_FIELD);
 535             writePoolObject(findFieldDeclaringClass(field));
 536             writePoolObject(findFieldName(field));
 537             writePoolObject(findFieldTypeName(field));
 538             writeInt(findFieldModifiers(field));
 539         } else if ((signature = findSignature(object)) != null) {
 540             writeByte(POOL_SIGNATURE);
 541             int args = findSignatureParameterCount(signature);
 542             writeShort((char) args);
 543             for (int i = 0; i < args; i++) {
 544                 writePoolObject(findSignatureParameterTypeName(signature, i));
 545             }
 546             writePoolObject(findSignatureReturnTypeName(signature));
 547         } else if (versionMajor >= 4 && (pos = findNodeSourcePosition(object)) != null) {
 548             writeByte(POOL_NODE_SOURCE_POSITION);
 549             ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
 550             writePoolObject(method);
 551             final int bci = findNodeSourcePositionBCI(pos);
 552             writeInt(bci);
 553             StackTraceElement ste = findMethodStackTraceElement(method, bci, pos);
 554             if (ste != null && ste.getFileName() != null) {
 555                 writePoolObject(ste.getFileName());
 556                 writeInt(ste.getLineNumber());
 557             } else {
 558                 writePoolObject(null);
 559             }
 560             writePoolObject(findNodeSourcePositionCaller(pos));
 561         } else {
 562             Node node = findNode(object);
 563             if (node != null) {
 564                 if (versionMajor >= 5) {
 565                     writeByte(POOL_NODE);
 566                     writeInt(findNodeId(node));
 567                     writePoolObject(classForNode(node));
 568                     return;
 569                 }
 570                 if (versionMajor == 4) {
 571                     object = classForNode(node);
 572                 }
 573             }
 574             NodeClass nodeClass = findNodeClass(object);
 575             if (nodeClass != null) {
 576                 writeByte(POOL_NODE_CLASS);
 577                 final Object clazz = findJavaClass(nodeClass);
 578                 if (versionMajor >= 3) {
 579                     writePoolObject(clazz);
 580                     writeString(findNameTemplate(nodeClass));
 581                 } else {
 582                     writeString(((Class<?>) clazz).getSimpleName());
 583                     String nameTemplate = findNameTemplate(nodeClass);
 584                     writeString(nameTemplate);
 585                 }
 586                 writeEdgesInfo(nodeClass, true);
 587                 writeEdgesInfo(nodeClass, false);
 588                 return;
 589             }
 590             ResolvedJavaMethod method = findMethod(object);
 591             if (method == null) {
 592                 if ((typeName = findJavaTypeName(object)) != null) {
 593                     writeByte(POOL_CLASS);
 594                     writeString(typeName);
 595                     String[] enumValueNames = findEnumTypeValues(object);
 596                     if (enumValueNames != null) {
 597                         writeByte(ENUM_KLASS);
 598                         writeInt(enumValueNames.length);
 599                         for (String o : enumValueNames) {
 600                             writePoolObject(o);
 601                         }
 602                     } else {
 603                         writeByte(KLASS);
 604                     }
 605                 } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
 606                     writeByte(POOL_ENUM);
 607                     writePoolObject(findEnumClass(object));
 608                     writeInt(enumOrdinal);
 609                 } else {
 610                     writeByte(POOL_STRING);
 611                     writeString(object.toString());
 612                 }
 613                 return;
 614             }
 615             writeByte(POOL_METHOD);
 616             writePoolObject(findMethodDeclaringClass(method));
 617             writePoolObject(findMethodName(method));
 618             writePoolObject(findMethodSignature(method));
 619             writeInt(findMethodModifiers(method));
 620             writeBytes(findMethodCode(method));
 621         }
 622     }
 623 
 624     private void writePropertyObject(Graph graph, Object obj) throws IOException {
 625         if (obj instanceof Integer) {
 626             writeByte(PROPERTY_INT);
 627             writeInt(((Integer) obj).intValue());
 628         } else if (obj instanceof Long) {
 629             writeByte(PROPERTY_LONG);
 630             writeLong(((Long) obj).longValue());
 631         } else if (obj instanceof Double) {
 632             writeByte(PROPERTY_DOUBLE);


< prev index next >