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