/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.runtime; import org.jikesrvm.VM; import org.jikesrvm.Constants; import org.jikesrvm.classloader.Atom; import org.jikesrvm.classloader.BootstrapClassLoader; import org.jikesrvm.classloader.RVMClass; import org.jikesrvm.classloader.RVMField; import org.jikesrvm.classloader.RVMMember; import org.jikesrvm.classloader.RVMMethod; import org.jikesrvm.classloader.MethodReference; import org.jikesrvm.classloader.NormalMethod; import org.jikesrvm.classloader.TypeReference; /** * Helper class for retrieving entrypoints. Entrypoints are fields and * methods of the virtual machine that are needed by compiler-generated * machine code or C runtime code. */ public class EntrypointHelper { /** * Get description of virtual machine component (field or method). * Note: This is method is intended for use only by VM classes that need * to address their own fields and methods in the runtime virtual machine * image. It should not be used for general purpose class loading. * @param classDescriptor class descriptor - something like "Lorg/jikesrvm/RuntimeEntrypoints;" * @param memberName member name - something like "invokestatic" * @param memberDescriptor member descriptor - something like "()V" * @return corresponding RVMMember object */ private static RVMMember getMember(String classDescriptor, String memberName, String memberDescriptor) { Atom clsDescriptor = Atom.findOrCreateAsciiAtom(classDescriptor); Atom memName = Atom.findOrCreateAsciiAtom(memberName); Atom memDescriptor = Atom.findOrCreateAsciiAtom(memberDescriptor); try { TypeReference tRef = TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), clsDescriptor); RVMClass cls = (RVMClass) tRef.resolve(); cls.resolve(); RVMMember member; if ((member = cls.findDeclaredField(memName, memDescriptor)) != null) { return member; } if ((member = cls.findDeclaredMethod(memName, memDescriptor)) != null) { return member; } } catch (Exception e) { e.printStackTrace(); } // The usual causes for getMember() to fail are: // 1. you mispelled the class name, member name, or member signature // 2. the class containing the specified member didn't get compiled // VM.sysWrite("Entrypoints.getMember: can't resolve class=" + classDescriptor + " member=" + memberName + " desc=" + memberDescriptor + "\n"); VM._assert(Constants.NOT_REACHED); return null; // placate jikes } public static NormalMethod getMethod(String klass, String member, String descriptor, final boolean runtimeServiceMethod) { NormalMethod m = (NormalMethod) getMember(klass, member, descriptor); m.setRuntimeServiceMethod(runtimeServiceMethod); return m; } public static NormalMethod getMethod(String klass, String member, String descriptor) { return getMethod(klass, member, descriptor, true); } private static String makeDescriptor(Class<?>... argTypes) { Class<?> lastClass = null; StringBuilder result = new StringBuilder("("); for (Class<?> c: argTypes) { if (lastClass != null) { result.append(TypeReference.findOrCreate(lastClass).getName().toString()); } lastClass = c; } result.append(")").append(TypeReference.findOrCreate(lastClass).getName().toString()); return result.toString(); } public static RVMMethod getMethod(Class<?> klass, Atom member, Class<?>... argTypes) { if (!VM.runningVM) { // avoid compiling this code into the boot image try { TypeReference tRef = TypeReference.findOrCreate(klass); RVMClass cls = tRef.resolve().asClass(); cls.resolve(); Atom descriptor = Atom.findOrCreateAsciiAtom(makeDescriptor(argTypes)); RVMMethod method = cls.findDeclaredMethod(member, descriptor); if (method != null) { return method; } } catch(Throwable t) { throw new Error("Entrypoints.getMethod: can't resolve class=" + klass + " member=" + member + " desc=" + makeDescriptor(argTypes), t); } } throw new Error("Entrypoints.getMethod: can't resolve class=" + klass + " member=" + member + " desc=" + makeDescriptor(argTypes)); } public static MethodReference getMethodReference(Class<?> klass, Atom member, Class<?>... argTypes) { if (!VM.runningVM) { // avoid compiling this code into the boot image TypeReference tRef = TypeReference.findOrCreate(klass); if (tRef.resolve().isClassType()) { return getMethod(klass, member, argTypes).getMemberRef().asMethodReference(); } else { // handle method references to unboxed types Atom descriptor = Atom.findOrCreateAsciiAtom(makeDescriptor(argTypes)); return MethodReference.findOrCreate(tRef, member, descriptor); } } throw new Error("Entrypoints.getMethod: can't resolve class=" + klass + " member=" + member + " desc=" + makeDescriptor(argTypes)); } public static RVMField getField(String klass, String member, String descriptor) { return (RVMField) getMember(klass, member, descriptor); } /** * Get description of virtual machine field. * @param klass class containing field * @param member member name - something like "invokestatic" * @param type of field * @return corresponding RVMField */ public static RVMField getField(Class<?> klass, String member, Class<?> type) { if (!VM.runningVM) { // avoid compiling this code into the boot image try { TypeReference klassTRef = TypeReference.findOrCreate(klass); RVMClass cls = klassTRef.resolve().asClass(); cls.resolve(); Atom memName = Atom.findOrCreateAsciiAtom(member); Atom typeName = TypeReference.findOrCreate(type).getName(); RVMField field = cls.findDeclaredField(memName, typeName); if (field != null) { return field; } } catch(Throwable t) { throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + type, t); } } throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + type); } /** * Get description of virtual machine field. * @param klass class containing field * @param member member name - something like "invokestatic" * @param type of field * @return corresponding RVMField */ static RVMField getField(String klass, String member, Class<?> type) { if (!VM.runningVM) { // avoid compiling this code into the boot image try { TypeReference tRef = TypeReference.findOrCreate(klass); RVMClass cls = tRef.resolve().asClass(); cls.resolve(); Atom memName = Atom.findOrCreateAsciiAtom(member); Atom typeName = TypeReference.findOrCreate(type).getName(); RVMField field = cls.findDeclaredField(memName, typeName); if (field != null) { return field; } } catch(Throwable t) { throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + type, t); } } throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + type); } /** * Get description of virtual machine method. * @param klass class containing method * @param member member name - something like "invokestatic" * @param descriptor member descriptor - something like "()V" * @return corresponding RVMMethod */ public static NormalMethod getMethod(Class<?> klass, String member, String descriptor) { if (!VM.runningVM) { // avoid compiling this code into the boot image try { TypeReference klassTRef = TypeReference.findOrCreate(klass); RVMClass cls = klassTRef.resolve().asClass(); cls.resolve(); Atom memName = Atom.findOrCreateAsciiAtom(member); Atom memDescriptor = Atom.findOrCreateAsciiAtom(descriptor); NormalMethod m = (NormalMethod)cls.findDeclaredMethod(memName, memDescriptor); if (m != null) { m.setRuntimeServiceMethod(true); return m; } } catch(Throwable t) { throw new Error("Entrypoints.getField: can't resolve class=" + klass + " member=" + member + " desc=" + descriptor, t); } } throw new Error("Entrypoints.getMethod: can't resolve class=" + klass + " method=" + member + " desc=" + descriptor); } }