src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java
changeset 54409 94986cf5e969
parent 54408 8fe16bf92ebd
parent 54373 13935056b05e
child 54410 7feb5e303c83
equal deleted inserted replaced
54408:8fe16bf92ebd 54409:94986cf5e969
     1 /*
       
     2  * Copyright (c) 2016, 2018, 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 
       
    25 package org.graalvm.compiler.hotspot;
       
    26 
       
    27 import java.io.File;
       
    28 import java.io.IOException;
       
    29 import java.net.URI;
       
    30 import java.net.URL;
       
    31 import java.net.URLClassLoader;
       
    32 import java.nio.file.FileSystem;
       
    33 import java.nio.file.FileSystems;
       
    34 import java.nio.file.FileVisitResult;
       
    35 import java.nio.file.Files;
       
    36 import java.nio.file.Path;
       
    37 import java.nio.file.SimpleFileVisitor;
       
    38 import java.nio.file.attribute.BasicFileAttributes;
       
    39 import java.util.ArrayList;
       
    40 import java.util.Arrays;
       
    41 import java.util.Collections;
       
    42 import java.util.HashSet;
       
    43 import java.util.List;
       
    44 import java.util.Set;
       
    45 import java.util.regex.Pattern;
       
    46 import java.util.regex.PatternSyntaxException;
       
    47 import java.util.stream.Collectors;
       
    48 
       
    49 import org.graalvm.compiler.debug.CSVUtil;
       
    50 import org.graalvm.compiler.debug.GraalError;
       
    51 import org.graalvm.compiler.graph.Node;
       
    52 import org.graalvm.compiler.graph.NodeClass;
       
    53 import org.graalvm.compiler.graph.spi.Canonicalizable;
       
    54 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
       
    55 import org.graalvm.compiler.nodes.spi.Virtualizable;
       
    56 
       
    57 public class NodeCostDumpUtil {
       
    58 
       
    59     private static final String prefix1 = "com.oracle.";
       
    60     private static final String prefix2 = "org.graalvm.";
       
    61     private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s");
       
    62 
       
    63     private static String getArgumentRegex(String arg) {
       
    64         if (arg.length() == 0) {
       
    65             return null;
       
    66         }
       
    67         try {
       
    68             Pattern.compile(arg);
       
    69             return arg;
       
    70         } catch (PatternSyntaxException e) {
       
    71             // silently ignore
       
    72             System.err.println("Invalid regex given, defaulting to \".*\" regex..");
       
    73             return null;
       
    74         }
       
    75     }
       
    76 
       
    77     public static void main(String[] args) {
       
    78         if (args.length != 1) {
       
    79             System.err.println("NodeCostDumpUtil expects exactly one argument, the node name regex to match against.");
       
    80             System.exit(-1);
       
    81         }
       
    82         final String pattern = getArgumentRegex(args[0]);
       
    83         String version = System.getProperty("java.specification.version");
       
    84         if (version.compareTo("1.9") >= 0) {
       
    85             System.err.printf("NodeCostDumpUtil does not support JDK versions greater than 1.8, current version is %s.\n", version);
       
    86             System.exit(-1);
       
    87         }
       
    88         String[] jvmciCP = System.getProperty("jvmci.class.path.append").split(File.pathSeparator);
       
    89         String[] primarySuiteCP = System.getProperty("primary.suite.cp").split(File.pathSeparator);
       
    90         ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader();
       
    91         HashSet<Class<?>> classes = new HashSet<>();
       
    92         try {
       
    93             Set<String> uniquePaths = new HashSet<>(Arrays.asList(primarySuiteCP));
       
    94             uniquePaths.addAll(Arrays.asList(jvmciCP));
       
    95             for (String path : uniquePaths) {
       
    96                 if (new File(path).exists()) {
       
    97                     if (path.endsWith(".jar")) {
       
    98                         try (FileSystem jarFileSystem = FileSystems.newFileSystem(URI.create("jar:file:" + path), Collections.emptyMap())) {
       
    99                             initAllClasses(jarFileSystem.getPath("/"), applicationClassLoader, classes);
       
   100                         }
       
   101                     } else {
       
   102                         initAllClasses(FileSystems.getDefault().getPath(path), applicationClassLoader, classes);
       
   103                     }
       
   104                 }
       
   105             }
       
   106         } catch (IOException ex) {
       
   107             GraalError.shouldNotReachHere();
       
   108         }
       
   109         System.err.printf("Loaded %d classes...\n", classes.size());
       
   110         List<Class<?>> nodeClasses = new ArrayList<>();
       
   111         for (Class<?> loaded : classes) {
       
   112             if (Node.class.isAssignableFrom(loaded) && !loaded.isArray()) {
       
   113                 nodeClasses.add(loaded);
       
   114             }
       
   115         }
       
   116         System.err.printf("Loaded %s node classes...\n", nodeClasses.size());
       
   117         List<NodeClass<?>> nc = new ArrayList<>();
       
   118         for (Class<?> c : nodeClasses) {
       
   119             try {
       
   120                 nc.add(NodeClass.get(c));
       
   121             } catch (Throwable t) {
       
   122                 // Silently ignore problems here
       
   123             }
       
   124         }
       
   125         System.err.printf("Read TYPE field from %s node classes...\n", nc.size());
       
   126         nc = nc.stream().filter(x -> x != null).collect(Collectors.toList());
       
   127         nc.sort((x, y) -> {
       
   128             String a = x.getJavaClass().getName();
       
   129             String b = y.getJavaClass().getName();
       
   130             return a.compareTo(b);
       
   131         });
       
   132         CSVUtil.Escape.println(System.out, FMT, "NodeName", "Size", "Overrides Size Method", "Cycles", "Overrides Cycles Method", "Canonicalizable", "MemoryCheckPoint", "Virtualizable");
       
   133         for (NodeClass<?> nodeclass : nc) {
       
   134             String packageStrippedName = null;
       
   135             try {
       
   136                 packageStrippedName = nodeclass.getJavaClass().getCanonicalName().replace(prefix1, "").replace(prefix2, "");
       
   137             } catch (Throwable t) {
       
   138                 // do nothing
       
   139                 continue;
       
   140             }
       
   141             if (pattern != null && !packageStrippedName.matches(pattern)) {
       
   142                 continue;
       
   143             }
       
   144             boolean overridesSizeMethod = false;
       
   145             boolean overridesCyclesMethod = false;
       
   146             Class<?> c = nodeclass.getJavaClass();
       
   147             try {
       
   148                 c.getDeclaredMethod("estimatedNodeSize");
       
   149                 overridesSizeMethod = true;
       
   150             } catch (Throwable t) {
       
   151                 // do nothing
       
   152             }
       
   153             try {
       
   154                 c.getDeclaredMethod("estimatedNodeCycles");
       
   155                 overridesCyclesMethod = true;
       
   156             } catch (Throwable t) {
       
   157                 // do nothing
       
   158             }
       
   159             CSVUtil.Escape.println(System.out, FMT, packageStrippedName, nodeclass.size(), overridesSizeMethod, nodeclass.cycles(), overridesCyclesMethod, canonicalizable(c), memoryCheckPoint(c),
       
   160                             virtualizable(c));
       
   161         }
       
   162     }
       
   163 
       
   164     private static boolean canonicalizable(Class<?> c) {
       
   165         return Canonicalizable.class.isAssignableFrom(c);
       
   166     }
       
   167 
       
   168     private static boolean virtualizable(Class<?> c) {
       
   169         return Virtualizable.class.isAssignableFrom(c);
       
   170     }
       
   171 
       
   172     private static boolean memoryCheckPoint(Class<?> c) {
       
   173         return MemoryCheckpoint.class.isAssignableFrom(c);
       
   174     }
       
   175 
       
   176     private static void initAllClasses(final Path root, ClassLoader classLoader, HashSet<Class<?>> classes) {
       
   177         try {
       
   178             Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
       
   179                 @Override
       
   180                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
       
   181                     String className = root.relativize(file).toString();
       
   182                     ClassLoader c = classLoader;
       
   183                     if (className.endsWith(".class")) {
       
   184                         String prefix = prefixed(className);
       
   185                         if (prefix != null) {
       
   186                             String stripped = stripClassName(className);
       
   187                             c = new URLClassLoader(new URL[]{new File(constructURLPart(stripped, className, prefix)).toURI().toURL()}, classLoader);
       
   188                             className = constructClazzPart(stripped, prefix);
       
   189                         } else {
       
   190                             String clazzPart = className.replace('/', '.');
       
   191                             className = clazzPart.substring(0, clazzPart.length() - ".class".length());
       
   192                         }
       
   193                         try {
       
   194                             Class<?> systemClass = Class.forName(className, false, c);
       
   195                             if (systemClass.getEnclosingClass() != null) {
       
   196                                 try {
       
   197                                     classes.add(systemClass.getEnclosingClass());
       
   198                                 } catch (Throwable t) {
       
   199                                     // do nothing
       
   200                                 }
       
   201                             }
       
   202                             classes.add(systemClass);
       
   203                         } catch (Throwable ignored) {
       
   204                         }
       
   205                     }
       
   206                     return FileVisitResult.CONTINUE;
       
   207                 }
       
   208             });
       
   209         } catch (IOException ex) {
       
   210             GraalError.shouldNotReachHere();
       
   211         }
       
   212     }
       
   213 
       
   214     private static String prefixed(String className) {
       
   215         if (className.contains(prefix1) && className.indexOf(prefix1) > 0) {
       
   216             return prefix1;
       
   217         } else if (className.contains(prefix2) && className.indexOf(prefix2) > 0) {
       
   218             return prefix2;
       
   219         }
       
   220         return null;
       
   221     }
       
   222 
       
   223     private static String stripClassName(String className) {
       
   224         return className.replace('/', '.');
       
   225     }
       
   226 
       
   227     private static String constructClazzPart(String stripped, String prefix) {
       
   228         String clazzPart = stripped.substring(stripped.lastIndexOf(prefix), stripped.length());
       
   229         return clazzPart.substring(0, clazzPart.length() - ".class".length());
       
   230     }
       
   231 
       
   232     private static String constructURLPart(String stripped, String className, String prefix) {
       
   233         return className.substring(0, stripped.lastIndexOf(prefix));
       
   234     }
       
   235 
       
   236 }