001/* 002 * Copyright (c) 2011, 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 jdk.internal.jvmci.hotspot; 024 025import java.util.*; 026 027import jdk.internal.jvmci.common.*; 028import jdk.internal.jvmci.meta.*; 029 030/** 031 * Represents a method signature. 032 */ 033public class HotSpotSignature implements Signature { 034 035 private final List<String> parameters = new ArrayList<>(); 036 private final String returnType; 037 private final String originalString; 038 private ResolvedJavaType[] parameterTypes; 039 private ResolvedJavaType returnTypeCache; 040 private final HotSpotJVMCIRuntimeProvider runtime; 041 042 public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, String signature) { 043 this.runtime = runtime; 044 assert signature.length() > 0; 045 this.originalString = signature; 046 047 if (signature.charAt(0) == '(') { 048 int cur = 1; 049 while (cur < signature.length() && signature.charAt(cur) != ')') { 050 int nextCur = parseSignature(signature, cur); 051 parameters.add(signature.substring(cur, nextCur)); 052 cur = nextCur; 053 } 054 055 cur++; 056 int nextCur = parseSignature(signature, cur); 057 returnType = signature.substring(cur, nextCur); 058 assert nextCur == signature.length(); 059 } else { 060 returnType = null; 061 } 062 } 063 064 public HotSpotSignature(HotSpotJVMCIRuntimeProvider runtime, ResolvedJavaType returnType, ResolvedJavaType... parameterTypes) { 065 this.runtime = runtime; 066 this.parameterTypes = parameterTypes.clone(); 067 this.returnTypeCache = returnType; 068 this.returnType = returnType.getName(); 069 StringBuilder sb = new StringBuilder("("); 070 for (JavaType type : parameterTypes) { 071 parameters.add(type.getName()); 072 sb.append(type.getName()); 073 } 074 sb.append(")").append(returnType.getName()); 075 this.originalString = sb.toString(); 076 assert new HotSpotSignature(runtime, originalString).equals(this); 077 } 078 079 private static int parseSignature(String signature, int start) { 080 int cur = start; 081 char first; 082 do { 083 first = signature.charAt(cur++); 084 } while (first == '['); 085 086 switch (first) { 087 case 'L': 088 while (signature.charAt(cur) != ';') { 089 cur++; 090 } 091 cur++; 092 break; 093 case 'V': 094 case 'I': 095 case 'B': 096 case 'C': 097 case 'D': 098 case 'F': 099 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 Kind getParameterKind(int index) { 116 return Kind.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 Kind kind = Kind.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 Kind getReturnKind() { 169 return Kind.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}