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();
}
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";
}
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());
}
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;
}
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;
}
Aggregations