Util.java revision 12651:6ef01bd40ce2
1100619Smp/*
2100619Smp * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3100619Smp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4100619Smp *
5100619Smp * This code is free software; you can redistribute it and/or modify it
6100619Smp * under the terms of the GNU General Public License version 2 only, as
7100619Smp * published by the Free Software Foundation.
8167469Smp *
9100619Smp * 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 */
23package org.graalvm.compiler.core.common.util;
24
25import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
26
27import java.util.Collection;
28import java.util.List;
29
30import org.graalvm.compiler.debug.TTY;
31
32import jdk.vm.ci.meta.JavaConstant;
33import jdk.vm.ci.meta.JavaKind;
34import 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 */
40public 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}
216