StampFactory.java revision 12651:6ef01bd40ce2
1184588Sdfr/* 2197583Sjamie * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3197583Sjamie * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4184588Sdfr * 5184588Sdfr * This code is free software; you can redistribute it and/or modify it 6184588Sdfr * under the terms of the GNU General Public License version 2 only, as 7184588Sdfr * published by the Free Software Foundation. 8184588Sdfr * 9184588Sdfr * This code is distributed in the hope that it will be useful, but WITHOUT 10184588Sdfr * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11184588Sdfr * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12184588Sdfr * version 2 for more details (a copy is included in the LICENSE file that 13184588Sdfr * accompanied this code). 14197583Sjamie * 15184588Sdfr * You should have received a copy of the GNU General Public License version 16184588Sdfr * 2 along with this work; if not, write to the Free Software Foundation, 17197583Sjamie * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18184588Sdfr * 19184588Sdfr * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20184588Sdfr * or visit www.oracle.com if you need additional information or have any 21184588Sdfr * questions. 22184588Sdfr */ 23184588Sdfrpackage org.graalvm.compiler.core.common.type; 24184588Sdfr 25184588Sdfrimport org.graalvm.compiler.debug.GraalError; 26197583Sjamie 27197583Sjamieimport jdk.vm.ci.code.CodeUtil; 28197583Sjamieimport jdk.vm.ci.meta.Assumptions; 29197583Sjamieimport jdk.vm.ci.meta.JavaConstant; 30197583Sjamieimport jdk.vm.ci.meta.JavaKind; 31184588Sdfrimport jdk.vm.ci.meta.JavaType; 32197583Sjamieimport jdk.vm.ci.meta.MetaAccessProvider; 33197583Sjamieimport jdk.vm.ci.meta.ResolvedJavaMethod; 34197583Sjamieimport jdk.vm.ci.meta.ResolvedJavaType; 35197583Sjamieimport jdk.vm.ci.meta.Signature; 36197583Sjamie 37197583Sjamiepublic class StampFactory { 38197583Sjamie 39197583Sjamie /* 40197583Sjamie * The marker stamp for node intrinsics must be its own class, so that it is never equal() to a 41197583Sjamie * regular ObjectStamp. 42197583Sjamie */ 43197583Sjamie static final class NodeIntrinsicStamp extends ObjectStamp { 44197583Sjamie protected static final Stamp SINGLETON = new NodeIntrinsicStamp(); 45197583Sjamie 46197583Sjamie private NodeIntrinsicStamp() { 47197583Sjamie super(null, false, false, false); 48197583Sjamie } 49197583Sjamie 50197583Sjamie @Override 51197583Sjamie public int hashCode() { 52197583Sjamie return System.identityHashCode(this); 53197583Sjamie } 54197583Sjamie 55197583Sjamie @Override 56197583Sjamie public boolean equals(Object obj) { 57197583Sjamie return this == obj; 58197583Sjamie } 59197583Sjamie } 60197583Sjamie 61197583Sjamie // JaCoCo Exclude 62197583Sjamie 63184588Sdfr private static final Stamp[] stampCache = new Stamp[JavaKind.values().length]; 64184588Sdfr private static final Stamp[] emptyStampCache = new Stamp[JavaKind.values().length]; 65184588Sdfr private static final Stamp objectStamp = new ObjectStamp(null, false, false, false); 66184588Sdfr private static final Stamp objectNonNullStamp = new ObjectStamp(null, false, true, false); 67197583Sjamie private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true); 68194239Srmacklem private static final Stamp positiveInt = forInteger(JavaKind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); 69184588Sdfr private static final Stamp booleanTrue = forInteger(JavaKind.Boolean, -1, -1, 1, 1); 70197583Sjamie private static final Stamp booleanFalse = forInteger(JavaKind.Boolean, 0, 0, 0, 0); 71184588Sdfr private static final Stamp rawPointer = new RawPointerStamp(); 72184588Sdfr 73184588Sdfr private static void setCache(JavaKind kind, Stamp stamp) { 74184588Sdfr stampCache[kind.ordinal()] = stamp; 75197583Sjamie } 76197583Sjamie 77197583Sjamie private static void setIntCache(JavaKind kind) { 78184588Sdfr int bits = kind.getStackKind().getBitCount(); 79197583Sjamie long mask; 80197583Sjamie if (kind.isUnsigned()) { 81184588Sdfr mask = CodeUtil.mask(kind.getBitCount()); 82197583Sjamie } else { 83184588Sdfr mask = CodeUtil.mask(bits); 84197583Sjamie } 85197583Sjamie setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); 86197583Sjamie } 87197583Sjamie 88197583Sjamie private static void setFloatCache(JavaKind kind) { 89184588Sdfr setCache(kind, new FloatStamp(kind.getBitCount())); 90197583Sjamie } 91197583Sjamie 92197583Sjamie static { 93197583Sjamie setIntCache(JavaKind.Boolean); 94184588Sdfr setIntCache(JavaKind.Byte); 95184588Sdfr setIntCache(JavaKind.Short); 96197583Sjamie setIntCache(JavaKind.Char); 97197583Sjamie setIntCache(JavaKind.Int); 98197583Sjamie setIntCache(JavaKind.Long); 99197583Sjamie 100197583Sjamie setFloatCache(JavaKind.Float); 101197583Sjamie setFloatCache(JavaKind.Double); 102197583Sjamie 103201145Santoine setCache(JavaKind.Object, objectStamp); 104197583Sjamie setCache(JavaKind.Void, VoidStamp.getInstance()); 105197583Sjamie setCache(JavaKind.Illegal, IllegalStamp.getInstance()); 106197583Sjamie 107197583Sjamie for (JavaKind k : JavaKind.values()) { 108197583Sjamie if (stampCache[k.ordinal()] != null) { 109197583Sjamie emptyStampCache[k.ordinal()] = stampCache[k.ordinal()].empty(); 110197583Sjamie } 111197583Sjamie } 112197583Sjamie } 113197583Sjamie 114197583Sjamie public static Stamp tautology() { 115201145Santoine return booleanTrue; 116197583Sjamie } 117197583Sjamie 118197583Sjamie public static Stamp contradiction() { 119197583Sjamie return booleanFalse; 120197583Sjamie } 121197583Sjamie 122197583Sjamie /** 123197583Sjamie * Return a stamp for a Java kind, as it would be represented on the bytecode stack. 124201853Sbrooks */ 125201853Sbrooks public static Stamp forKind(JavaKind kind) { 126201853Sbrooks assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")"; 127197583Sjamie return stampCache[kind.ordinal()]; 128197583Sjamie } 129197583Sjamie 130197583Sjamie /** 131197583Sjamie * Return the stamp for the {@code void} type. This will return a singleton instance than can be 132197583Sjamie * compared using {@code ==}. 133197583Sjamie */ 134197583Sjamie public static Stamp forVoid() { 135197583Sjamie return VoidStamp.getInstance(); 136197583Sjamie } 137197583Sjamie 138197583Sjamie /** 139197583Sjamie * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an 140197583Sjamie * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. 141197583Sjamie */ 142197583Sjamie public static Stamp forNodeIntrinsic() { 143197583Sjamie return NodeIntrinsicStamp.SINGLETON; 144197583Sjamie } 145197583Sjamie 146197583Sjamie public static Stamp intValue() { 147197583Sjamie return forKind(JavaKind.Int); 148197583Sjamie } 149197583Sjamie 150197583Sjamie public static Stamp positiveInt() { 151197583Sjamie return positiveInt; 152197583Sjamie } 153201853Sbrooks 154197583Sjamie public static Stamp empty(JavaKind kind) { 155197583Sjamie return emptyStampCache[kind.ordinal()]; 156197583Sjamie } 157197583Sjamie 158197583Sjamie public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound, long downMask, long upMask) { 159197583Sjamie return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); 160197583Sjamie } 161197581Sjamie 162197583Sjamie public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound) { 163197583Sjamie return forInteger(kind.getBitCount(), lowerBound, upperBound); 164197583Sjamie } 165197581Sjamie 166197583Sjamie /** 167197583Sjamie * Create a new stamp use {@code newLowerBound} and {@code newUpperBound} computing the 168197583Sjamie * appropriate {@link IntegerStamp#upMask} and {@link IntegerStamp#downMask} and incorporating 169197583Sjamie * any mask information from {@code maskStamp}. 170184588Sdfr * 171184588Sdfr * @param bits 172197583Sjamie * @param newLowerBound 173197583Sjamie * @param newUpperBound 174197583Sjamie * @param maskStamp 175197583Sjamie * @return a new stamp with the appropriate bounds and masks 176197583Sjamie */ 177197583Sjamie public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, IntegerStamp maskStamp) { 178197583Sjamie IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); 179197583Sjamie return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); 180197583Sjamie } 181184588Sdfr 182197583Sjamie public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, long newDownMask, long newUpMask) { 183184588Sdfr IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); 184197583Sjamie return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); 185197583Sjamie } 186197583Sjamie 187197583Sjamie public static IntegerStamp forInteger(int bits) { 188197583Sjamie return new IntegerStamp(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); 189197583Sjamie } 190197583Sjamie 191197583Sjamie public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { 192197583Sjamie long defaultMask = CodeUtil.mask(bits); 193197583Sjamie if (lowerBound == upperBound) { 194197583Sjamie return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); 195197583Sjamie } 196197583Sjamie final long downMask; 197197583Sjamie final long upMask; 198197583Sjamie if (lowerBound >= 0) { 199197583Sjamie int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); 200197583Sjamie long differentBits = lowerBound ^ upperBound; 201184588Sdfr int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); 202197583Sjamie 203197583Sjamie upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); 204197583Sjamie downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); 205197583Sjamie } else { 206184588Sdfr if (upperBound >= 0) { 207197583Sjamie upMask = defaultMask; 208197583Sjamie downMask = 0; 209197583Sjamie } else { 210197583Sjamie int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); 211197583Sjamie long differentBits = lowerBound ^ upperBound; 212197583Sjamie int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); 213197583Sjamie 214197583Sjamie upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); 215197583Sjamie downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); 216197583Sjamie } 217197583Sjamie } 218197583Sjamie return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); 219197583Sjamie } 220197583Sjamie 221197583Sjamie public static FloatStamp forFloat(JavaKind kind, double lowerBound, double upperBound, boolean nonNaN) { 222197583Sjamie assert kind.isNumericFloat(); 223197583Sjamie return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN); 224197583Sjamie } 225184588Sdfr 226184588Sdfr public static Stamp forConstant(JavaConstant value) { 227197583Sjamie JavaKind kind = value.getJavaKind(); 228197583Sjamie switch (kind) { 229184588Sdfr case Boolean: 230197583Sjamie case Byte: 231197583Sjamie case Char: 232197583Sjamie case Short: 233197583Sjamie case Int: 234197583Sjamie case Long: 235197583Sjamie long mask = value.asLong() & CodeUtil.mask(kind.getBitCount()); 236197583Sjamie return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask); 237197583Sjamie case Float: 238197583Sjamie return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat())); 239197583Sjamie case Double: 240197583Sjamie return forFloat(kind, value.asDouble(), value.asDouble(), !Double.isNaN(value.asDouble())); 241197583Sjamie case Illegal: 242197583Sjamie return forKind(JavaKind.Illegal); 243197583Sjamie case Object: 244197583Sjamie if (value.isNull()) { 245197583Sjamie return alwaysNull(); 246197583Sjamie } else { 247197583Sjamie return objectNonNull(); 248197583Sjamie } 249197583Sjamie default: 250197583Sjamie throw new GraalError("unexpected kind: %s", kind); 251197583Sjamie } 252197583Sjamie } 253197583Sjamie 254197583Sjamie public static Stamp forConstant(JavaConstant value, MetaAccessProvider metaAccess) { 255197583Sjamie if (value.getJavaKind() == JavaKind.Object) { 256197583Sjamie ResolvedJavaType type = value.isNull() ? null : metaAccess.lookupJavaType(value); 257197583Sjamie return new ObjectStamp(type, value.isNonNull(), value.isNonNull(), value.isNull()); 258184588Sdfr } else { 259197583Sjamie return forConstant(value); 260184588Sdfr } 261197583Sjamie } 262197583Sjamie 263197583Sjamie public static Stamp object() { 264197583Sjamie return objectStamp; 265197583Sjamie } 266197583Sjamie 267197583Sjamie public static Stamp objectNonNull() { 268197583Sjamie return objectNonNullStamp; 269197583Sjamie } 270197583Sjamie 271197583Sjamie public static Stamp alwaysNull() { 272197583Sjamie return objectAlwaysNullStamp; 273197583Sjamie } 274197583Sjamie 275197583Sjamie public static ObjectStamp object(TypeReference type) { 276197583Sjamie return object(type, false); 277197583Sjamie } 278197583Sjamie 279197583Sjamie public static ObjectStamp objectNonNull(TypeReference type) { 280197583Sjamie return object(type, true); 281197583Sjamie } 282197583Sjamie 283197583Sjamie public static ObjectStamp object(TypeReference type, boolean nonNull) { 284197583Sjamie if (type == null) { 285197583Sjamie return new ObjectStamp(null, false, nonNull, false); 286197583Sjamie } else { 287197583Sjamie return new ObjectStamp(type.getType(), type.isExact(), nonNull, false); 288184588Sdfr } 289197583Sjamie } 290197583Sjamie 291197583Sjamie public static Stamp[] createParameterStamps(Assumptions assumptions, ResolvedJavaMethod method) { 292197583Sjamie Signature sig = method.getSignature(); 293197583Sjamie Stamp[] result = new Stamp[sig.getParameterCount(!method.isStatic())]; 294197583Sjamie int index = 0; 295197583Sjamie 296197583Sjamie if (!method.isStatic()) { 297197583Sjamie result[index++] = StampFactory.objectNonNull(TypeReference.create(assumptions, method.getDeclaringClass())); 298197583Sjamie } 299197583Sjamie 300197583Sjamie int max = sig.getParameterCount(false); 301197583Sjamie ResolvedJavaType accessingClass = method.getDeclaringClass(); 302197583Sjamie for (int i = 0; i < max; i++) { 303197583Sjamie JavaType type = sig.getParameterType(i, accessingClass); 304197583Sjamie JavaKind kind = type.getJavaKind(); 305197583Sjamie Stamp stamp; 306197583Sjamie if (kind == JavaKind.Object && type instanceof ResolvedJavaType) { 307197583Sjamie stamp = StampFactory.object(TypeReference.create(assumptions, (ResolvedJavaType) type)); 308197583Sjamie } else { 309197583Sjamie stamp = StampFactory.forKind(kind); 310197583Sjamie } 311197583Sjamie result[index++] = stamp; 312197583Sjamie } 313197583Sjamie 314184588Sdfr return result; 315184588Sdfr } 316197583Sjamie 317197583Sjamie public static Stamp pointer() { 318197583Sjamie return rawPointer; 319197583Sjamie } 320197583Sjamie 321197583Sjamie public static StampPair forDeclaredType(Assumptions assumptions, JavaType returnType, boolean nonNull) { 322197583Sjamie if (returnType.getJavaKind() == JavaKind.Object && returnType instanceof ResolvedJavaType) { 323197583Sjamie ResolvedJavaType resolvedJavaType = (ResolvedJavaType) returnType; 324197583Sjamie TypeReference reference = TypeReference.create(assumptions, resolvedJavaType); 325197583Sjamie if (resolvedJavaType.isInterface()) { 326197583Sjamie ResolvedJavaType implementor = resolvedJavaType.getSingleImplementor(); 327197583Sjamie if (implementor != null && !resolvedJavaType.equals(implementor)) { 328197583Sjamie TypeReference uncheckedType = TypeReference.createTrusted(assumptions, implementor); 329197583Sjamie return StampPair.create(StampFactory.object(reference, nonNull), StampFactory.object(uncheckedType, nonNull)); 330197583Sjamie } 331197583Sjamie } 332197583Sjamie return StampPair.createSingle(StampFactory.object(reference, nonNull)); 333197583Sjamie } else { 334197583Sjamie return StampPair.createSingle(StampFactory.forKind(returnType.getJavaKind())); 335197583Sjamie } 336197583Sjamie } 337197583Sjamie} 338197583Sjamie