Mercurial > hg > graal-jvmci-8
comparison jvmci/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java @ 23393:1d4ce2d19e52
clean up and minimize JVMCI (JDK-8156835)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 12 May 2016 20:57:31 +0200 |
parents | 1bbd4a7c274b |
children | d6bd0b9cd0b6 |
comparison
equal
deleted
inserted
replaced
23392:b3a816d3b844 | 23393:1d4ce2d19e52 |
---|---|
20 * or visit www.oracle.com if you need additional information or have any | 20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. | 21 * questions. |
22 */ | 22 */ |
23 package jdk.vm.ci.meta; | 23 package jdk.vm.ci.meta; |
24 | 24 |
25 import java.io.PrintStream; | |
26 import java.lang.reflect.Field; | 25 import java.lang.reflect.Field; |
27 import java.lang.reflect.Modifier; | 26 import java.lang.reflect.Modifier; |
28 import java.util.ArrayDeque; | |
29 import java.util.ArrayList; | |
30 import java.util.Collections; | |
31 import java.util.Comparator; | |
32 import java.util.Deque; | |
33 import java.util.HashMap; | |
34 import java.util.HashSet; | |
35 import java.util.Set; | |
36 | 27 |
37 /** | 28 /** |
38 * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. | 29 * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. |
39 */ | 30 */ |
40 public class MetaUtil { | 31 public class MetaUtil { |
41 | |
42 private static class ClassInfo { | |
43 public long totalSize; | |
44 public long instanceCount; | |
45 | |
46 @Override | |
47 public String toString() { | |
48 return "totalSize=" + totalSize + ", instanceCount=" + instanceCount; | |
49 } | |
50 } | |
51 | |
52 /** | |
53 * Returns the number of bytes occupied by this constant value or constant object and | |
54 * recursively all values reachable from this value. | |
55 * | |
56 * @param constant the constant whose bytes should be measured | |
57 * @param printTopN print total size and instance count of the top n classes is desired | |
58 * @return the number of bytes occupied by this constant | |
59 */ | |
60 public static long getMemorySizeRecursive(MetaAccessProvider access, ConstantReflectionProvider constantReflection, JavaConstant constant, PrintStream out, int printTopN) { | |
61 Set<JavaConstant> marked = new HashSet<>(); | |
62 Deque<JavaConstant> stack = new ArrayDeque<>(); | |
63 if (constant.getJavaKind() == JavaKind.Object && constant.isNonNull()) { | |
64 marked.add(constant); | |
65 } | |
66 final HashMap<ResolvedJavaType, ClassInfo> histogram = new HashMap<>(); | |
67 stack.push(constant); | |
68 long sum = 0; | |
69 while (!stack.isEmpty()) { | |
70 JavaConstant c = stack.pop(); | |
71 long memorySize = access.getMemorySize(constant); | |
72 sum += memorySize; | |
73 if (c.getJavaKind() == JavaKind.Object && c.isNonNull()) { | |
74 ResolvedJavaType clazz = access.lookupJavaType(c); | |
75 if (!histogram.containsKey(clazz)) { | |
76 histogram.put(clazz, new ClassInfo()); | |
77 } | |
78 ClassInfo info = histogram.get(clazz); | |
79 info.instanceCount++; | |
80 info.totalSize += memorySize; | |
81 ResolvedJavaType type = access.lookupJavaType(c); | |
82 if (type.isArray()) { | |
83 if (!type.getComponentType().isPrimitive()) { | |
84 int length = constantReflection.readArrayLength(c); | |
85 for (int i = 0; i < length; i++) { | |
86 JavaConstant value = constantReflection.readArrayElement(c, i); | |
87 pushConstant(marked, stack, value); | |
88 } | |
89 } | |
90 } else { | |
91 ResolvedJavaField[] instanceFields = type.getInstanceFields(true); | |
92 for (ResolvedJavaField f : instanceFields) { | |
93 if (f.getJavaKind() == JavaKind.Object) { | |
94 JavaConstant value = constantReflection.readFieldValue(f, c); | |
95 pushConstant(marked, stack, value); | |
96 } | |
97 } | |
98 } | |
99 } | |
100 } | |
101 ArrayList<ResolvedJavaType> clazzes = new ArrayList<>(); | |
102 clazzes.addAll(histogram.keySet()); | |
103 Collections.sort(clazzes, new Comparator<ResolvedJavaType>() { | |
104 | |
105 @Override | |
106 public int compare(ResolvedJavaType o1, ResolvedJavaType o2) { | |
107 long l1 = histogram.get(o1).totalSize; | |
108 long l2 = histogram.get(o2).totalSize; | |
109 if (l1 > l2) { | |
110 return -1; | |
111 } else if (l1 == l2) { | |
112 return 0; | |
113 } else { | |
114 return 1; | |
115 } | |
116 } | |
117 }); | |
118 | |
119 int z = 0; | |
120 for (ResolvedJavaType c : clazzes) { | |
121 if (z > printTopN) { | |
122 break; | |
123 } | |
124 out.println("Class " + c + ", " + histogram.get(c)); | |
125 ++z; | |
126 } | |
127 | |
128 return sum; | |
129 } | |
130 | |
131 private static void pushConstant(Set<JavaConstant> marked, Deque<JavaConstant> stack, JavaConstant value) { | |
132 if (value.isNonNull()) { | |
133 if (!marked.contains(value)) { | |
134 marked.add(value); | |
135 stack.push(value); | |
136 } | |
137 } | |
138 } | |
139 | |
140 /** | |
141 * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types. | |
142 */ | |
143 public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) { | |
144 ResolvedJavaType[] result = new ResolvedJavaType[types.length]; | |
145 for (int i = 0; i < result.length; i++) { | |
146 result[i] = types[i].resolve(accessingClass); | |
147 } | |
148 return result; | |
149 } | |
150 | 32 |
151 /** | 33 /** |
152 * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for | 34 * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for |
153 * anonymous and local classes. | 35 * anonymous and local classes. |
154 * | 36 * |
182 return name; | 64 return name; |
183 } | 65 } |
184 return name.substring(index + 1); | 66 return name.substring(index + 1); |
185 } | 67 } |
186 | 68 |
187 static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { | 69 /** |
70 * Converts a type name in internal form to an external form. | |
71 * | |
72 * @param name the internal name to convert | |
73 * @param qualified whether the returned name should be qualified with the package name | |
74 * @param classForNameCompatible specifies if the returned name for array types should be in | |
75 * {@link Class#forName(String)} format (e.g., {@code "[Ljava.lang.Object;"}, | |
76 * {@code "[[I"}) or in Java source code format (e.g., {@code "java.lang.Object[]"}, | |
77 * {@code "int[][]"} ). | |
78 */ | |
79 public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { | |
188 switch (name.charAt(0)) { | 80 switch (name.charAt(0)) { |
189 case 'L': { | 81 case 'L': { |
190 String result = name.substring(1, name.length() - 1).replace('/', '.'); | 82 String result = name.substring(1, name.length() - 1).replace('/', '.'); |
191 if (!qualified) { | 83 if (!qualified) { |
192 final int lastDot = result.lastIndexOf('.'); | 84 final int lastDot = result.lastIndexOf('.'); |
205 return JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)).getJavaName(); | 97 return JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)).getJavaName(); |
206 } | 98 } |
207 } | 99 } |
208 | 100 |
209 /** | 101 /** |
210 * Turns an class name in internal format into a resolved Java type. | |
211 */ | |
212 public static ResolvedJavaType classForName(String internal, MetaAccessProvider metaAccess, ClassLoader cl) { | |
213 JavaKind k = JavaKind.fromTypeString(internal); | |
214 try { | |
215 String n = internalNameToJava(internal, true, true); | |
216 return metaAccess.lookupJavaType(k.isPrimitive() ? k.toJavaClass() : Class.forName(n, true, cl)); | |
217 } catch (ClassNotFoundException cnfe) { | |
218 throw new IllegalArgumentException("could not instantiate class described by " + internal, cnfe); | |
219 } | |
220 } | |
221 | |
222 /** | |
223 * Convenient shortcut for calling | 102 * Convenient shortcut for calling |
224 * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a | 103 * {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a |
225 * {@link StringBuilder} instance and convert the result to a string. | 104 * {@link StringBuilder} instance and convert the result to a string. |
226 */ | 105 */ |
227 public static String toLocation(ResolvedJavaMethod method, int bci) { | 106 public static String toLocation(ResolvedJavaMethod method, int bci) { |
335 } | 214 } |
336 return result.toString(); | 215 return result.toString(); |
337 } | 216 } |
338 | 217 |
339 /** | 218 /** |
340 * Prepends the String {@code indentation} to every line in String {@code lines}, including a | |
341 * possibly non-empty line following the final newline. | |
342 */ | |
343 public static String indent(String lines, String indentation) { | |
344 if (lines.length() == 0) { | |
345 return lines; | |
346 } | |
347 final String newLine = "\n"; | |
348 if (lines.endsWith(newLine)) { | |
349 return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine; | |
350 } | |
351 return indentation + lines.replace(newLine, newLine + indentation); | |
352 } | |
353 | |
354 /** | |
355 * Gets a string representation of an object based soley on its class and its | 219 * Gets a string representation of an object based soley on its class and its |
356 * {@linkplain System#identityHashCode(Object) identity hash code}. This avoids and calls to | 220 * {@linkplain System#identityHashCode(Object) identity hash code}. This avoids and calls to |
357 * virtual methods on the object such as {@link Object#hashCode()}. | 221 * virtual methods on the object such as {@link Object#hashCode()}. |
358 */ | 222 */ |
359 public static String identityHashCodeString(Object obj) { | 223 public static String identityHashCodeString(Object obj) { |