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