view graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiKind.java @ 4558:3706975946e4

Make graph dumping a bit more robust when there is no method, enable debug in the startCompiler method, add context and scope for snippets installation Made IGV display graphs even if some edges are problematic When schedule failed don't use it
author Gilles Duboscq <duboscq@ssw.jku.at>
date Fri, 10 Feb 2012 02:22:23 +0100
parents 87a12a816e99
children 077ec9468516
line wrap: on
line source

/*
 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.max.cri.ci;

import static com.oracle.max.cri.ci.CiKind.Flags.*;
import sun.misc.*;

import com.oracle.max.cri.ri.*;

/**
 * Denotes the basic kinds of types in CRI, including the all the Java primitive types,
 * for example, {@link CiKind#Int} for {@code int} and {@link CiKind#Object}
 * for all object types.
 * A kind has a single character short name, a Java name, and a set of flags
 * further describing its behavior.
 */
public enum CiKind {
    Boolean('z', "boolean", FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT),
    Byte   ('b', "byte",    FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT),
    Short  ('s', "short",   FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT),
    Char   ('c', "char",    FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT),
    Int    ('i', "int",     FIELD_TYPE | RETURN_TYPE | PRIMITIVE | STACK_INT),
    Float  ('f', "float",   FIELD_TYPE | RETURN_TYPE | PRIMITIVE),
    Long   ('j', "long",    FIELD_TYPE | RETURN_TYPE | PRIMITIVE),
    Double ('d', "double",  FIELD_TYPE | RETURN_TYPE | PRIMITIVE),
    Object ('a', "Object",  FIELD_TYPE | RETURN_TYPE),
    Void   ('v', "void",    RETURN_TYPE),
    /** Denote a bytecode address in a {@code JSR} bytecode. */
    Jsr    ('r', "jsr",     0),
    /** The non-type. */
    Illegal('-', "illegal", 0);

    public static final CiKind[] VALUES = values();
    public static final CiKind[] JAVA_VALUES = new CiKind[] {CiKind.Boolean, CiKind.Byte, CiKind.Short, CiKind.Char, CiKind.Int, CiKind.Float, CiKind.Long, CiKind.Double, CiKind.Object};

    CiKind(char ch, String name, int flags) {
        this.typeChar = ch;
        this.javaName = name;
        this.flags = flags;
    }

    static class Flags {
        /**
         * Can be an object field type.
         */
        public static final int FIELD_TYPE  = 0x0001;
        /**
         * Can be result type of a method.
         */
        public static final int RETURN_TYPE = 0x0002;
        /**
         * Behaves as an integer when on Java evaluation stack.
         */
        public static final int STACK_INT   = 0x0004;
        /**
         * Represents a Java primitive type.
         */
        public static final int PRIMITIVE   = 0x0008;
    }

    /**
     * The flags for this kind.
     */
    private final int flags;

    /**
     * The name of the kind as a single character.
     */
    public final char typeChar;

    /**
     * The name of this kind which will also be it Java programming language name if
     * it is {@linkplain #isPrimitive() primitive} or {@code void}.
     */
    public final String javaName;

    /**
     * Checks whether this kind is valid as the type of a field.
     * @return {@code true} if this kind is valid as the type of a Java field
     */
    public boolean isValidFieldType() {
        return (flags & FIELD_TYPE) != 0;
    }

    /**
     * Checks whether this kind is valid as the return type of a method.
     * @return {@code true} if this kind is valid as the return type of a Java method
     */
    public boolean isValidReturnType() {
        return (flags & RETURN_TYPE) != 0;
    }

    /**
     * Checks whether this type is valid as an {@code int} on the Java operand stack.
     * @return {@code true} if this type is represented by an {@code int} on the operand stack
     */
    public boolean isInt() {
        return (flags & STACK_INT) != 0;
    }

    /**
     * Checks whether this type is a Java primitive type.
     * @return {@code true} if this is {@link #Boolean}, {@link #Byte}, {@link #Char}, {@link #Short},
     *                                 {@link #Int}, {@link #Long}, {@link #Float} or {@link #Double}.
     */
    public boolean isPrimitive() {
        return (flags & PRIMITIVE) != 0;
    }

    /**
     * Gets the kind that represents this kind when on the Java operand stack.
     * @return the kind used on the operand stack
     */
    public CiKind stackKind() {
        if (isInt()) {
            return Int;
        }
        return this;
    }

    public static CiKind fromTypeString(String typeString) {
        assert typeString.length() > 0;
        final char first = typeString.charAt(0);
        if (first == '[' || first == 'L') {
            return CiKind.Object;
        }
        return CiKind.fromPrimitiveOrVoidTypeChar(first);
    }

    /**
     * Gets the kind from the character describing a primitive or void.
     * @param ch the character
     * @return the kind
     */
    public static CiKind fromPrimitiveOrVoidTypeChar(char ch) {
        // Checkstyle: stop
        switch (ch) {
            case 'Z': return Boolean;
            case 'C': return Char;
            case 'F': return Float;
            case 'D': return Double;
            case 'B': return Byte;
            case 'S': return Short;
            case 'I': return Int;
            case 'J': return Long;
            case 'V': return Void;
        }
        // Checkstyle: resume
        throw new IllegalArgumentException("unknown primitive or void type character: " + ch);
    }

    public Class< ? > toJavaClass() {
        // Checkstyle: stop
        switch(this) {
            case Void:      return java.lang.Void.TYPE;
            case Long:      return java.lang.Long.TYPE;
            case Int:       return java.lang.Integer.TYPE;
            case Byte:      return java.lang.Byte.TYPE;
            case Char:      return java.lang.Character.TYPE;
            case Double:    return java.lang.Double.TYPE;
            case Float:     return java.lang.Float.TYPE;
            case Short:     return java.lang.Short.TYPE;
            case Boolean:   return java.lang.Boolean.TYPE;
            default:        return null;
        }
        // Checkstyle: resume
    }

    public Class< ? > toUnboxedJavaClass() {
        // Checkstyle: stop
        switch(this) {
            case Void:      return null;
            case Long:      return java.lang.Long.class;
            case Int:       return java.lang.Integer.class;
            case Byte:      return java.lang.Byte.class;
            case Char:      return java.lang.Character.class;
            case Double:    return java.lang.Double.class;
            case Float:     return java.lang.Float.class;
            case Short:     return java.lang.Short.class;
            case Boolean:   return java.lang.Boolean.class;
            default:        return null;
        }
        // Checkstyle: resume
    }

    /**
     * Checks whether this value type is void.
     * @return {@code true} if this type is void
     */
    public final boolean isVoid() {
        return this == CiKind.Void;
    }

    /**
     * Checks whether this value type is long.
     * @return {@code true} if this type is long
     */
    public final boolean isLong() {
        return this == CiKind.Long;
    }

    /**
     * Checks whether this value type is float.
     * @return {@code true} if this type is float
     */
    public final boolean isFloat() {
        return this == CiKind.Float;
    }

    /**
     * Checks whether this value type is double.
     * @return {@code true} if this type is double
     */
    public final boolean isDouble() {
        return this == CiKind.Double;
    }

    /**
     * Checks whether this value type is float or double.
     * @return {@code true} if this type is float or double
     */
    public final boolean isFloatOrDouble() {
        return this == CiKind.Double || this == CiKind.Float;
    }

   /**
     * Checks whether this value type is an object type.
     * @return {@code true} if this type is an object
     */
    public final boolean isObject() {
        return this == CiKind.Object;
    }

    /**
     * Checks whether this value type is an address type.
     * @return {@code true} if this type is an address
     */
    public boolean isJsr() {
        return this == CiKind.Jsr;
    }

    /**
     * Converts this value type to a string.
     */
    @Override
    public String toString() {
        return javaName;
    }

    /**
     * Marker interface for types that should be {@linkplain CiKind#format(Object) formatted}
     * with their {@link Object#toString()} value.
     */
    public interface FormatWithToString {}

    /**
     * Gets a formatted string for a given value of this kind.
     *
     * @param value a value of this kind
     * @return a formatted string for {@code value} based on this kind
     */
    public String format(Object value) {
        if (isObject()) {
            if (value == null) {
                return "null";
            } else {
                if (value instanceof String) {
                    String s = (String) value;
                    if (s.length() > 50) {
                        return "\"" + s.substring(0, 30) + "...\"";
                    } else {
                        return " \"" + s + '"';
                    }
                } else if (value instanceof RiType) {
                    return "class " + CiUtil.toJavaName((RiType) value);
                } else if (value instanceof Enum || value instanceof FormatWithToString) {
                    return String.valueOf(value);
                } else if (value instanceof Class< ? >) {
                    return ((Class< ? >) value).getName() + ".class";
                } else {
                    return CiUtil.getSimpleName(value.getClass(), true) + "@" + System.identityHashCode(value);
                }
            }
        } else {
            return value.toString();
        }
    }

    public final char signatureChar() {
        return Character.toUpperCase(typeChar);
    }

    public CiConstant readUnsafeConstant(Object value, long displacement) {
        assert value != null;
        Unsafe u = Unsafe.getUnsafe();
        switch(this) {
            case Boolean:
                return CiConstant.forBoolean(u.getBoolean(value, displacement));
            case Byte:
                return CiConstant.forByte(u.getByte(value, displacement));
            case Char:
                return CiConstant.forChar(u.getChar(value, displacement));
            case Short:
                return CiConstant.forShort(u.getShort(value, displacement));
            case Int:
                return CiConstant.forInt(u.getInt(value, displacement));
            case Long:
                return CiConstant.forLong(u.getLong(value, displacement));
            case Float:
                return CiConstant.forFloat(u.getFloat(value, displacement));
            case Double:
                return CiConstant.forDouble(u.getDouble(value, displacement));
            case Object:
                return CiConstant.forObject(u.getObject(value, displacement));
            default:
                assert false : "unexpected kind: " + this;
                return null;
        }
    }

}