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 java.lang.reflect.AccessibleObject; 26 import java.lang.reflect.Executable; 27 import java.lang.reflect.Field; 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 /** 78 * Sets the element at a given position of a list and ensures that this position exists. If the 79 * list is current shorter than the position, intermediate positions are filled with a given 80 * value. 81 * 82 * @param list the list to put the element into 83 * @param pos the position at which to insert the element 84 * @param x the element that should be inserted 85 * @param filler the filler element that is used for the intermediate positions in case the list 86 * is shorter than pos 87 */ 88 public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) { 89 if (list.size() < pos + 1) { 90 while (list.size() < pos + 1) { 91 list.add(filler); 92 } 93 assert list.size() == pos + 1; 94 } 95 96 assert list.size() >= pos + 1; 97 list.set(pos, x); 98 } 99 100 /** 101 * Prepends the String {@code indentation} to every line in String {@code lines}, including a 102 * possibly non-empty line following the final newline. 103 */ 104 public static String indent(String lines, String indentation) { 105 if (lines.length() == 0) { 106 return lines; 107 } 108 final String newLine = "\n"; 109 if (lines.endsWith(newLine)) { 110 return indentation + (lines.substring(0, lines.length() - 1)).replace(newLine, newLine + indentation) + newLine; 111 } 112 return indentation + lines.replace(newLine, newLine + indentation); 113 } 114 115 /** 116 * Returns the zero value for a given numeric kind. 117 */ 118 public static JavaConstant zero(JavaKind kind) { 119 switch (kind) { 120 case Boolean: 121 return JavaConstant.FALSE; 122 case Byte: 123 return JavaConstant.forByte((byte) 0); 124 case Char: 125 return JavaConstant.forChar((char) 0); 126 case Double: 127 return JavaConstant.DOUBLE_0; 128 case Float: 129 return JavaConstant.FLOAT_0; 130 case Int: 131 return JavaConstant.INT_0; 132 case Long: 133 return JavaConstant.LONG_0; 134 case Short: 135 return JavaConstant.forShort((short) 0); 136 default: 137 throw new IllegalArgumentException(kind.toString()); 138 } 139 } 140 141 /** 142 * Returns the one value for a given numeric kind. 143 */ 144 public static JavaConstant one(JavaKind kind) { 145 switch (kind) { 146 case Boolean: 147 return JavaConstant.TRUE; 148 case Byte: 149 return JavaConstant.forByte((byte) 1); 150 case Char: 151 return JavaConstant.forChar((char) 1); 152 case Double: 153 return JavaConstant.DOUBLE_1; 154 case Float: 155 return JavaConstant.FLOAT_1; 156 case Int: 157 return JavaConstant.INT_1; 158 case Long: 159 return JavaConstant.LONG_1; 160 case Short: 161 return JavaConstant.forShort((short) 1); 162 default: 163 throw new IllegalArgumentException(kind.toString()); 164 } 165 } 166 167 /** 168 * Print a HotSpot-style inlining message to the console. 169 */ 170 public static void printInlining(final ResolvedJavaMethod method, final int bci, final int inliningDepth, final boolean success, final String msg, final Object... args) { 171 StringBuilder sb = new StringBuilder(); 172 // 1234567 173 sb.append(" "); // print timestamp 174 // 1234 175 sb.append(" "); // print compilation number 176 // % s ! b n 177 sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); 178 sb.append(" "); // more indent 179 sb.append(" "); // initial inlining indent 180 for (int i = 0; i < inliningDepth; i++) { 181 sb.append(" "); 182 } 183 sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); 184 TTY.println(sb.toString()); 185 } 186 187 private static String methodName(ResolvedJavaMethod method) { 188 return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; 189 } 190 191 /** 192 * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code field} with the value 193 * {@code flag}. 194 */ 195 public static void setAccessible(Field field, boolean flag) { 196 if (!Java8OrEarlier) { 197 ModuleAPI.openForReflectionTo(field.getDeclaringClass(), Util.class); 198 } 199 field.setAccessible(flag); 200 } 201 202 /** 203 * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code executable} with the value 204 * {@code flag}. 205 */ 206 public static void setAccessible(Executable executable, boolean flag) { 207 if (!Java8OrEarlier) { 208 ModuleAPI.openForReflectionTo(executable.getDeclaringClass(), Util.class); 209 } 210 executable.setAccessible(flag); 211 } 212 }