001/* 002 * Copyright (c) 2012, 2015, 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.type; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.type.*; 030import com.oracle.graal.nodes.*; 031 032/** 033 * Helper class that is used to keep all stamp-related operations in one place. 034 */ 035public class StampTool { 036 037 public static Stamp meet(Collection<? extends ValueNode> values) { 038 Iterator<? extends ValueNode> iterator = values.iterator(); 039 if (iterator.hasNext()) { 040 Stamp stamp = iterator.next().stamp(); 041 while (iterator.hasNext()) { 042 stamp = stamp.meet(iterator.next().stamp()); 043 } 044 return stamp; 045 } else { 046 return StampFactory.forVoid(); 047 } 048 } 049 050 /** 051 * Compute the stamp resulting from the unsigned comparison being true. 052 * 053 * @return null if it's can't be true or it nothing useful can be encoded. 054 */ 055 public static Stamp unsignedCompare(Stamp stamp, Stamp stamp2) { 056 IntegerStamp x = (IntegerStamp) stamp; 057 IntegerStamp y = (IntegerStamp) stamp2; 058 if (x == x.unrestricted() && y == y.unrestricted()) { 059 // Don't know anything. 060 return null; 061 } 062 // c <| n, where c is a constant and n is known to be positive. 063 if (x.lowerBound() == x.upperBound()) { 064 if (y.isPositive()) { 065 if (x.lowerBound() == (1 << x.getBits()) - 1) { 066 // Constant is MAX_VALUE which must fail. 067 return null; 068 } 069 if (x.lowerBound() <= y.lowerBound()) { 070 // Test will fail. Return illegalStamp instead? 071 return null; 072 } 073 // If the test succeeds then this proves that n is at greater than c so the bounds 074 // are [c+1..-n.upperBound)]. 075 return StampFactory.forInteger(x.getBits(), x.lowerBound() + 1, y.upperBound()); 076 } 077 return null; 078 } 079 // n <| c, where c is a strictly positive constant 080 if (y.lowerBound() == y.upperBound() && y.isStrictlyPositive()) { 081 // The test proves that n is positive and less than c, [0..c-1] 082 return StampFactory.forInteger(y.getBits(), 0, y.lowerBound() - 1); 083 } 084 return null; 085 } 086 087 /** 088 * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#hasValues() legal} 089 * pointer value which is known to be always null. 090 * 091 * @param node the node to check 092 * @return true if this node represents a legal object value which is known to be always null 093 */ 094 public static boolean isPointerAlwaysNull(ValueNode node) { 095 return isPointerAlwaysNull(node.stamp()); 096 } 097 098 /** 099 * Checks whether this {@link Stamp} represents a {@linkplain Stamp#hasValues() legal} pointer 100 * stamp whose values are known to be always null. 101 * 102 * @param stamp the stamp to check 103 * @return true if this stamp represents a legal object stamp whose values are known to be 104 * always null 105 */ 106 public static boolean isPointerAlwaysNull(Stamp stamp) { 107 if (stamp instanceof AbstractPointerStamp && stamp.hasValues()) { 108 return ((AbstractPointerStamp) stamp).alwaysNull(); 109 } 110 return false; 111 } 112 113 /** 114 * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#hasValues() legal} 115 * pointer value which is known to never be null. 116 * 117 * @param node the node to check 118 * @return true if this node represents a legal object value which is known to never be null 119 */ 120 public static boolean isPointerNonNull(ValueNode node) { 121 return isPointerNonNull(node.stamp()); 122 } 123 124 /** 125 * Checks whether this {@link Stamp} represents a {@linkplain Stamp#hasValues() legal} pointer 126 * stamp whose values are known to never be null. 127 * 128 * @param stamp the stamp to check 129 * @return true if this stamp represents a legal object stamp whose values are known to be 130 * always null 131 */ 132 public static boolean isPointerNonNull(Stamp stamp) { 133 if (stamp instanceof AbstractPointerStamp) { 134 return ((AbstractPointerStamp) stamp).nonNull(); 135 } 136 return false; 137 } 138 139 /** 140 * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain ValueNode} has if it is 141 * a {@linkplain Stamp#hasValues() legal} Object value. 142 * 143 * @param node the node to check 144 * @return the Java type this value has if it is a legal Object type, null otherwise 145 */ 146 public static ResolvedJavaType typeOrNull(ValueNode node) { 147 return typeOrNull(node.stamp()); 148 } 149 150 /** 151 * Returns the {@linkplain ResolvedJavaType Java type} this {@linkplain Stamp} has if it is a 152 * {@linkplain Stamp#hasValues() legal} Object stamp. 153 * 154 * @param stamp the stamp to check 155 * @return the Java type this stamp has if it is a legal Object stamp, null otherwise 156 */ 157 public static ResolvedJavaType typeOrNull(Stamp stamp) { 158 if (stamp instanceof AbstractObjectStamp && stamp.hasValues()) { 159 return ((AbstractObjectStamp) stamp).type(); 160 } 161 return null; 162 } 163 164 /** 165 * Checks whether this {@link ValueNode} represents a {@linkplain Stamp#hasValues() legal} 166 * Object value whose Java type is known exactly. If this method returns true then the 167 * {@linkplain ResolvedJavaType Java type} returned by {@link #typeOrNull(ValueNode)} is the 168 * concrete dynamic/runtime Java type of this value. 169 * 170 * @param node the node to check 171 * @return true if this node represents a legal object value whose Java type is known exactly 172 */ 173 public static boolean isExactType(ValueNode node) { 174 return isExactType(node.stamp()); 175 } 176 177 /** 178 * Checks whether this {@link Stamp} represents a {@linkplain Stamp#hasValues() legal} Object 179 * stamp whose {@linkplain ResolvedJavaType Java type} is known exactly. If this method returns 180 * true then the Java type returned by {@link #typeOrNull(Stamp)} is the only concrete 181 * dynamic/runtime Java type possible for values of this stamp. 182 * 183 * @param stamp the stamp to check 184 * @return true if this node represents a legal object stamp whose Java type is known exactly 185 */ 186 public static boolean isExactType(Stamp stamp) { 187 if (stamp instanceof AbstractObjectStamp && stamp.hasValues()) { 188 return ((AbstractObjectStamp) stamp).isExactType(); 189 } 190 return false; 191 } 192}