1 /* 2 * Copyright (c) 2014, 2015, 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 package org.graalvm.compiler.hotspot.nodes.type; 24 25 import java.util.Objects; 26 27 import org.graalvm.compiler.core.common.LIRKind; 28 import org.graalvm.compiler.core.common.spi.LIRKindTool; 29 import org.graalvm.compiler.core.common.type.AbstractPointerStamp; 30 import org.graalvm.compiler.core.common.type.Stamp; 31 import org.graalvm.compiler.hotspot.CompressEncoding; 32 33 import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; 34 import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; 35 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 36 import jdk.vm.ci.meta.Constant; 37 import jdk.vm.ci.meta.JavaConstant; 38 import jdk.vm.ci.meta.MemoryAccessProvider; 39 import jdk.vm.ci.meta.MetaAccessProvider; 40 41 public final class KlassPointerStamp extends MetaspacePointerStamp { 42 43 private static final KlassPointerStamp KLASS = new KlassPointerStamp(false, false); 44 45 private static final KlassPointerStamp KLASS_NON_NULL = new KlassPointerStamp(true, false); 46 47 private static final KlassPointerStamp KLASS_ALWAYS_NULL = new KlassPointerStamp(false, true); 48 49 private final CompressEncoding encoding; 50 51 public static KlassPointerStamp klass() { 52 return KLASS; 53 } 54 55 public static KlassPointerStamp klassNonNull() { 56 return KLASS_NON_NULL; 57 } 58 59 public static KlassPointerStamp klassAlwaysNull() { 60 return KLASS_ALWAYS_NULL; 61 } 62 63 private KlassPointerStamp(boolean nonNull, boolean alwaysNull) { 64 this(nonNull, alwaysNull, null); 65 } 66 67 private KlassPointerStamp(boolean nonNull, boolean alwaysNull, CompressEncoding encoding) { 68 super(nonNull, alwaysNull); 69 this.encoding = encoding; 70 } 71 72 @Override 73 protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) { 74 return new KlassPointerStamp(newNonNull, newAlwaysNull, encoding); 75 } 76 77 @Override 78 public boolean isCompatible(Stamp otherStamp) { 79 if (this == otherStamp) { 80 return true; 81 } 82 if (otherStamp instanceof KlassPointerStamp) { 83 KlassPointerStamp other = (KlassPointerStamp) otherStamp; 84 return Objects.equals(this.encoding, other.encoding); 85 } 86 return false; 87 } 88 89 @Override 90 public boolean isCompatible(Constant constant) { 91 if (constant instanceof HotSpotMetaspaceConstant) { 92 return ((HotSpotMetaspaceConstant) constant).asResolvedJavaType() != null; 93 } else { 94 return super.isCompatible(constant); 95 } 96 } 97 98 @Override 99 public Stamp constant(Constant c, MetaAccessProvider meta) { 100 if (isCompressed()) { 101 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 102 return new KlassPointerStamp(false, true, encoding); 103 } 104 } else { 105 if (JavaConstant.NULL_POINTER.equals(c)) { 106 return KLASS_ALWAYS_NULL; 107 } 108 } 109 110 assert c instanceof HotSpotMetaspaceConstant; 111 assert ((HotSpotMetaspaceConstant) c).isCompressed() == isCompressed(); 112 if (nonNull()) { 113 return this; 114 } 115 if (isCompressed()) { 116 return new KlassPointerStamp(true, false, encoding); 117 } else { 118 return KLASS_NON_NULL; 119 } 120 } 121 122 @Override 123 public Constant asConstant() { 124 if (alwaysNull() && isCompressed()) { 125 return HotSpotCompressedNullConstant.COMPRESSED_NULL; 126 } else { 127 return super.asConstant(); 128 } 129 } 130 131 @Override 132 public LIRKind getLIRKind(LIRKindTool tool) { 133 if (isCompressed()) { 134 return ((HotSpotLIRKindTool) tool).getNarrowPointerKind(); 135 } else { 136 return super.getLIRKind(tool); 137 } 138 } 139 140 public boolean isCompressed() { 141 return encoding != null; 142 } 143 144 public CompressEncoding getEncoding() { 145 return encoding; 146 } 147 148 public KlassPointerStamp compressed(CompressEncoding newEncoding) { 149 assert !isCompressed(); 150 return new KlassPointerStamp(nonNull(), alwaysNull(), newEncoding); 151 } 152 153 public KlassPointerStamp uncompressed() { 154 assert isCompressed(); 155 return new KlassPointerStamp(nonNull(), alwaysNull()); 156 } 157 158 @Override 159 public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { 160 HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider; 161 if (isCompressed()) { 162 return hsProvider.readNarrowKlassPointerConstant(base, displacement); 163 } else { 164 return hsProvider.readKlassPointerConstant(base, displacement); 165 } 166 } 167 168 @Override 169 public int hashCode() { 170 final int prime = 31; 171 int result = super.hashCode(); 172 result = prime * result + ((encoding == null) ? 0 : encoding.hashCode()); 173 return result; 174 } 175 176 @Override 177 public boolean equals(Object obj) { 178 if (this == obj) { 179 return true; 180 } 181 if (!super.equals(obj)) { 182 return false; 183 } 184 if (!(obj instanceof KlassPointerStamp)) { 185 return false; 186 } 187 KlassPointerStamp other = (KlassPointerStamp) obj; 188 return Objects.equals(this.encoding, other.encoding); 189 } 190 191 @Override 192 public String toString() { 193 StringBuilder ret = new StringBuilder("Klass*"); 194 appendString(ret); 195 if (isCompressed()) { 196 ret.append("(compressed ").append(encoding).append(")"); 197 } 198 return ret.toString(); 199 } 200 }