001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.runtime; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.classloader.Atom; 017 import org.jikesrvm.classloader.BootstrapClassLoader; 018 import org.jikesrvm.classloader.RVMClass; 019 import org.jikesrvm.classloader.RVMField; 020 import org.jikesrvm.classloader.RVMMember; 021 import org.jikesrvm.classloader.RVMMethod; 022 import org.jikesrvm.classloader.MethodReference; 023 import org.jikesrvm.classloader.NormalMethod; 024 import org.jikesrvm.classloader.TypeReference; 025 026 /** 027 * Helper class for retrieving entrypoints. Entrypoints are fields and 028 * methods of the virtual machine that are needed by compiler-generated 029 * machine code or C runtime code. 030 */ 031 public class EntrypointHelper { 032 /** 033 * Get description of virtual machine component (field or method). 034 * <p> 035 * Note: This is method is intended for use only by VM classes that need 036 * to address their own fields and methods in the runtime virtual machine 037 * image. It should not be used for general purpose class loading. 038 * @param classDescriptor class descriptor - something like "Lorg/jikesrvm/RuntimeEntrypoints;" 039 * @param memberName member name - something like "invokestatic" 040 * @param memberDescriptor member descriptor - something like "()V" 041 * @return corresponding RVMMember object 042 */ 043 private static RVMMember getMember(String classDescriptor, String memberName, String memberDescriptor) { 044 Atom clsDescriptor = Atom.findOrCreateAsciiAtom(classDescriptor); 045 Atom memName = Atom.findOrCreateAsciiAtom(memberName); 046 Atom memDescriptor = Atom.findOrCreateAsciiAtom(memberDescriptor); 047 try { 048 TypeReference tRef = 049 TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), clsDescriptor); 050 RVMClass cls = (RVMClass) tRef.resolve(); 051 cls.resolve(); 052 053 RVMMember member; 054 if ((member = cls.findDeclaredField(memName, memDescriptor)) != null) { 055 return member; 056 } 057 if ((member = cls.findDeclaredMethod(memName, memDescriptor)) != null) { 058 return member; 059 } 060 } catch (Exception e) { 061 e.printStackTrace(); 062 } 063 // The usual causes for getMember() to fail are: 064 // 1. you mispelled the class name, member name, or member signature 065 // 2. the class containing the specified member didn't get compiled 066 // 067 VM.sysWrite("Entrypoints.getMember: can't resolve class=" + 068 classDescriptor + 069 " member=" + 070 memberName + 071 " desc=" + 072 memberDescriptor + 073 "\n"); 074 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 075 return null; // placate jikes 076 } 077 078 public static NormalMethod getMethod(String klass, String member, String descriptor, final boolean runtimeServiceMethod) { 079 NormalMethod m = (NormalMethod) getMember(klass, member, descriptor); 080 m.setRuntimeServiceMethod(runtimeServiceMethod); 081 return m; 082 } 083 084 public static NormalMethod getMethod(String klass, String member, String descriptor) { 085 return getMethod(klass, member, descriptor, true); 086 } 087 088 private static String makeDescriptor(Class<?>... argTypes) { 089 Class<?> lastClass = null; 090 StringBuilder result = new StringBuilder("("); 091 for (Class<?> c: argTypes) { 092 if (lastClass != null) { 093 result.append(TypeReference.findOrCreate(lastClass).getName().toString()); 094 } 095 lastClass = c; 096 } 097 result.append(")").append(TypeReference.findOrCreate(lastClass).getName().toString()); 098 return result.toString(); 099 } 100 101 public static RVMMethod getMethod(Class<?> klass, Atom member, Class<?>... argTypes) { 102 if (!VM.runningVM) { // avoid compiling this code into the boot image 103 try { 104 TypeReference tRef = TypeReference.findOrCreate(klass); 105 RVMClass cls = tRef.resolve().asClass(); 106 cls.resolve(); 107 108 Atom descriptor = Atom.findOrCreateAsciiAtom(makeDescriptor(argTypes)); 109 110 RVMMethod method = cls.findDeclaredMethod(member, descriptor); 111 if (method != null) { 112 return method; 113 } 114 } catch(Throwable t) { 115 throw new Error("Entrypoints.getMethod: can't resolve class=" + 116 klass + " member=" + member + " desc=" + makeDescriptor(argTypes), t); 117 } 118 } 119 throw new Error("Entrypoints.getMethod: can't resolve class=" + 120 klass + " member=" + member + " desc=" + makeDescriptor(argTypes)); 121 } 122 123 public static MethodReference getMethodReference(Class<?> klass, Atom member, Class<?>... argTypes) { 124 if (!VM.runningVM) { // avoid compiling this code into the boot image 125 TypeReference tRef = TypeReference.findOrCreate(klass); 126 if (tRef.resolve().isClassType()) { 127 return getMethod(klass, member, argTypes).getMemberRef().asMethodReference(); 128 } else { // handle method references to unboxed types 129 Atom descriptor = Atom.findOrCreateAsciiAtom(makeDescriptor(argTypes)); 130 return MethodReference.findOrCreate(tRef, member, descriptor); 131 } 132 } 133 throw new Error("Entrypoints.getMethod: can't resolve class=" + 134 klass + " member=" + member + " desc=" + makeDescriptor(argTypes)); 135 } 136 137 public static RVMField getField(String klass, String member, String descriptor) { 138 return (RVMField) getMember(klass, member, descriptor); 139 } 140 141 /** 142 * Get description of virtual machine field. 143 * @param klass class containing field 144 * @param member member name - something like "invokestatic" 145 * @param type of field 146 * @return corresponding RVMField 147 */ 148 public static RVMField getField(Class<?> klass, String member, Class<?> type) { 149 if (!VM.runningVM) { // avoid compiling this code into the boot image 150 try { 151 TypeReference klassTRef = TypeReference.findOrCreate(klass); 152 RVMClass cls = klassTRef.resolve().asClass(); 153 cls.resolve(); 154 155 Atom memName = Atom.findOrCreateAsciiAtom(member); 156 Atom typeName = TypeReference.findOrCreate(type).getName(); 157 158 RVMField field = cls.findDeclaredField(memName, typeName); 159 if (field != null) { 160 return field; 161 } 162 } catch(Throwable t) { 163 throw new Error("Entrypoints.getField: can't resolve class=" + 164 klass + " member=" + member + " desc=" + type, t); 165 } 166 } 167 throw new Error("Entrypoints.getField: can't resolve class=" + 168 klass + " member=" + member + " desc=" + type); 169 } 170 171 /** 172 * Get description of virtual machine field. 173 * @param klass class containing field 174 * @param member member name - something like "invokestatic" 175 * @param type of field 176 * @return corresponding RVMField 177 */ 178 static RVMField getField(String klass, String member, Class<?> type) { 179 if (!VM.runningVM) { // avoid compiling this code into the boot image 180 try { 181 TypeReference tRef = TypeReference.findOrCreate(klass); 182 RVMClass cls = tRef.resolve().asClass(); 183 cls.resolve(); 184 185 Atom memName = Atom.findOrCreateAsciiAtom(member); 186 Atom typeName = TypeReference.findOrCreate(type).getName(); 187 188 RVMField field = cls.findDeclaredField(memName, typeName); 189 if (field != null) { 190 return field; 191 } 192 } catch(Throwable t) { 193 throw new Error("Entrypoints.getField: can't resolve class=" + 194 klass + " member=" + member + " desc=" + type, t); 195 } 196 } 197 throw new Error("Entrypoints.getField: can't resolve class=" + 198 klass + " member=" + member + " desc=" + type); 199 } 200 201 /** 202 * Get description of virtual machine method. 203 * @param klass class containing method 204 * @param member member name - something like "invokestatic" 205 * @param descriptor member descriptor - something like "()V" 206 * @return corresponding RVMMethod 207 */ 208 public static NormalMethod getMethod(Class<?> klass, String member, String descriptor) { 209 if (!VM.runningVM) { // avoid compiling this code into the boot image 210 try { 211 TypeReference klassTRef = TypeReference.findOrCreate(klass); 212 RVMClass cls = klassTRef.resolve().asClass(); 213 cls.resolve(); 214 215 Atom memName = Atom.findOrCreateAsciiAtom(member); 216 Atom memDescriptor = Atom.findOrCreateAsciiAtom(descriptor); 217 218 NormalMethod m = (NormalMethod)cls.findDeclaredMethod(memName, memDescriptor); 219 if (m != null) { 220 m.setRuntimeServiceMethod(true); 221 return m; 222 } 223 } catch(Throwable t) { 224 throw new Error("Entrypoints.getField: can't resolve class=" + 225 klass + " member=" + member + " desc=" + descriptor, t); 226 } 227 } 228 throw new Error("Entrypoints.getMethod: can't resolve class=" + 229 klass + " method=" + member + " desc=" + descriptor); 230 } 231 }