1 /* 2 * Copyright (c) 2011, 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 jdk.vm.ci.hotspot; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 28 import jdk.vm.ci.common.JVMCIError; 29 import jdk.vm.ci.meta.JavaKind; 30 import jdk.vm.ci.meta.JavaType; 31 import jdk.vm.ci.meta.ResolvedJavaType; 32 import jdk.vm.ci.meta.Signature; 33 34 /** 35 * Represents a method signature. 36 */ 37 public class HotSpotSignature implements Signature { 38 39 private final List<String> parameters = new ArrayList<>(); 40 private final String returnType; 41 private final String originalString; 42 private ResolvedJavaType[] parameterTypes; 43 private ResolvedJavaType returnTypeCache; 44 private final HotSpotJVMCIRuntimeProvider runtime; 45 46 public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, String signature) { 47 this.runtime = runtime; 48 assert signature.length() > 0; 49 this.originalString = signature; 50 51 if (signature.charAt(0) == '(') { 52 int cur = 1; 53 while (cur < signature.length() && signature.charAt(cur) != ')') { 54 int nextCur = parseSignature(signature, cur); 55 parameters.add(signature.substring(cur, nextCur)); 56 cur = nextCur; 57 } 58 59 cur++; 60 int nextCur = parseSignature(signature, cur); 61 returnType = signature.substring(cur, nextCur); 62 assert nextCur == signature.length(); 63 } else { 64 returnType = null; 65 } 66 } 67 68 public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) { 69 this.runtime = runtime; 70 this.parameterTypes = parameterTypes.clone(); 71 this.returnTypeCache = returnType; 72 this.returnType = returnType.getName(); 73 StringBuilder sb = new StringBuilder("("); 74 for (JavaType type : parameterTypes) { 75 parameters.add(type.getName()); 76 sb.append(type.getName()); 77 } 78 sb.append(")").append(returnType.getName()); 79 this.originalString = sb.toString(); 80 assert new HotSpotSignature(runtime, originalString).equals(this); 81 } 82 83 private static int parseSignature(String signature, int start) { 84 int cur = start; 85 char first; 86 do { 87 first = signature.charAt(cur++); 88 } while (first == '['); 89 90 switch (first) { 91 case 'L': 92 while (signature.charAt(cur) != ';') { 93 cur++; 94 } 95 cur++; 96 break; 97 case 'V': 98 case 'I': 99 case 'B': 100 case 'C': 101 case 'D': 102 case 'F': 103 case 'J': 104 case 'S': 105 case 'Z': 106 break; 107 default: 108 throw new JVMCIError("Invalid character at index %d in signature: %s", cur, signature); 109 } 110 return cur; 111 } 112 113 @Override 114 public int getParameterCount(boolean withReceiver) { 115 return parameters.size() + (withReceiver ? 1 : 0); 116 } 117 118 @Override 119 public JavaKind getParameterKind(int index) { 120 return JavaKind.fromTypeString(parameters.get(index)); 121 } 122 123 private static boolean checkValidCache(ResolvedJavaType type, ResolvedJavaType accessingClass) { 124 assert accessingClass != null; 125 if (type == null) { 126 return false; 127 } else if (type instanceof HotSpotResolvedObjectTypeImpl) { 128 return ((HotSpotResolvedObjectTypeImpl) type).isDefinitelyResolvedWithRespectTo(accessingClass); 129 } 130 return true; 131 } 132 133 private static JavaType getUnresolvedOrPrimitiveType(HotSpotJVMCIRuntimeProvider runtime, String name) { 134 if (name.length() == 1) { 135 JavaKind kind = JavaKind.fromPrimitiveOrVoidTypeChar(name.charAt(0)); 136 return runtime.getHostJVMCIBackend().getMetaAccess().lookupJavaType(kind.toJavaClass()); 137 } 138 return HotSpotUnresolvedJavaType.create(runtime, name); 139 } 140 141 @Override 142 public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { 143 if (accessingClass == null) { 144 // Caller doesn't care about resolution context so return an unresolved 145 // or primitive type (primitive type resolution is context free) 146 return getUnresolvedOrPrimitiveType(runtime, parameters.get(index)); 147 } 148 if (parameterTypes == null) { 149 parameterTypes = new ResolvedJavaType[parameters.size()]; 150 } 151 152 ResolvedJavaType type = parameterTypes[index]; 153 if (!checkValidCache(type, accessingClass)) { 154 JavaType result = runtime.lookupType(parameters.get(index), (HotSpotResolvedObjectType) accessingClass, false); 155 if (result instanceof ResolvedJavaType) { 156 type = (ResolvedJavaType) result; 157 parameterTypes[index] = type; 158 } else { 159 return result; 160 } 161 } 162 return type; 163 } 164 165 @Override 166 public String toMethodDescriptor() { 167 assert originalString.equals(Signature.super.toMethodDescriptor()); 168 return originalString; 169 } 170 171 @Override 172 public JavaKind getReturnKind() { 173 return JavaKind.fromTypeString(returnType); 174 } 175 176 @Override 177 public JavaType getReturnType(ResolvedJavaType accessingClass) { 178 if (accessingClass == null) { 179 // Caller doesn't care about resolution context so return an unresolved 180 // or primitive type (primitive type resolution is context free) 181 return getUnresolvedOrPrimitiveType(runtime, returnType); 182 } 183 if (!checkValidCache(returnTypeCache, accessingClass)) { 184 JavaType result = runtime.lookupType(returnType, (HotSpotResolvedObjectType) accessingClass, false); 185 if (result instanceof ResolvedJavaType) { 186 returnTypeCache = (ResolvedJavaType) result; 187 } else { 188 return result; 189 } 190 } 191 return returnTypeCache; 192 } 193 194 @Override 195 public String toString() { 196 return "HotSpotSignature<" + originalString + ">"; 197 } 198 199 @Override 200 public boolean equals(Object obj) { 201 if (obj instanceof HotSpotSignature) { 202 HotSpotSignature other = (HotSpotSignature) obj; 203 if (other.originalString.equals(originalString)) { 204 assert other.parameters.equals(parameters); 205 assert other.returnType.equals(returnType); 206 return true; 207 } 208 } 209 return false; 210 } 211 212 @Override 213 public int hashCode() { 214 return originalString.hashCode(); 215 } 216 }