use of org.codehaus.groovy.reflection.CachedMethod in project groovy-core by groovy.
the class CallSiteGenerator method writeMethod.
private static MethodVisitor writeMethod(ClassWriter cw, String name, int argumentCount, final String superClass, CachedMethod cachedMethod, String receiverType, String parameterDescription, boolean useArray) {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "call" + name, "(L" + receiverType + ";" + parameterDescription + ")Ljava/lang/Object;", null, null);
mv.visitCode();
final Label tryStart = new Label();
mv.visitLabel(tryStart);
// call for checking if method is still valid
for (int i = 0; i < argumentCount; ++i) mv.visitVarInsn(Opcodes.ALOAD, i);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, superClass, "checkCall", "(Ljava/lang/Object;" + parameterDescription + ")Z", false);
Label l0 = new Label();
mv.visitJumpInsn(Opcodes.IFEQ, l0);
// valid method branch
Class callClass = cachedMethod.getDeclaringClass().getTheClass();
boolean useInterface = callClass.isInterface();
String type = BytecodeHelper.getClassInternalName(callClass.getName());
String descriptor = BytecodeHelper.getMethodDescriptor(cachedMethod.getReturnType(), cachedMethod.getNativeParameterTypes());
// prepare call
int invokeMethodCode = Opcodes.INVOKEVIRTUAL;
if (cachedMethod.isStatic()) {
invokeMethodCode = Opcodes.INVOKESTATIC;
} else {
mv.visitVarInsn(Opcodes.ALOAD, 1);
BytecodeHelper.doCast(mv, callClass);
if (useInterface)
invokeMethodCode = Opcodes.INVOKEINTERFACE;
}
Method method = cachedMethod.setAccessible();
Class<?>[] parameters = method.getParameterTypes();
int size = parameters.length;
for (int i = 0; i < size; i++) {
if (useArray) {
// unpack argument from Object[]
mv.visitVarInsn(Opcodes.ALOAD, 2);
BytecodeHelper.pushConstant(mv, i);
mv.visitInsn(Opcodes.AALOAD);
} else {
mv.visitVarInsn(Opcodes.ALOAD, i + 2);
}
// cast argument to parameter class, inclusive unboxing
// for methods with primitive types
BytecodeHelper.doCast(mv, parameters[i]);
}
// make call
mv.visitMethodInsn(invokeMethodCode, type, cachedMethod.getName(), descriptor, invokeMethodCode == Opcodes.INVOKEINTERFACE);
// produce result
BytecodeHelper.box(mv, cachedMethod.getReturnType());
if (cachedMethod.getReturnType() == void.class) {
mv.visitInsn(Opcodes.ACONST_NULL);
}
// return
mv.visitInsn(Opcodes.ARETURN);
// fall back after method change
mv.visitLabel(l0);
for (int i = 0; i < argumentCount; ++i) mv.visitVarInsn(Opcodes.ALOAD, i);
if (!useArray) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/codehaus/groovy/runtime/ArrayUtil", "createArray", "(" + parameterDescription + ")[Ljava/lang/Object;", false);
}
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "defaultCall" + name, "(Lorg/codehaus/groovy/runtime/callsite/CallSite;L" + receiverType + ";[Ljava/lang/Object;)Ljava/lang/Object;", false);
mv.visitInsn(Opcodes.ARETURN);
// exception unwrapping for stackless exceptions
final Label tryEnd = new Label();
mv.visitLabel(tryEnd);
final Label catchStart = new Label();
mv.visitLabel(catchStart);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "unwrap", "(Lgroovy/lang/GroovyRuntimeException;)Ljava/lang/Throwable;", false);
mv.visitInsn(Opcodes.ATHROW);
mv.visitTryCatchBlock(tryStart, tryEnd, catchStart, GRE);
mv.visitMaxs(0, 0);
mv.visitEnd();
return mv;
}
use of org.codehaus.groovy.reflection.CachedMethod in project groovy by apache.
the class MetaClassImpl method addNewInstanceMethod.
/**
*Adds an instance method to this metaclass.
*
* @param method The method to be added
*/
public void addNewInstanceMethod(Method method) {
final CachedMethod cachedMethod = CachedMethod.find(method);
NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
final CachedClass declaringClass = newMethod.getDeclaringClass();
addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
}
use of org.codehaus.groovy.reflection.CachedMethod in project groovy by apache.
the class MetaClassImpl method findMatchingMethod.
private int findMatchingMethod(CachedMethod[] data, int from, int to, MetaMethod method) {
for (int j = from; j <= to; ++j) {
CachedMethod aMethod = data[j];
CachedClass[] params1 = aMethod.getParameterTypes();
CachedClass[] params2 = method.getParameterTypes();
if (params1.length == params2.length) {
boolean matches = true;
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i]) {
matches = false;
break;
}
}
if (matches) {
return j;
}
}
}
return -1;
}
use of org.codehaus.groovy.reflection.CachedMethod in project groovy by apache.
the class ClosureMetaMethod method createMethodList.
public static List<MetaMethod> createMethodList(final String name, final Class declaringClass, final Closure closure) {
List<MetaMethod> res = new ArrayList<MetaMethod>();
if (closure instanceof MethodClosure) {
MethodClosure methodClosure = (MethodClosure) closure;
Object owner = closure.getOwner();
Class ownerClass = (Class) (owner instanceof Class ? owner : owner.getClass());
for (CachedMethod method : ReflectionCache.getCachedClass(ownerClass).getMethods()) {
if (method.getName().equals(methodClosure.getMethod())) {
MetaMethod metaMethod = new MethodClosureMetaMethod(name, declaringClass, closure, method);
res.add(adjustParamTypesForStdMethods(metaMethod, name));
}
}
} else {
if (closure instanceof GeneratedClosure) {
for (CachedMethod method : ReflectionCache.getCachedClass(closure.getClass()).getMethods()) {
if (method.getName().equals("doCall")) {
MetaMethod metaMethod = new ClosureMetaMethod(name, declaringClass, closure, method);
res.add(adjustParamTypesForStdMethods(metaMethod, name));
}
}
} else {
MetaMethod metaMethod = new AnonymousMetaMethod(closure, name, declaringClass);
res.add(adjustParamTypesForStdMethods(metaMethod, name));
}
}
return res;
}
use of org.codehaus.groovy.reflection.CachedMethod in project groovy by apache.
the class DgmConverter method main.
public static void main(String[] args) throws IOException {
String targetDirectory = "target/classes/";
boolean info = (args.length == 1 && args[0].equals("--info")) || (args.length == 2 && args[0].equals("--info"));
if (info && args.length == 2) {
targetDirectory = args[1];
if (!targetDirectory.endsWith("/"))
targetDirectory += "/";
}
List<CachedMethod> cachedMethodsList = new ArrayList<CachedMethod>();
for (Class aClass : DefaultGroovyMethods.DGM_LIKE_CLASSES) {
Collections.addAll(cachedMethodsList, ReflectionCache.getCachedClass(aClass).getMethods());
}
final CachedMethod[] cachedMethods = cachedMethodsList.toArray(new CachedMethod[cachedMethodsList.size()]);
List<GeneratedMetaMethod.DgmMethodRecord> records = new ArrayList<GeneratedMetaMethod.DgmMethodRecord>();
int cur = 0;
for (CachedMethod method : cachedMethods) {
if (!method.isStatic() || !method.isPublic())
continue;
if (method.getCachedMethod().getAnnotation(Deprecated.class) != null)
continue;
if (method.getParameterTypes().length == 0)
continue;
final Class returnType = method.getReturnType();
final String className = "org/codehaus/groovy/runtime/dgm$" + cur++;
GeneratedMetaMethod.DgmMethodRecord record = new GeneratedMetaMethod.DgmMethodRecord();
records.add(record);
record.methodName = method.getName();
record.returnType = method.getReturnType();
record.parameters = method.getNativeParameterTypes();
record.className = className;
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(V1_3, ACC_PUBLIC, className, null, "org/codehaus/groovy/reflection/GeneratedMetaMethod", null);
createConstructor(cw);
final String methodDescriptor = BytecodeHelper.getMethodDescriptor(returnType, method.getNativeParameterTypes());
createInvokeMethod(method, cw, returnType, methodDescriptor);
createDoMethodInvokeMethod(method, cw, className, returnType, methodDescriptor);
createIsValidMethodMethod(method, cw, className);
cw.visitEnd();
final byte[] bytes = cw.toByteArray();
final FileOutputStream fileOutputStream = new FileOutputStream(targetDirectory + className + ".class");
fileOutputStream.write(bytes);
fileOutputStream.flush();
fileOutputStream.close();
}
GeneratedMetaMethod.DgmMethodRecord.saveDgmInfo(records, targetDirectory + "/META-INF/dgminfo");
if (info)
System.out.println("Saved " + cur + " dgm records to: " + targetDirectory + "/META-INF/dgminfo");
}
Aggregations