Search in sources :

Example 6 with Type

use of soot.Type in project robovm by robovm.

the class LambdaClassGenerator method createForwardingMethod.

private void createForwardingMethod(SootClass caller, String lambdaClassName, ClassWriter cw, String name, List<Type> parameters, Type returnType, List<Type> invokedParameters, SootMethodType samMethodType, SootMethodHandle implMethod, SootMethodType instantiatedMethodType, boolean isBridgeMethod) {
    String descriptor = Types.getDescriptor(parameters, returnType);
    String implClassName = implMethod.getMethodRef().declaringClass().getName().replace('.', '/');
    int accessFlags = ACC_PUBLIC | (isBridgeMethod ? ACC_BRIDGE : 0);
    MethodVisitor mv = cw.visitMethod(accessFlags, name, descriptor, null, null);
    mv.visitCode();
    // figure out the invoke op code for the lambda implementation
    // as well as if it's an instance method.
    int invokeOpCode = INVOKESTATIC;
    boolean isInstanceMethod = false;
    switch(implMethod.getReferenceKind()) {
        case SootMethodHandle.REF_invokeInterface:
            invokeOpCode = INVOKEINTERFACE;
            isInstanceMethod = true;
            break;
        case SootMethodHandle.REF_invokeSpecial:
            invokeOpCode = INVOKESPECIAL;
            isInstanceMethod = true;
            break;
        case SootMethodHandle.REF_newInvokeSpecial:
            invokeOpCode = INVOKESPECIAL;
            break;
        case SootMethodHandle.REF_invokeStatic:
            invokeOpCode = INVOKESTATIC;
            break;
        case SootMethodHandle.REF_invokeVirtual:
            invokeOpCode = INVOKEVIRTUAL;
            isInstanceMethod = true;
            break;
        default:
            throw new CompilerException("Unknown invoke type: " + implMethod.getReferenceKind());
    }
    GeneratorAdapter caster = new GeneratorAdapter(mv, accessFlags, name, descriptor);
    // push the arguments
    pushArguments(caller, lambdaClassName, mv, caster, parameters, invokedParameters, implMethod, instantiatedMethodType, isInstanceMethod);
    // generate a descriptor for the lambda implementation
    // to invoke based on the parameters. If the lambda
    // is an instance method, we need to remove the first
    // parameter for the descriptor generation as it's
    // not part of the method signature.
    String implDescriptor = null;
    List<Type> paramTypes = new ArrayList<Type>(implMethod.getMethodType().getParameterTypes());
    if (isInstanceMethod)
        paramTypes.remove(0);
    implDescriptor = Types.getDescriptor(paramTypes, implMethod.getMethodType().getReturnType());
    // call the lambda implementation
    mv.visitMethodInsn(invokeOpCode, implClassName, implMethod.getMethodRef().name(), implDescriptor, invokeOpCode == INVOKEINTERFACE);
    // emit the return instruction based on the return type
    createForwardingMethodReturn(mv, caster, returnType, samMethodType, implMethod, instantiatedMethodType);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
}
Also used : RefType(soot.RefType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) Type(soot.Type) PrimType(soot.PrimType) VoidType(soot.VoidType) LongType(soot.LongType) SootMethodType(soot.SootMethodType) ArrayList(java.util.ArrayList) CompilerException(org.robovm.compiler.CompilerException) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 7 with Type

use of soot.Type in project robovm by robovm.

the class LambdaClassGenerator method createFactory.

private String createFactory(String lambdaClassName, ClassWriter cw, SootMethodRef invokedType, SootMethodType samMethodType, SootMethodHandle implMethod, SootMethodType instantiatedMethodType) {
    MethodVisitor mv = cw.visitMethod(ACC_STATIC, "get$Lambda", Types.getDescriptor(invokedType.parameterTypes(), invokedType.returnType()), null, null);
    mv.visitCode();
    mv.visitTypeInsn(NEW, lambdaClassName);
    mv.visitInsn(DUP);
    int i = 0;
    for (Object obj : invokedType.parameterTypes()) {
        Type captureType = (Type) obj;
        mv.visitVarInsn(loadOpcodeForType(captureType), i);
        i += slotsForType(captureType);
    }
    mv.visitMethodInsn(INVOKESPECIAL, lambdaClassName, "<init>", Types.getDescriptor(invokedType.parameterTypes(), VoidType.v()), false);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(-1, -1);
    mv.visitEnd();
    return "get$Lambda";
}
Also used : RefType(soot.RefType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) Type(soot.Type) PrimType(soot.PrimType) VoidType(soot.VoidType) LongType(soot.LongType) SootMethodType(soot.SootMethodType) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 8 with Type

use of soot.Type in project robovm by robovm.

the class LambdaClassGenerator method generate.

public LambdaClass generate(SootClass caller, String invokedName, SootMethodRef invokedType, SootMethodType samMethodType, SootMethodHandle implMethod, SootMethodType instantiatedMethodType, List<Type> markerInterfaces, List<SootMethodType> bridgeMethods) {
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    String lambdaClassName = caller.getName().replace('.', '/') + "$$Lambda$" + (counter++);
    String functionalInterface = invokedType.returnType().toString().replace('.', '/');
    List<String> interfaces = new ArrayList<String>();
    interfaces.add(functionalInterface);
    for (Type markerInterface : markerInterfaces) {
        interfaces.add(markerInterface.toString().replace('.', '/'));
    }
    cw.visit(CLASS_VERSION, ACC_FINAL + ACC_SUPER + ACC_SYNTHETIC, lambdaClassName, null, "java/lang/Object", interfaces.toArray(new String[interfaces.size()]));
    String targetMethod = "<init>";
    createFieldsAndConstructor(lambdaClassName, cw, invokedType, samMethodType, implMethod, instantiatedMethodType);
    // of the lambda by LambdaPlugin.
    if (!invokedType.parameterTypes().isEmpty()) {
        targetMethod = createFactory(lambdaClassName, cw, invokedType, samMethodType, implMethod, instantiatedMethodType);
    }
    // forward the lambda method
    createForwardingMethod(caller, lambdaClassName, cw, invokedName, samMethodType.getParameterTypes(), samMethodType.getReturnType(), invokedType.parameterTypes(), samMethodType, implMethod, instantiatedMethodType, false);
    // create any bridge methods necessary
    for (SootMethodType bridgeMethod : bridgeMethods) {
        createForwardingMethod(caller, lambdaClassName, cw, invokedName, bridgeMethod.getParameterTypes(), bridgeMethod.getReturnType(), invokedType.parameterTypes(), samMethodType, implMethod, instantiatedMethodType, true);
    }
    cw.visitEnd();
    return new LambdaClass(lambdaClassName, cw.toByteArray(), targetMethod, invokedType.parameterTypes(), invokedType.returnType());
}
Also used : RefType(soot.RefType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) Type(soot.Type) PrimType(soot.PrimType) VoidType(soot.VoidType) LongType(soot.LongType) SootMethodType(soot.SootMethodType) SootMethodType(soot.SootMethodType) ArrayList(java.util.ArrayList) ClassWriter(org.objectweb.asm.ClassWriter)

Example 9 with Type

use of soot.Type in project robovm by robovm.

the class ObjCMemberPlugin method getMsgSendSuperMethod.

@SuppressWarnings("unchecked")
private SootMethod getMsgSendSuperMethod(String selectorName, SootMethod method) {
    List<Type> paramTypes = new ArrayList<>();
    paramTypes.add(org_robovm_objc_ObjCSuper.getType());
    paramTypes.add(org_robovm_objc_Selector.getType());
    paramTypes.addAll(method.getParameterTypes());
    SootMethod m = new SootMethod("$m$super$" + selectorName.replace(':', '$'), paramTypes, method.getReturnType(), STATIC | PRIVATE | NATIVE);
    copyAnnotations(method, m, false);
    createGenericSignatureForMsgSend(method, m, paramTypes, false);
    return m;
}
Also used : RefType(soot.RefType) BooleanType(soot.BooleanType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) Type(soot.Type) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) RefLikeType(soot.RefLikeType) PrimType(soot.PrimType) VoidType(soot.VoidType) ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod)

Example 10 with Type

use of soot.Type in project robovm by robovm.

the class ObjCMemberPlugin method init.

private void init(Config config) {
    if (initialized) {
        return;
    }
    this.config = config;
    if (config.getClazzes().load(OBJC_OBJECT.replace('.', '/')) == null) {
        initialized = true;
        return;
    }
    SootResolver r = SootResolver.v();
    // These have to be resolved to HIERARCHY so that isPhantom() works
    // properly
    org_robovm_objc_ObjCObject = r.resolveClass(OBJC_OBJECT, SootClass.HIERARCHY);
    org_robovm_objc_ObjCExtensions = r.resolveClass(OBJC_EXTENSIONS, SootClass.HIERARCHY);
    // These only have to be DANGLING
    org_robovm_objc_ObjCClass = r.makeClassRef(OBJC_CLASS);
    org_robovm_objc_ObjCSuper = r.makeClassRef(OBJC_SUPER);
    org_robovm_objc_ObjCRuntime = r.makeClassRef(OBJC_RUNTIME);
    org_robovm_objc_Selector = r.makeClassRef(SELECTOR);
    org_robovm_apple_foundation_NSObject = r.makeClassRef(NS_OBJECT);
    org_robovm_apple_foundation_NSObject$Marshaler = r.makeClassRef(NS_OBJECT$MARSHALER);
    org_robovm_apple_foundation_NSString$AsStringMarshaler = r.makeClassRef(NS_STRING$AS_STRING_MARSHALER);
    org_robovm_objc_$M = r.makeClassRef($M);
    org_robovm_apple_uikit_UIEvent = r.makeClassRef(UI_EVENT);
    org_robovm_apple_foundation_NSArray = r.makeClassRef(NS_ARRAY);
    SootClass java_lang_Object = r.makeClassRef("java.lang.Object");
    java_lang_String = r.makeClassRef("java.lang.String");
    java_lang_Class = r.makeClassRef("java.lang.Class");
    org_robovm_objc_Selector_register = Scene.v().makeMethodRef(org_robovm_objc_Selector, "register", Arrays.<Type>asList(java_lang_String.getType()), org_robovm_objc_Selector.getType(), true);
    org_robovm_objc_ObjCObject_getSuper = Scene.v().makeMethodRef(org_robovm_objc_ObjCObject, "getSuper", Collections.<Type>emptyList(), org_robovm_objc_ObjCSuper.getType(), false);
    org_robovm_objc_ObjCObject_updateStrongRef = Scene.v().makeMethodRef(org_robovm_objc_ObjCObject, "updateStrongRef", Arrays.<Type>asList(java_lang_Object.getType(), java_lang_Object.getType()), VoidType.v(), false);
    org_robovm_objc_ObjCClass_getByType = Scene.v().makeMethodRef(org_robovm_objc_ObjCClass, "getByType", Arrays.<Type>asList(java_lang_Class.getType()), org_robovm_objc_ObjCClass.getType(), true);
    org_robovm_objc_ObjCRuntime_bind = Scene.v().makeMethodRef(org_robovm_objc_ObjCRuntime, "bind", Arrays.<Type>asList(java_lang_Class.getType()), VoidType.v(), true);
    org_robovm_objc_ObjCObject_customClass = Scene.v().makeFieldRef(org_robovm_objc_ObjCObject, "customClass", BooleanType.v(), false);
    org_robovm_objc_ObjCExtensions_updateStrongRef = Scene.v().makeMethodRef(org_robovm_objc_ObjCExtensions, "updateStrongRef", Arrays.<Type>asList(org_robovm_objc_ObjCObject.getType(), java_lang_Object.getType(), java_lang_Object.getType()), VoidType.v(), true);
    initialized = true;
}
Also used : RefType(soot.RefType) BooleanType(soot.BooleanType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) Type(soot.Type) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) RefLikeType(soot.RefLikeType) PrimType(soot.PrimType) VoidType(soot.VoidType) SootResolver(soot.SootResolver) SootClass(soot.SootClass)

Aggregations

RefType (soot.RefType)14 Type (soot.Type)14 PrimType (soot.PrimType)13 VoidType (soot.VoidType)13 DoubleType (soot.DoubleType)12 FloatType (soot.FloatType)12 LongType (soot.LongType)12 SootMethod (soot.SootMethod)8 SootMethodType (org.robovm.compiler.util.generic.SootMethodType)7 BooleanType (soot.BooleanType)7 RefLikeType (soot.RefLikeType)7 ArrayList (java.util.ArrayList)6 SootMethodType (soot.SootMethodType)6 CompilerException (org.robovm.compiler.CompilerException)5 LinkedList (java.util.LinkedList)3 MethodVisitor (org.objectweb.asm.MethodVisitor)3 Body (soot.Body)3 Local (soot.Local)3 SootClass (soot.SootClass)3 SootMethodRef (soot.SootMethodRef)3