Search in sources :

Example 16 with CachedMethod

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;
}
Also used : Label(org.objectweb.asm.Label) CachedClass(org.codehaus.groovy.reflection.CachedClass) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) Method(java.lang.reflect.Method) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 17 with CachedMethod

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()));
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 18 with CachedMethod

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;
}
Also used : CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 19 with CachedMethod

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;
}
Also used : MetaMethod(groovy.lang.MetaMethod) ArrayList(java.util.ArrayList) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure)

Example 20 with CachedMethod

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");
}
Also used : ArrayList(java.util.ArrayList) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) ClassWriter(org.objectweb.asm.ClassWriter) FileOutputStream(java.io.FileOutputStream) CachedClass(org.codehaus.groovy.reflection.CachedClass) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod)

Aggregations

CachedMethod (org.codehaus.groovy.reflection.CachedMethod)23 CachedClass (org.codehaus.groovy.reflection.CachedClass)19 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)10 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)10 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)8 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)6 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)6 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)6 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)6 Method (java.lang.reflect.Method)5 ArrayList (java.util.ArrayList)4 MetaMethodIndex (org.codehaus.groovy.runtime.metaclass.MetaMethodIndex)4 MetaMethod (groovy.lang.MetaMethod)2 PropertyDescriptor (java.beans.PropertyDescriptor)2 FileOutputStream (java.io.FileOutputStream)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 GeneratedClosure (org.codehaus.groovy.runtime.GeneratedClosure)2 MethodClosure (org.codehaus.groovy.runtime.MethodClosure)2 ClassWriter (org.objectweb.asm.ClassWriter)2 Label (org.objectweb.asm.Label)2