001/* 002 * Copyright (c) 2014, 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.hotspot.nodes.type; 024 025import java.util.*; 026 027import jdk.internal.jvmci.hotspot.*; 028import jdk.internal.jvmci.hotspot.HotSpotVMConfig.*; 029import jdk.internal.jvmci.meta.*; 030 031import com.oracle.graal.compiler.common.spi.*; 032import com.oracle.graal.compiler.common.type.*; 033 034public final class KlassPointerStamp extends MetaspacePointerStamp { 035 036 private final CompressEncoding encoding; 037 038 private final Kind kind; 039 040 public KlassPointerStamp(boolean nonNull, boolean alwaysNull, Kind kind) { 041 this(nonNull, alwaysNull, null, kind); 042 } 043 044 private KlassPointerStamp(boolean nonNull, boolean alwaysNull, CompressEncoding encoding, Kind kind) { 045 super(nonNull, alwaysNull); 046 this.encoding = encoding; 047 this.kind = kind; 048 } 049 050 @Override 051 protected AbstractPointerStamp copyWith(boolean newNonNull, boolean newAlwaysNull) { 052 return new KlassPointerStamp(newNonNull, newAlwaysNull, encoding, kind); 053 } 054 055 @Override 056 public boolean isCompatible(Stamp otherStamp) { 057 if (this == otherStamp) { 058 return true; 059 } 060 if (otherStamp instanceof KlassPointerStamp) { 061 KlassPointerStamp other = (KlassPointerStamp) otherStamp; 062 return Objects.equals(this.encoding, other.encoding); 063 } 064 return false; 065 } 066 067 @Override 068 public Stamp constant(Constant c, MetaAccessProvider meta) { 069 if (isCompressed()) { 070 if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { 071 return new KlassPointerStamp(false, true, encoding, kind); 072 } 073 } else { 074 if (JavaConstant.NULL_POINTER.equals(c)) { 075 return new KlassPointerStamp(false, true, encoding, kind); 076 } 077 } 078 079 assert c instanceof HotSpotMetaspaceConstant; 080 assert ((HotSpotMetaspaceConstant) c).isCompressed() == isCompressed(); 081 if (nonNull()) { 082 return this; 083 } 084 return new KlassPointerStamp(true, false, encoding, kind); 085 } 086 087 @Override 088 public Constant asConstant() { 089 if (alwaysNull() && isCompressed()) { 090 return HotSpotCompressedNullConstant.COMPRESSED_NULL; 091 } else { 092 return super.asConstant(); 093 } 094 } 095 096 @Override 097 public LIRKind getLIRKind(LIRKindTool tool) { 098 if (isCompressed()) { 099 return LIRKind.value(Kind.Int); 100 } else { 101 return super.getLIRKind(tool); 102 } 103 } 104 105 public boolean isCompressed() { 106 return encoding != null; 107 } 108 109 public CompressEncoding getEncoding() { 110 return encoding; 111 } 112 113 public KlassPointerStamp compressed(CompressEncoding newEncoding) { 114 assert !isCompressed(); 115 return new KlassPointerStamp(nonNull(), alwaysNull(), newEncoding, Kind.Int); 116 } 117 118 public KlassPointerStamp uncompressed() { 119 assert isCompressed(); 120 return new KlassPointerStamp(nonNull(), alwaysNull(), Kind.Long); 121 } 122 123 @Override 124 public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { 125 HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider; 126 if (isCompressed()) { 127 return hsProvider.readNarrowKlassPointerConstant(base, displacement, encoding); 128 } else { 129 return hsProvider.readKlassPointerConstant(base, displacement); 130 } 131 } 132 133 @Override 134 public int hashCode() { 135 final int prime = 31; 136 int result = super.hashCode(); 137 result = prime * result + ((encoding == null) ? 0 : encoding.hashCode()); 138 return result; 139 } 140 141 @Override 142 public boolean equals(Object obj) { 143 if (this == obj) { 144 return true; 145 } 146 if (!super.equals(obj)) { 147 return false; 148 } 149 if (!(obj instanceof KlassPointerStamp)) { 150 return false; 151 } 152 KlassPointerStamp other = (KlassPointerStamp) obj; 153 return Objects.equals(this.encoding, other.encoding); 154 } 155 156 @Override 157 public String toString() { 158 StringBuilder ret = new StringBuilder("Klass*"); 159 appendString(ret); 160 if (isCompressed()) { 161 ret.append("(compressed ").append(encoding).append(")"); 162 } 163 return ret.toString(); 164 } 165 166 @Override 167 public Kind getStackKind() { 168 return isCompressed() ? Kind.Int : Kind.Long; 169 } 170}