1 /* 2 * Copyright (c) 2014, 2018, 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 protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) { 76 return new KlassPointerStamp(newNonNull, newAlwaysNull, encoding); 77 } 78 79 @Override 80 public boolean isCompatible(Stamp otherStamp) { 81 if (this == otherStamp) { 82 return true; 83 } 84 if (otherStamp instanceof KlassPointerStamp) { 85 KlassPointerStamp other = (KlassPointerStamp) otherStamp; 86 return Objects.equals(this.encoding, other.encoding); 87 } 88 return false; 89 } 90 91 @Override 92 public boolean isCompatible(Constant constant) { 93 if (constant instanceof HotSpotMetaspaceConstant) { 94 return ((HotSpotMetaspaceConstant) constant).asResolvedJavaType() != null; 95 } else { 96 return super.isCompatible(constant); 97 } 98 } 99 100 @Override 101 public Stamp constant(Constant c, MetaAccessProvider meta) { 102 if (isCompressed()) { 103 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 104 return new KlassPointerStamp(false, true, encoding); 105 } 106 } else { 107 if (JavaConstant.NULL_POINTER.equals(c)) { 108 return KLASS_ALWAYS_NULL; 109 } 110 } 111 112 assert c instanceof HotSpotMetaspaceConstant; 113 assert ((HotSpotMetaspaceConstant) c).isCompressed() == isCompressed(); 114 if (nonNull()) { 115 return this; 116 } 117 if (isCompressed()) { 118 return new KlassPointerStamp(true, false, encoding); 119 } else { 120 return KLASS_NON_NULL; 121 } 122 } 123 124 @Override 125 public JavaConstant nullConstant() { 126 if (isCompressed()) { 127 return HotSpotCompressedNullConstant.COMPRESSED_NULL; 128 } else { 129 return super.nullConstant(); 130 } 131 } 132 133 @Override 134 public LIRKind getLIRKind(LIRKindTool tool) { 135 if (isCompressed()) { 136 return tool.getNarrowPointerKind(); 137 } else { 138 return super.getLIRKind(tool); 139 } 140 } 141 142 public boolean isCompressed() { 143 return encoding != null; 144 } 145 146 public CompressEncoding getEncoding() { 147 return encoding; 148 } 149 150 public KlassPointerStamp compressed(CompressEncoding newEncoding) { 151 assert !isCompressed(); 152 return new KlassPointerStamp(nonNull(), alwaysNull(), newEncoding); 153 } 154 155 public KlassPointerStamp uncompressed() { 156 assert isCompressed(); 157 return new KlassPointerStamp(nonNull(), alwaysNull()); 158 } 159 160 @Override 161 public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { 162 HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider; 163 if (isCompressed()) { 164 return hsProvider.readNarrowKlassPointerConstant(base, displacement); 165 } else { 166 return hsProvider.readKlassPointerConstant(base, displacement); 167 } 168 } 169 170 @Override 171 public int hashCode() { 172 final int prime = 31; 173 int result = super.hashCode(); 174 result = prime * result + ((encoding == null) ? 0 : encoding.hashCode()); 175 return result; 176 } 177 178 @Override 179 public boolean equals(Object obj) { 180 if (this == obj) { 181 return true; 182 } 183 if (!super.equals(obj)) { 184 return false; 185 } 186 if (!(obj instanceof KlassPointerStamp)) { 187 return false; 188 } 189 KlassPointerStamp other = (KlassPointerStamp) obj; 190 return Objects.equals(this.encoding, other.encoding); 191 } 192 193 @Override 194 public String toString() { 195 StringBuilder ret = new StringBuilder("Klass*"); 196 appendString(ret); 197 if (isCompressed()) { 198 ret.append("(compressed ").append(encoding).append(")"); 199 } 200 return ret.toString(); 201 } 202 }