001/*
002 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.compiler.common.util;
024
025import java.util.*;
026
027import com.oracle.graal.debug.*;
028
029import jdk.internal.jvmci.code.*;
030
031/**
032 * The {@code Util} class contains a motley collection of utility methods used throughout the
033 * compiler.
034 */
035public class Util {
036
037    public static final int PRINTING_LINE_WIDTH = 40;
038    public static final char SECTION_CHARACTER = '*';
039    public static final char SUB_SECTION_CHARACTER = '=';
040    public static final char SEPERATOR_CHARACTER = '-';
041
042    public static <T> boolean replaceInList(T a, T b, List<T> list) {
043        final int max = list.size();
044        for (int i = 0; i < max; i++) {
045            if (list.get(i) == a) {
046                list.set(i, b);
047                return true;
048            }
049        }
050        return false;
051    }
052
053    /**
054     * Statically cast an object to an arbitrary Object type. Dynamically checked.
055     */
056    @SuppressWarnings("unchecked")
057    public static <T> T uncheckedCast(@SuppressWarnings("unused") Class<T> type, Object object) {
058        return (T) object;
059    }
060
061    /**
062     * Statically cast an object to an arbitrary Object type. Dynamically checked.
063     */
064    @SuppressWarnings("unchecked")
065    public static <T> T uncheckedCast(Object object) {
066        return (T) object;
067    }
068
069    /**
070     * Utility method to combine a base hash with the identity hash of one or more objects.
071     *
072     * @param hash the base hash
073     * @param x the object to add to the hash
074     * @return the combined hash
075     */
076    public static int hash1(int hash, Object x) {
077        // always set at least one bit in case the hash wraps to zero
078        return 0x10000000 | (hash + 7 * System.identityHashCode(x));
079    }
080
081    /**
082     * Utility method to combine a base hash with the identity hash of one or more objects.
083     *
084     * @param hash the base hash
085     * @param x the first object to add to the hash
086     * @param y the second object to add to the hash
087     * @return the combined hash
088     */
089    public static int hash2(int hash, Object x, Object y) {
090        // always set at least one bit in case the hash wraps to zero
091        return 0x20000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y));
092    }
093
094    /**
095     * Utility method to combine a base hash with the identity hash of one or more objects.
096     *
097     * @param hash the base hash
098     * @param x the first object to add to the hash
099     * @param y the second object to add to the hash
100     * @param z the third object to add to the hash
101     * @return the combined hash
102     */
103    public static int hash3(int hash, Object x, Object y, Object z) {
104        // always set at least one bit in case the hash wraps to zero
105        return 0x30000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z));
106    }
107
108    /**
109     * Utility method to combine a base hash with the identity hash of one or more objects.
110     *
111     * @param hash the base hash
112     * @param x the first object to add to the hash
113     * @param y the second object to add to the hash
114     * @param z the third object to add to the hash
115     * @param w the fourth object to add to the hash
116     * @return the combined hash
117     */
118    public static int hash4(int hash, Object x, Object y, Object z, Object w) {
119        // always set at least one bit in case the hash wraps to zero
120        return 0x40000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z) + 17 * System.identityHashCode(w));
121    }
122
123    static {
124        assert CodeUtil.log2(2) == 1;
125        assert CodeUtil.log2(4) == 2;
126        assert CodeUtil.log2(8) == 3;
127        assert CodeUtil.log2(16) == 4;
128        assert CodeUtil.log2(32) == 5;
129        assert CodeUtil.log2(0x40000000) == 30;
130
131        assert CodeUtil.log2(2L) == 1;
132        assert CodeUtil.log2(4L) == 2;
133        assert CodeUtil.log2(8L) == 3;
134        assert CodeUtil.log2(16L) == 4;
135        assert CodeUtil.log2(32L) == 5;
136        assert CodeUtil.log2(0x4000000000000000L) == 62;
137
138        assert !CodeUtil.isPowerOf2(3);
139        assert !CodeUtil.isPowerOf2(5);
140        assert !CodeUtil.isPowerOf2(7);
141        assert !CodeUtil.isPowerOf2(-1);
142
143        assert CodeUtil.isPowerOf2(2);
144        assert CodeUtil.isPowerOf2(4);
145        assert CodeUtil.isPowerOf2(8);
146        assert CodeUtil.isPowerOf2(16);
147        assert CodeUtil.isPowerOf2(32);
148        assert CodeUtil.isPowerOf2(64);
149    }
150
151    /**
152     * Sets the element at a given position of a list and ensures that this position exists. If the
153     * list is current shorter than the position, intermediate positions are filled with a given
154     * value.
155     *
156     * @param list the list to put the element into
157     * @param pos the position at which to insert the element
158     * @param x the element that should be inserted
159     * @param filler the filler element that is used for the intermediate positions in case the list
160     *            is shorter than pos
161     */
162    public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) {
163        if (list.size() < pos + 1) {
164            while (list.size() < pos + 1) {
165                list.add(filler);
166            }
167            assert list.size() == pos + 1;
168        }
169
170        assert list.size() >= pos + 1;
171        list.set(pos, x);
172    }
173
174    public static void breakpoint() {
175        // do nothing.
176    }
177
178    public static void guarantee(boolean b, String string) {
179        if (!b) {
180            throw new BailoutException(string);
181        }
182    }
183
184    public static void warning(String string) {
185        TTY.println("WARNING: " + string);
186    }
187
188    public static int safeToInt(long l) {
189        assert (int) l == l;
190        return (int) l;
191    }
192
193    public static int roundUp(int number, int mod) {
194        return ((number + mod - 1) / mod) * mod;
195    }
196
197    public static void printSection(String name, char sectionCharacter) {
198
199        String header = " " + name + " ";
200        int remainingCharacters = PRINTING_LINE_WIDTH - header.length();
201        int leftPart = remainingCharacters / 2;
202        int rightPart = remainingCharacters - leftPart;
203        for (int i = 0; i < leftPart; i++) {
204            TTY.print(sectionCharacter);
205        }
206
207        TTY.print(header);
208
209        for (int i = 0; i < rightPart; i++) {
210            TTY.print(sectionCharacter);
211        }
212
213        TTY.println();
214    }
215
216    /**
217     * Prints entries in a byte array as space separated hex values to {@link TTY}.
218     *
219     * @param address an address at which the bytes are located. This is used to print an address
220     *            prefix per line of output.
221     * @param array the array containing all the bytes to print
222     * @param bytesPerLine the number of values to print per line of output
223     */
224    public static void printBytes(long address, byte[] array, int bytesPerLine) {
225        printBytes(address, array, 0, array.length, bytesPerLine);
226    }
227
228    /**
229     * Prints entries in a byte array as space separated hex values to {@link TTY}.
230     *
231     * @param address an address at which the bytes are located. This is used to print an address
232     *            prefix per line of output.
233     * @param array the array containing the bytes to print
234     * @param offset the offset in {@code array} of the values to print
235     * @param length the number of values from {@code array} print
236     * @param bytesPerLine the number of values to print per line of output
237     */
238    public static void printBytes(long address, byte[] array, int offset, int length, int bytesPerLine) {
239        assert bytesPerLine > 0;
240        boolean newLine = true;
241        for (int i = 0; i < length; i++) {
242            if (newLine) {
243                TTY.print("%08x: ", address + i);
244                newLine = false;
245            }
246            TTY.print("%02x ", array[i]);
247            if (i % bytesPerLine == bytesPerLine - 1) {
248                TTY.println();
249                newLine = true;
250            }
251        }
252
253        if (length % bytesPerLine != bytesPerLine) {
254            TTY.println();
255        }
256    }
257
258    public static boolean isShiftCount(int x) {
259        return 0 <= x && x < 32;
260    }
261
262    /**
263     * Determines if a given {@code int} value is the range of unsigned byte values.
264     */
265    public static boolean isUByte(int x) {
266        return (x & 0xff) == x;
267    }
268
269    /**
270     * Determines if a given {@code int} value is the range of signed byte values.
271     */
272    public static boolean isByte(int x) {
273        return (byte) x == x;
274    }
275
276    /**
277     * Determines if a given {@code long} value is the range of unsigned byte values.
278     */
279    public static boolean isUByte(long x) {
280        return (x & 0xffL) == x;
281    }
282
283    /**
284     * Determines if a given {@code long} value is the range of signed byte values.
285     */
286    public static boolean isByte(long l) {
287        return (byte) l == l;
288    }
289
290    /**
291     * Determines if a given {@code long} value is the range of unsigned int values.
292     */
293    public static boolean isUInt(long x) {
294        return (x & 0xffffffffL) == x;
295    }
296
297    /**
298     * Determines if a given {@code long} value is the range of signed int values.
299     */
300    public static boolean isInt(long l) {
301        return (int) l == l;
302    }
303
304    /**
305     * Determines if a given {@code int} value is the range of signed short values.
306     */
307    public static boolean isShort(int x) {
308        return (short) x == x;
309    }
310
311    public static boolean is32bit(long x) {
312        return -0x80000000L <= x && x < 0x80000000L;
313    }
314
315    public static short safeToShort(int v) {
316        assert isShort(v);
317        return (short) v;
318    }
319
320    /**
321     * Creates an array of integers of length "size", in which each number from 0 to (size - 1)
322     * occurs exactly once. The integers are sorted using the given comparator. This can be used to
323     * create a sorting for arrays that cannot be modified directly.
324     *
325     * @param size The size of the range to be sorted.
326     * @param comparator A comparator that is used to compare indexes.
327     * @return An array of integers that contains each number from 0 to (size - 1) exactly once,
328     *         sorted using the comparator.
329     */
330    public static Integer[] createSortedPermutation(int size, Comparator<Integer> comparator) {
331        Integer[] indexes = new Integer[size];
332        for (int i = 0; i < size; i++) {
333            indexes[i] = i;
334        }
335        Arrays.sort(indexes, comparator);
336        return indexes;
337    }
338}