001/*
002 * Copyright (c) 2011, 2012, 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.nodes;
024
025import java.util.*;
026
027import jdk.internal.jvmci.meta.*;
028import jdk.internal.jvmci.meta.Kind.FormatWithToString;
029
030/**
031 * A {@link LocationIdentity} with a name.
032 */
033public class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
034
035    /**
036     * Map for asserting all {@link NamedLocationIdentity} instances have a unique name.
037     */
038    static class DB {
039        private static final HashSet<String> map = new HashSet<>();
040
041        static boolean checkUnique(String name) {
042            if (!map.add(name)) {
043                throw new AssertionError("identity " + name + " already exists");
044            }
045            return true;
046        }
047    }
048
049    /**
050     * Denotes the location of a value that is guaranteed to be unchanging.
051     */
052    public static final LocationIdentity FINAL_LOCATION = NamedLocationIdentity.immutable("FINAL_LOCATION");
053
054    /**
055     * Denotes the location of the length field of a Java array.
056     */
057    public static final LocationIdentity ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("[].length");
058
059    public static LocationIdentity any() {
060        return ANY_LOCATION;
061    }
062
063    private final String name;
064    private final boolean immutable;
065
066    protected NamedLocationIdentity(String name, boolean immutable) {
067        this.name = name;
068        this.immutable = immutable;
069        assert DB.checkUnique(name);
070    }
071
072    /**
073     * Creates a named unique location identity for read and write operations against mutable
074     * memory.
075     *
076     * @param name the name of the new location identity
077     */
078    public static NamedLocationIdentity mutable(String name) {
079        return create(name, false);
080    }
081
082    /**
083     * Creates a named unique location identity for read operations against immutable memory.
084     * Immutable memory will never have a visible write in the graph, which is more restictive than
085     * Java final.
086     *
087     * @param name the name of the new location identity
088     */
089    public static NamedLocationIdentity immutable(String name) {
090        return create(name, true);
091    }
092
093    /**
094     * Creates a named unique location identity for read and write operations.
095     *
096     * @param name the name of the new location identity
097     * @param immutable true if the location is immutable
098     */
099    private static NamedLocationIdentity create(String name, boolean immutable) {
100        return new NamedLocationIdentity(name, immutable);
101    }
102
103    @Override
104    public boolean isImmutable() {
105        return immutable;
106    }
107
108    @Override
109    public String toString() {
110        return name + (isImmutable() ? ":final" : "");
111    }
112
113    /**
114     * Returns the named location identity for an array of the given element kind. Array accesses of
115     * the same kind must have the same location identity unless an alias analysis guarantees that
116     * two distinct arrays are accessed.
117     */
118    public static LocationIdentity getArrayLocation(Kind elementKind) {
119        return ARRAY_LOCATIONS.get(elementKind);
120    }
121
122    private static final EnumMap<Kind, LocationIdentity> ARRAY_LOCATIONS = initArrayLocations();
123
124    private static EnumMap<Kind, LocationIdentity> initArrayLocations() {
125        EnumMap<Kind, LocationIdentity> result = new EnumMap<>(Kind.class);
126        for (Kind kind : Kind.values()) {
127            result.put(kind, NamedLocationIdentity.mutable("Array: " + kind.getJavaName()));
128        }
129        return result;
130    }
131}