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