private static ConstructorInfo AddConstructor(TypeBuilder tb, MethodWrapper defaultConstructor, ConstructorInfo serializationConstructor, bool callReadObject) { ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Family, CallingConventions.Standard, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); AttributeHelper.HideFromJava(ctor); ctor.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); CodeEmitter ilgen = CodeEmitter.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); if (defaultConstructor != null) { defaultConstructor.EmitCall(ilgen); } else { ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); ilgen.Emit(OpCodes.Call, serializationConstructor); } if (callReadObject) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); MethodWrapper mw = serializationHelper.GetMethodWrapper("readObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); mw.Link(); mw.EmitCall(ilgen); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); return(ctor); }
private static void AddDefaultInterfaceMethods(DynamicTypeWrapper.FinishContext context, MethodWrapper[] methodList, TypeBuilder tb) { // we use special name to hide these from Java reflection const MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName; TypeWrapperFactory factory = context.TypeWrapper.GetClassLoader().GetTypeWrapperFactory(); foreach (MethodWrapper mw in methodList) { if (!mw.IsAbstract) { MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); if (mw.Name != mw.RealName) { tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); } DynamicTypeWrapper.FinishContext.EmitCallDefaultInterfaceMethod(mb, mw); } else if (IsObjectMethod(mw)) { MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); if (mw.Name != mw.RealName) { tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); } CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0, count = mw.GetParameters().Length; i <= count; i++) { ilgen.EmitLdarg(i); } CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, false).EmitCallvirt(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } } }
private static void AddReadResolve(DynamicTypeWrapper wrapper, TypeBuilder tb) { MethodWrapper mw = wrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", false); if (mw != null && !wrapper.IsSubTypeOf(iobjectreference)) { tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference))); MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) }); getRealObject.SetCustomAttribute(securityCriticalAttribute); AttributeHelper.HideFromJava(getRealObject); tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject")); CodeEmitter ilgen = CodeEmitter.Create(getRealObject); mw.Link(); if (!wrapper.IsFinal) { // readResolve is only applicable if it exists on the actual type of the object, so if we're a subclass don't call it ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); ilgen.Emit(OpCodes.Ldtoken, wrapper.TypeAsBaseType); ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Beq_S, label); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(label); } ilgen.Emit(OpCodes.Ldarg_0); mw.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } }
internal static void AddGetObjectData(TypeBuilder tb) { string name = tb.IsSealed ? "System.Runtime.Serialization.ISerializable.GetObjectData" : "GetObjectData"; MethodAttributes attr = tb.IsSealed ? MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final : MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; tb.AddInterfaceImplementation(JVM.Import(typeof(ISerializable))); MethodBuilder getObjectData = tb.DefineMethod(name, attr, null, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); getObjectData.SetCustomAttribute(securityCriticalAttribute); AttributeHelper.HideFromJava(getObjectData); //TODO: We need to review this for .NET Core //getObjectData.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); tb.DefineMethodOverride(getObjectData, JVM.Import(typeof(ISerializable)).GetMethod("GetObjectData")); CodeEmitter ilgen = CodeEmitter.Create(getObjectData); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); MethodWrapper mw = serializationHelper.GetMethodWrapper("writeObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); mw.Link(); mw.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static ConstructorBuilder DefineThreadLocalType(DynamicTypeWrapper.FinishContext context, int opcodeIndex, MethodWrapper caller) { TypeWrapper threadLocal = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicThreadLocal"); TypeBuilder tb = caller.DeclaringType.TypeAsBuilder.DefineNestedType("__<tls>_" + opcodeIndex, TypeAttributes.NestedPrivate | TypeAttributes.Sealed, threadLocal.TypeAsBaseType); FieldBuilder fb = tb.DefineField("field", Types.Object, FieldAttributes.Private | FieldAttributes.Static); fb.SetCustomAttribute(new CustomAttributeBuilder(JVM.Import(typeof(ThreadStaticAttribute)).GetConstructor(Type.EmptyTypes), new object[0])); MethodBuilder mbGet = tb.DefineMethod("get", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, Types.Object, Type.EmptyTypes); ILGenerator ilgen = mbGet.GetILGenerator(); ilgen.Emit(OpCodes.Ldsfld, fb); ilgen.Emit(OpCodes.Ret); MethodBuilder mbSet = tb.DefineMethod("set", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final, null, new Type[] { Types.Object }); ilgen = mbSet.GetILGenerator(); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Stsfld, fb); ilgen.Emit(OpCodes.Ret); ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes); CodeEmitter ctorilgen = CodeEmitter.Create(cb); ctorilgen.Emit(OpCodes.Ldarg_0); MethodWrapper basector = threadLocal.GetMethodWrapper("<init>", "()V", false); basector.Link(); basector.EmitCall(ctorilgen); ctorilgen.Emit(OpCodes.Ret); ctorilgen.DoEmit(); context.RegisterPostFinishProc(delegate { threadLocal.Finish(); tb.CreateType(); }); return(cb); }
private static MethodBuilder AddConstructor(TypeBuilder tb, MethodWrapper defaultConstructor, MethodBase serializationConstructor, bool callReadObject) { MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Family, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); AttributeHelper.HideFromJava(ctor); CodeEmitter ilgen = CodeEmitter.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); if (defaultConstructor != null) { defaultConstructor.EmitCall(ilgen); } else { ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); ilgen.Emit(OpCodes.Call, serializationConstructor); } if (callReadObject) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); MethodWrapper mw = serializationHelper.GetMethodWrapper("readObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); mw.Link(); mw.EmitCall(ilgen); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); return(ctor); }
private static void CreateConstructor(TypeBuilder tb) { CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(tb, MethodAttributes.Public, new Type[] { invocationHandlerClass.TypeAsSignatureType })); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); proxyConstructor.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static void CreateConstructor(TypeBuilder tb) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { invocationHandlerClass.TypeAsSignatureType }); CodeEmitter ilgen = CodeEmitter.Create(cb); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); proxyConstructor.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static void RemoveReadResolve(TypeBuilder tb) { tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference))); MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) }); getRealObject.SetCustomAttribute(securityCriticalAttribute); AttributeHelper.HideFromJava(getRealObject); tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject")); CodeEmitter ilgen = CodeEmitter.Create(getRealObject); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
internal static void Finish(ClassLoaderWrapper loader) { TypeBuilder tb = (TypeBuilder)genericEnumEnumType; TypeWrapper enumTypeWrapper = loader.LoadClassByDottedName("java.lang.Enum"); enumTypeWrapper.Finish(); tb.SetParent(enumTypeWrapper.TypeAsBaseType); CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineConstructor(tb, MethodAttributes.Private, new Type[] { Types.String, Types.Int32 })); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); enumTypeWrapper.GetMethodWrapper("<init>", "(Ljava.lang.String;I)V", false).EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); genericEnumEnumType = tb.CreateType(); }
private static void CreateStaticInitializer(TypeBuilder tb, List <ProxyMethod> methods) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); CodeEmitter ilgen = CodeEmitter.Create(cb); CodeEmitterLocal callerID = ilgen.DeclareLocal([email protected]); TypeBuilder tbCallerID = DynamicTypeWrapper.FinishContext.EmitCreateCallerID(tb, ilgen); ilgen.Emit(OpCodes.Stloc, callerID); // HACK we shouldn't create the nested type here (the outer type must be created first) tbCallerID.CreateType(); ilgen.BeginExceptionBlock(); foreach (ProxyMethod method in methods) { method.mw.DeclaringType.EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Ldstr, method.mw.Name); TypeWrapper[] parameters = method.mw.GetParameters(); ilgen.Emit(OpCodes.Ldc_I4, parameters.Length); ilgen.Emit(OpCodes.Newarr, CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType); for (int i = 0; i < parameters.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Ldc_I4, i); parameters[i].EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Stelem_Ref); } if (javaLangClass_getMethod.HasCallerID) { ilgen.Emit(OpCodes.Ldloc, callerID); } javaLangClass_getMethod.EmitCallvirt(ilgen); ilgen.Emit(OpCodes.Stsfld, method.fb); } CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Leave_S, label); ilgen.BeginCatchBlock(javaLangNoSuchMethodException.TypeAsExceptionType); javaLangThrowable_getMessage.EmitCallvirt(ilgen); javaLangNoClassDefFoundErrorConstructor.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Throw); ilgen.EndExceptionBlock(); ilgen.MarkLabel(label); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static void CreateEnumEnum(ModuleBuilder modb, ClassLoaderWrapper loader) { TypeWrapper enumTypeWrapper = loader.LoadClassByDottedName("java.lang.Enum"); enumTypeWrapper.Finish(); TypeBuilder tb = modb.DefineType(DotNetTypeWrapper.GenericEnumEnumTypeName, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public, enumTypeWrapper.TypeAsBaseType); GenericTypeParameterBuilder gtpb = tb.DefineGenericParameters("T")[0]; gtpb.SetBaseTypeConstraint(Types.Enum); CodeEmitter ilgen = CodeEmitter.Create(tb.DefineConstructor(MethodAttributes.Private, CallingConventions.Standard, new Type[] { Types.String, Types.Int32 })); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); enumTypeWrapper.GetMethodWrapper("<init>", "(Ljava.lang.String;I)V", false).EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); genericEnumEnumType = tb.CreateType(); }
private static void EmitClassLiteral(CompilerClassLoader ccl) { TypeBuilder tb = ccl.GetTypeWrapperFactory().ModuleBuilder.DefineType("ikvm.internal.ClassLiteral`1", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.Class | TypeAttributes.BeforeFieldInit); GenericTypeParameterBuilder typeParam = tb.DefineGenericParameters("T")[0]; Type classType = CoreClasses.java.lang.Class.Wrapper.TypeAsSignatureType; classLiteralField = tb.DefineField("Value", classType, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly); CodeEmitter ilgen = CodeEmitter.Create(ReflectUtil.DefineTypeInitializer(tb)); ilgen.Emit(OpCodes.Ldtoken, typeParam); ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle", new Type[] { Types.RuntimeTypeHandle })); MethodWrapper mw = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("<init>", "(Lcli.System.Type;)V", false); mw.Link(); mw.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Stsfld, classLiteralField); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); classLiteralType = tb.CreateType(); }
private static void AddReadResolve(TypeWrapper wrapper) { MethodWrapper mw = wrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", false); if (mw != null && !wrapper.IsSubTypeOf(iobjectreference)) { TypeBuilder tb = wrapper.TypeAsBuilder; tb.AddInterfaceImplementation(JVM.Import(typeof(IObjectReference))); MethodBuilder getRealObject = tb.DefineMethod("IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, Types.Object, new Type[] { JVM.Import(typeof(StreamingContext)) }); getRealObject.SetCustomAttribute(securityCriticalAttribute); AttributeHelper.HideFromJava(getRealObject); tb.DefineMethodOverride(getRealObject, JVM.Import(typeof(IObjectReference)).GetMethod("GetRealObject")); CodeEmitter ilgen = CodeEmitter.Create(getRealObject); mw.Link(); ilgen.Emit(OpCodes.Ldarg_0); mw.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } }
private static void AddGetObjectData(TypeWrapper wrapper) { TypeBuilder tb = wrapper.TypeAsBuilder; tb.AddInterfaceImplementation(JVM.Import(typeof(ISerializable))); MethodBuilder getObjectData = tb.DefineMethod("GetObjectData", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.NewSlot, null, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); getObjectData.SetCustomAttribute(securityCriticalAttribute); AttributeHelper.HideFromJava(getObjectData); getObjectData.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); tb.DefineMethodOverride(getObjectData, JVM.Import(typeof(ISerializable)).GetMethod("GetObjectData")); CodeEmitter ilgen = CodeEmitter.Create(getObjectData); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); MethodWrapper mw = serializationHelper.GetMethodWrapper("writeObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); mw.Link(); mw.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static void CreateMethod(CompilerClassLoader loader, TypeBuilder tb, ProxyMethod pm) { MethodBuilder mb = pm.mw.GetDefineMethodHelper().DefineMethod(loader.GetTypeWrapperFactory(), tb, pm.mw.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final); List <string> exceptions = new List <string>(); foreach (TypeWrapper tw in pm.exceptions) { exceptions.Add(tw.Name); } AttributeHelper.SetThrowsAttribute(mb, exceptions.ToArray()); CodeEmitter ilgen = CodeEmitter.Create(mb); ilgen.BeginExceptionBlock(); ilgen.Emit(OpCodes.Ldarg_0); invocationHandlerField.EmitGet(ilgen); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldsfld, pm.fb); TypeWrapper[] parameters = pm.mw.GetParameters(); if (parameters.Length == 0) { ilgen.Emit(OpCodes.Ldnull); } else { ilgen.EmitLdc_I4(parameters.Length); ilgen.Emit(OpCodes.Newarr, Types.Object); for (int i = 0; i < parameters.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.EmitLdc_I4(i); ilgen.EmitLdarg(i); if (parameters[i].IsNonPrimitiveValueType) { parameters[i].EmitBox(ilgen); } else if (parameters[i].IsPrimitive) { Boxer.EmitBox(ilgen, parameters[i]); } ilgen.Emit(OpCodes.Stelem_Ref); } } invokeMethod.EmitCallvirt(ilgen); TypeWrapper returnType = pm.mw.ReturnType; CodeEmitterLocal returnValue = null; if (returnType != PrimitiveTypeWrapper.VOID) { returnValue = ilgen.DeclareLocal(returnType.TypeAsSignatureType); if (returnType.IsNonPrimitiveValueType) { returnType.EmitUnbox(ilgen); } else if (returnType.IsPrimitive) { Boxer.EmitUnbox(ilgen, returnType); } else if (returnType != CoreClasses.java.lang.Object.Wrapper) { ilgen.EmitCastclass(returnType.TypeAsSignatureType); } ilgen.Emit(OpCodes.Stloc, returnValue); } CodeEmitterLabel returnLabel = ilgen.DefineLabel(); ilgen.EmitLeave(returnLabel); // TODO consider using a filter here (but we would need to add filter support to CodeEmitter) ilgen.BeginCatchBlock(Types.Exception); ilgen.EmitLdc_I4(0); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception)); CodeEmitterLocal exception = ilgen.DeclareLocal(Types.Exception); ilgen.Emit(OpCodes.Stloc, exception); CodeEmitterLabel rethrow = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldloc, exception); errorClass.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); ilgen.Emit(OpCodes.Ldloc, exception); runtimeExceptionClass.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); foreach (TypeWrapper tw in pm.exceptions) { ilgen.Emit(OpCodes.Ldloc, exception); tw.EmitInstanceOf(ilgen); ilgen.EmitBrtrue(rethrow); } ilgen.Emit(OpCodes.Ldloc, exception); undeclaredThrowableExceptionConstructor.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Throw); ilgen.MarkLabel(rethrow); ilgen.Emit(OpCodes.Rethrow); ilgen.EndExceptionBlock(); ilgen.MarkLabel(returnLabel); if (returnValue != null) { ilgen.Emit(OpCodes.Ldloc, returnValue); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields) { MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); if (interfaceMethod.Name != interfaceMethod.RealName) { tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod()); } CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0; i < capturedFields.Length; i++) { ilgen.EmitLdarg(0); OpCode opc = OpCodes.Ldfld; if (i == 0 && args[0].IsGhost) { switch (implMethod.Kind) { case ClassFile.RefKind.invokeInterface: case ClassFile.RefKind.invokeVirtual: case ClassFile.RefKind.invokeSpecial: opc = OpCodes.Ldflda; break; } } ilgen.Emit(opc, capturedFields[i]); } for (int i = 0, count = interfaceMethod.GetParameters().Length, k = capturedFields.Length; i < count; i++) { ilgen.EmitLdarg(i + 1); TypeWrapper Ui = interfaceMethod.GetParameters()[i]; TypeWrapper Ti = instantiatedMethodType.GetArgTypes()[i]; TypeWrapper Aj = implParameters[i + k]; if (Ui == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } if (Ti != Ui) { if (Ti.IsGhost) { Ti.EmitConvStackTypeToSignatureType(ilgen, Ui); } else if (Ui.IsGhost) { Ui.EmitConvSignatureTypeToStackType(ilgen); } else { Ti.EmitCheckcast(ilgen); } } if (Ti != Aj) { if (Ti.IsPrimitive && !Aj.IsPrimitive) { Boxer.EmitBox(ilgen, Ti); } else if (!Ti.IsPrimitive && Aj.IsPrimitive) { TypeWrapper primitive = GetPrimitiveFromWrapper(Ti); Boxer.EmitUnbox(ilgen, primitive, false); if (primitive == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } } else if (Aj == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Conv_I8); } else if (Aj == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Conv_R4); } else if (Aj == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Conv_R8); } } } switch (implMethod.Kind) { case ClassFile.RefKind.invokeVirtual: case ClassFile.RefKind.invokeInterface: ((MethodWrapper)implMethod.Member).EmitCallvirt(ilgen); break; case ClassFile.RefKind.newInvokeSpecial: ((MethodWrapper)implMethod.Member).EmitNewobj(ilgen); break; case ClassFile.RefKind.invokeStatic: case ClassFile.RefKind.invokeSpecial: ((MethodWrapper)implMethod.Member).EmitCall(ilgen); break; default: throw new InvalidOperationException(); } TypeWrapper Ru = interfaceMethod.ReturnType; TypeWrapper Ra = GetImplReturnType(implMethod); TypeWrapper Rt = instantiatedMethodType.GetRetType(); if (Ra == PrimitiveTypeWrapper.BYTE) { ilgen.Emit(OpCodes.Conv_I1); } if (Ra != Ru) { if (Ru == PrimitiveTypeWrapper.VOID) { ilgen.Emit(OpCodes.Pop); } else if (Ra.IsGhost) { Ra.EmitConvSignatureTypeToStackType(ilgen); } else if (Ru.IsGhost) { Ru.EmitConvStackTypeToSignatureType(ilgen, Ra); } } if (Ra != Rt) { if (Rt.IsPrimitive) { if (Rt == PrimitiveTypeWrapper.VOID) { // already popped } else if (!Ra.IsPrimitive) { TypeWrapper primitive = GetPrimitiveFromWrapper(Ra); if (primitive != null) { Boxer.EmitUnbox(ilgen, primitive, false); } else { // If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types EmitConvertingUnbox(ilgen, Rt); } } else if (Rt == PrimitiveTypeWrapper.LONG) { ilgen.Emit(OpCodes.Conv_I8); } else if (Rt == PrimitiveTypeWrapper.FLOAT) { ilgen.Emit(OpCodes.Conv_R4); } else if (Rt == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Conv_R8); } } else if (Ra.IsPrimitive) { Boxer.EmitBox(ilgen, GetPrimitiveFromWrapper(Rt)); } else { Rt.EmitCheckcast(ilgen); } } ilgen.EmitTailCallPrevention(); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); }
private static MethodBuilder CreateConstructorAndDispatch(DynamicTypeWrapper.FinishContext context, ClassFile.ConstantPoolItemInvokeDynamic cpi, TypeBuilder tb, List <MethodWrapper> methods, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodType samMethodType, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, bool serializable) { TypeWrapper[] args = cpi.GetArgTypes(); // captured values Type[] capturedTypes = new Type[args.Length]; FieldBuilder[] capturedFields = new FieldBuilder[capturedTypes.Length]; for (int i = 0; i < capturedTypes.Length; i++) { capturedTypes[i] = args[i].TypeAsSignatureType; FieldAttributes attr = FieldAttributes.Private; if (i > 0 || !args[0].IsGhost) { attr |= FieldAttributes.InitOnly; } capturedFields[i] = tb.DefineField("arg$" + (i + 1), capturedTypes[i], attr); } // constructor MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Assembly, capturedTypes); CodeEmitter ilgen = CodeEmitter.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Call, Types.Object.GetConstructor(Type.EmptyTypes)); for (int i = 0; i < capturedTypes.Length; i++) { ilgen.EmitLdarg(0); ilgen.EmitLdarg(i + 1); ilgen.Emit(OpCodes.Stfld, capturedFields[i]); } ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // dispatch methods foreach (MethodWrapper mw in methods) { EmitDispatch(context, args, tb, mw, implParameters, implMethod, instantiatedMethodType, capturedFields); } // writeReplace method if (serializable) { MethodBuilder writeReplace = tb.DefineMethod("writeReplace", MethodAttributes.Private, Types.Object, Type.EmptyTypes); ilgen = CodeEmitter.Create(writeReplace); context.TypeWrapper.EmitClassLiteral(ilgen); ilgen.Emit(OpCodes.Ldstr, cpi.GetRetType().Name.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, cpi.Name); ilgen.Emit(OpCodes.Ldstr, samMethodType.Signature.Replace('.', '/')); ilgen.EmitLdc_I4((int)implMethod.Kind); ilgen.Emit(OpCodes.Ldstr, implMethod.Class.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, implMethod.Name); ilgen.Emit(OpCodes.Ldstr, implMethod.Signature.Replace('.', '/')); ilgen.Emit(OpCodes.Ldstr, instantiatedMethodType.Signature.Replace('.', '/')); ilgen.EmitLdc_I4(capturedFields.Length); ilgen.Emit(OpCodes.Newarr, Types.Object); for (int i = 0; i < capturedFields.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.EmitLdc_I4(i); ilgen.EmitLdarg(0); ilgen.Emit(OpCodes.Ldfld, capturedFields[i]); if (args[i].IsPrimitive) { Boxer.EmitBox(ilgen, args[i]); } else if (args[i].IsGhost) { args[i].EmitConvSignatureTypeToStackType(ilgen); } ilgen.Emit(OpCodes.Stelem, Types.Object); } MethodWrapper ctorSerializedLambda = ClassLoaderWrapper.LoadClassCritical("java.lang.invoke.SerializedLambda").GetMethodWrapper(StringConstants.INIT, "(Ljava.lang.Class;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;ILjava.lang.String;Ljava.lang.String;Ljava.lang.String;Ljava.lang.String;[Ljava.lang.Object;)V", false); ctorSerializedLambda.Link(); ctorSerializedLambda.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); if (!context.TypeWrapper.GetClassLoader().NoAutomagicSerialization) { // add .NET serialization interop support Serialization.MarkSerializable(tb); Serialization.AddGetObjectData(tb); } } return(ctor); }