1 /*
2  * Copyright (c) 2011, 2016, 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.type;
26 
27 import org.graalvm.compiler.core.common.LIRKind;
28 import org.graalvm.compiler.core.common.spi.LIRKindTool;
29 
30 import jdk.vm.ci.meta.Constant;
31 import jdk.vm.ci.meta.JavaKind;
32 import jdk.vm.ci.meta.MemoryAccessProvider;
33 import jdk.vm.ci.meta.MetaAccessProvider;
34 import jdk.vm.ci.meta.ResolvedJavaType;
35 
36 /**
37  * A stamp is the basis for a type system.
38  */
39 public abstract class Stamp {
40 
Stamp()41     protected Stamp() {
42     }
43 
44     /**
45      * Returns the type of the stamp, guaranteed to be non-null. In some cases, this requires the
46      * lookup of class meta data, therefore the {@link MetaAccessProvider} is mandatory.
47      */
javaType(MetaAccessProvider metaAccess)48     public abstract ResolvedJavaType javaType(MetaAccessProvider metaAccess);
49 
alwaysDistinct(Stamp other)50     public boolean alwaysDistinct(Stamp other) {
51         return join(other).isEmpty();
52     }
53 
54     /**
55      * Gets a Java {@link JavaKind} that can be used to store a value of this stamp on the Java
56      * bytecode stack. Returns {@link JavaKind#Illegal} if a value of this stamp can not be stored
57      * on the bytecode stack.
58      */
getStackKind()59     public abstract JavaKind getStackKind();
60 
61     /**
62      * Gets a platform dependent {@link LIRKind} that can be used to store a value of this stamp.
63      */
getLIRKind(LIRKindTool tool)64     public abstract LIRKind getLIRKind(LIRKindTool tool);
65 
66     /**
67      * Returns the union of this stamp and the given stamp. Typically used to create stamps for phi
68      * nodes.
69      *
70      * @param other The stamp that will enlarge this stamp.
71      * @return The union of this stamp and the given stamp.
72      */
meet(Stamp other)73     public abstract Stamp meet(Stamp other);
74 
75     /**
76      * Returns the intersection of this stamp and the given stamp.
77      *
78      * @param other The stamp that will tighten this stamp.
79      * @return The intersection of this stamp and the given stamp.
80      */
join(Stamp other)81     public abstract Stamp join(Stamp other);
82 
83     /**
84      * Returns a stamp of the same kind, but allowing the full value range of the kind.
85      *
86      * {@link #unrestricted()} is the neutral element of the {@link #join(Stamp)} operation.
87      */
unrestricted()88     public abstract Stamp unrestricted();
89 
90     /**
91      * Returns a stamp of the same kind, but with no allowed values.
92      *
93      * {@link #empty()} is the neutral element of the {@link #meet(Stamp)} operation.
94      */
empty()95     public abstract Stamp empty();
96 
97     /**
98      * If it is possible to represent single value stamps of this kind, this method returns the
99      * stamp representing the single value c. stamp.constant(c).asConstant() should be equal to c.
100      * <p>
101      * If it is not possible to represent single value stamps, this method returns a stamp that
102      * includes c, and is otherwise as narrow as possible.
103      */
constant(Constant c, MetaAccessProvider meta)104     public abstract Stamp constant(Constant c, MetaAccessProvider meta);
105 
106     /**
107      * Test whether two stamps have the same base type.
108      */
isCompatible(Stamp other)109     public abstract boolean isCompatible(Stamp other);
110 
111     /**
112      * Check that the constant {@code other} is compatible with this stamp.
113      *
114      * @param constant
115      */
isCompatible(Constant constant)116     public abstract boolean isCompatible(Constant constant);
117 
118     /**
119      * Test whether this stamp has legal values.
120      */
hasValues()121     public abstract boolean hasValues();
122 
123     /**
124      * Tests whether this stamp represents an illegal value.
125      */
isEmpty()126     public final boolean isEmpty() {
127         return !hasValues();
128     }
129 
130     /**
131      * Tests whether this stamp represents all values of this kind.
132      */
isUnrestricted()133     public boolean isUnrestricted() {
134         return this.equals(this.unrestricted());
135     }
136 
137     /**
138      * If this stamp represents a single value, the methods returns this single value. It returns
139      * null otherwise.
140      *
141      * @return the constant corresponding to the single value of this stamp and null if this stamp
142      *         can represent less or more than one value.
143      */
asConstant()144     public Constant asConstant() {
145         return null;
146     }
147 
148     /**
149      * Read a value of this stamp from memory.
150      *
151      * @return the value read or null if the value can't be read for some reason.
152      */
readConstant(MemoryAccessProvider provider, Constant base, long displacement)153     public abstract Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement);
154 
155     /**
156      * Tries to improve this stamp with the stamp given as parameter. If successful, returns the new
157      * improved stamp. Otherwise, returns a stamp equal to this.
158      *
159      * @param other the stamp that should be used to improve this stamp
160      * @return the newly improved stamp or a stamp equal to {@code this} if an improvement was not
161      *         possible
162      */
improveWith(Stamp other)163     public abstract Stamp improveWith(Stamp other);
164 
165     /**
166      * Tries to improve this stamp with the stamp given as parameter. If successful, returns the new
167      * improved stamp. Otherwise, returns null.
168      *
169      * @param other the stamp that should be used to improve this stamp
170      * @return the newly improved stamp or {@code null} if an improvement was not possible
171      */
tryImproveWith(Stamp other)172     public final Stamp tryImproveWith(Stamp other) {
173         Stamp improved = improveWith(other);
174         if (improved.equals(this)) {
175             return null;
176         }
177         return improved;
178     }
179 
neverDistinct(Stamp other)180     public boolean neverDistinct(Stamp other) {
181         Constant constant = this.asConstant();
182         if (constant != null) {
183             Constant otherConstant = other.asConstant();
184             return otherConstant != null && constant.equals(otherConstant);
185         }
186         return false;
187     }
188 }
189