1 /* 2 * Copyright (c) 2009, 2011, 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 package org.graalvm.compiler.core.common.util; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; 26 27 import java.util.Collection; 28 import java.util.List; 29 30 import org.graalvm.compiler.debug.TTY; 31 32 import jdk.vm.ci.meta.JavaConstant; 33 import jdk.vm.ci.meta.JavaKind; 34 import jdk.vm.ci.meta.ResolvedJavaMethod; 35 36 /** 37 * The {@code Util} class contains a motley collection of utility methods used throughout the 38 * compiler. 39 */ 40 public class Util { 41 42 private static int getJavaSpecificationVersion() { 43 String value = System.getProperty("java.specification.version"); 44 if (value.startsWith("1.")) { 45 value = value.substring(2); 46 } 47 return Integer.parseInt(value); 48 } 49 50 /** 51 * The integer value corresponding to the value of the {@code java.specification.version} system 52 * property after any leading {@code "1."} has been stripped. 53 */ 54 public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion(); 55 56 /** 57 * Determines if the Java runtime is version 8 or earlier. 58 */ 59 public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8; 60 61 /** 62 * Statically cast an object to an arbitrary Object type. Dynamically checked. 63 */ 64 @SuppressWarnings("unchecked") 65 public static <T> T uncheckedCast(@SuppressWarnings("unused") Class<T> type, Object object) { 66 return (T) object; 67 } 68 69 /** 70 * Statically cast an object to an arbitrary Object type. Dynamically checked. 71 */ 72 @SuppressWarnings("unchecked") 73 public static <T> T uncheckedCast(Object object) { 74 return (T) object; 75 } 76 77 public interface Stringify { 78 String apply(Object o); 79 } 80 81 public static String join(Collection<?> c, String sep) { 82 return join(c, sep, "", "", null); 83 } 84 85 public static String join(Collection<?> c, String sep, String prefix, String suffix, Stringify stringify) { 86 StringBuilder buf = new StringBuilder(prefix); 87 boolean first = true; 88 for (Object e : c) { 89 if (!first) { 90 buf.append(sep); 91 } else { 92 first = false; 93 } 94 buf.append(stringify != null ? stringify.apply(e) : String.valueOf(e)); 95 } 96 buf.append(suffix); 97 return buf.toString(); 98 } 99 100 /** 101 * Sets the element at a given position of a list and ensures that this position exists. If the 102 * list is current shorter than the position, intermediate positions are filled with a given 103 * value. 104 * 105 * @param list the list to put the element into 106 * @param pos the position at which to insert the element 107 * @param x the element that should be inserted 108 * @param filler the filler element that is used for the intermediate positions in case the list 109 * is shorter than pos 110 */ 111 public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) { 112 if (list.size() < pos + 1) { 113 while (list.size() < pos + 1) { 114 list.add(filler); 115 } 116 assert list.size() == pos + 1; 117 } 118 119 assert list.size() >= pos + 1; 120 list.set(pos, x); 121 } 122 123 /** 124 * Prepends the String {@code indentation} to every line in String {@code lines}, including a 125 * possibly non-empty line following the final newline. 126 */ 127 public static String indent(String lines, String indentation) { 128 if (lines.length() == 0) { 129 return lines; 130 } 131 final String newLine = "\n"; 132 if (lines.endsWith(newLine)) { 133 return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine; 134 } 135 return indentation + lines.replace(newLine, newLine + indentation); 136 } 137 138 /** 139 * Returns the zero value for a given numeric kind. 140 */ 141 public static JavaConstant zero(JavaKind kind) { 142 switch (kind) { 143 case Boolean: 144 return JavaConstant.FALSE; 145 case Byte: 146 return JavaConstant.forByte((byte) 0); 147 case Char: 148 return JavaConstant.forChar((char) 0); 149 case Double: 150 return JavaConstant.DOUBLE_0; 151 case Float: 152 return JavaConstant.FLOAT_0; 153 case Int: 154 return JavaConstant.INT_0; 155 case Long: 156 return JavaConstant.LONG_0; 157 case Short: 158 return JavaConstant.forShort((short) 0); 159 default: 160 throw new IllegalArgumentException(kind.toString()); 161 } 162 } 163 164 /** 165 * Returns the one value for a given numeric kind. 166 */ 167 public static JavaConstant one(JavaKind kind) { 168 switch (kind) { 169 case Boolean: 170 return JavaConstant.TRUE; 171 case Byte: 172 return JavaConstant.forByte((byte) 1); 173 case Char: 174 return JavaConstant.forChar((char) 1); 175 case Double: 176 return JavaConstant.DOUBLE_1; 177 case Float: 178 return JavaConstant.FLOAT_1; 179 case Int: 180 return JavaConstant.INT_1; 181 case Long: 182 return JavaConstant.LONG_1; 183 case Short: 184 return JavaConstant.forShort((short) 1); 185 default: 186 throw new IllegalArgumentException(kind.toString()); 187 } 188 } 189 190 /** 191 * Print a HotSpot-style inlining message to the console. 192 */ 193 public static void printInlining(final ResolvedJavaMethod method, final int bci, final int inliningDepth, final boolean success, final String msg, final Object... args) { 194 if (HotSpotPrintInlining.getValue()) { 195 StringBuilder sb = new StringBuilder(); 196 // 1234567 197 sb.append(" "); // print timestamp 198 // 1234 199 sb.append(" "); // print compilation number 200 // % s ! b n 201 sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); 202 sb.append(" "); // more indent 203 sb.append(" "); // initial inlining indent 204 for (int i = 0; i < inliningDepth; i++) { 205 sb.append(" "); 206 } 207 sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); 208 TTY.println(sb.toString()); 209 } 210 } 211 212 private static String methodName(ResolvedJavaMethod method) { 213 return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; 214 } 215 }