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.Constants;
017 import org.jikesrvm.classloader.Atom;
018 import org.jikesrvm.classloader.BootstrapClassLoader;
019 import org.jikesrvm.classloader.RVMClass;
020 import org.jikesrvm.classloader.RVMField;
021 import org.jikesrvm.classloader.RVMMember;
022 import org.jikesrvm.classloader.RVMMethod;
023 import org.jikesrvm.classloader.MethodReference;
024 import org.jikesrvm.classloader.NormalMethod;
025 import org.jikesrvm.classloader.TypeReference;
026
027 /**
028 * Helper class for retrieving entrypoints. Entrypoints are fields and
029 * methods of the virtual machine that are needed by compiler-generated
030 * machine code or C runtime code.
031 */
032 public class EntrypointHelper {
033 /**
034 * Get description of virtual machine component (field or method).
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 VM._assert(Constants.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 }