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 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);
        }
示例#4
0
        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();
        }
示例#5
0
 internal void Emit(ClassLoaderWrapper loader, CodeEmitter ilgen)
 {
     if(Type != "static" || Class == null || Name == null || Sig == null)
     {
         throw new NotImplementedException();
     }
     Type[] redirParamTypes = loader.ArgTypeListFromSig(Sig);
     for(int i = 0; i < redirParamTypes.Length; i++)
     {
         ilgen.EmitLdarg(i);
     }
     // HACK if the class name contains a comma, we assume it is a .NET type
     if(Class.IndexOf(',') >= 0)
     {
         Type type = StaticCompiler.Universe.GetType(Class, true);
         MethodInfo mi = type.GetMethod(Name, redirParamTypes);
         if(mi == null)
         {
             throw new InvalidOperationException();
         }
         ilgen.Emit(OpCodes.Call, mi);
     }
     else
     {
         TypeWrapper tw = loader.LoadClassByDottedName(Class);
         MethodWrapper mw = tw.GetMethodWrapper(Name, Sig, false);
         if(mw == null)
         {
             throw new InvalidOperationException();
         }
         mw.Link();
         mw.EmitCall(ilgen);
     }
     // TODO we may need a cast here (or a stack to return type conversion)
     ilgen.Emit(OpCodes.Ret);
 }
示例#6
0
 internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
 {
     ilgen.EmitLdarg(ArgNum);
 }