Esempio n. 1
0
        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.EmitLdc_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.EmitLdc_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.EmitLeave(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();
        }
Esempio n. 2
0
        private static void EmitLoadCharArrayLiteral(CodeEmitter ilgen, string str, TypeWrapper tw)
        {
            ModuleBuilder mod = tw.GetClassLoader().GetTypeWrapperFactory().ModuleBuilder;
            // FXBUG on .NET 1.1 & 2.0 the value type that Ref.Emit automatically generates is public,
            // so we pre-create a non-public type with the right name here and it will "magically" use
            // that instead.
            // If we're running on Mono this isn't necessary, but for simplicitly we'll simply create
            // the type as well (it is useless, but all it does is waste a little space).
            int    length   = str.Length * 2;
            string typename = "$ArrayType$" + length;
            Type   type     = mod.GetType(typename, false, false);

            if (type == null)
            {
                if (tw.GetClassLoader().GetTypeWrapperFactory().ReserveName(typename))
                {
                    TypeBuilder tb = mod.DefineType(typename, TypeAttributes.Sealed | TypeAttributes.Class | TypeAttributes.ExplicitLayout | TypeAttributes.NotPublic, Types.ValueType, PackingSize.Size1, length);
                    AttributeHelper.HideFromJava(tb);
                    type = tb.CreateType();
                }
            }
            if (type == null ||
                !type.IsValueType ||
                type.StructLayoutAttribute.Pack != 1 || type.StructLayoutAttribute.Size != length)
            {
                // the type that we found doesn't match (must mean we've compiled a Java type with that name),
                // so we fall back to the string approach
                ilgen.Emit(OpCodes.Ldstr, str);
                ilgen.Emit(OpCodes.Call, Types.String.GetMethod("ToCharArray", Type.EmptyTypes));
                return;
            }
            ilgen.EmitLdc_I4(str.Length);
            ilgen.Emit(OpCodes.Newarr, Types.Char);
            ilgen.Emit(OpCodes.Dup);
            byte[] data = new byte[length];
            for (int j = 0; j < str.Length; j++)
            {
                data[j * 2 + 0] = (byte)(str[j] >> 0);
                data[j * 2 + 1] = (byte)(str[j] >> 8);
            }
            // NOTE we define a module field, because type fields on Mono don't use the global $ArrayType$<n> type.
            // NOTE this also means that this will only work during static compilation, because ModuleBuilder.CreateGlobalFunctions() must
            // be called before the field can be used.
            FieldBuilder fb = mod.DefineInitializedData("__<str>", data, FieldAttributes.Static | FieldAttributes.PrivateScope);

            ilgen.Emit(OpCodes.Ldtoken, fb);
            ilgen.Emit(OpCodes.Call, JVM.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers)).GetMethod("InitializeArray", new Type[] { Types.Array, JVM.Import(typeof(RuntimeFieldHandle)) }));
        }
        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);
        }
Esempio n. 4
0
 internal override void EmitCheckcast(CodeEmitter ilgen)
 {
     if(IsGhost)
     {
         ilgen.Emit(OpCodes.Dup);
         ilgen.Emit(OpCodes.Call, ghostCastMethod);
         ilgen.Emit(OpCodes.Pop);
     }
     else if(IsGhostArray)
     {
         ilgen.Emit(OpCodes.Dup);
         TypeWrapper tw = this;
         int rank = 0;
         while(tw.IsArray)
         {
             rank++;
             tw = tw.ElementTypeWrapper;
         }
         ilgen.EmitLdc_I4(rank);
         ilgen.Emit(OpCodes.Call, ghostCastArrayMethod);
         ilgen.Emit(OpCodes.Castclass, ArrayTypeWrapper.MakeArrayType(Types.Object, rank));
     }
     else
     {
         base.EmitCheckcast(ilgen);
     }
 }
		protected override void EmitGetImpl(CodeEmitter ilgen)
		{
			// Reading a field should trigger the cctor, but since we're inlining the value
			// we have to trigger it explicitly
			DeclaringType.EmitRunClassConstructor(ilgen);

			// NOTE even though you're not supposed to access a constant static final (the compiler is supposed
			// to inline them), we have to support it (because it does happen, e.g. if the field becomes final
			// after the referencing class was compiled, or when we're accessing an unsigned primitive .NET field)
			object v = GetConstantValue();
			if(v == null)
			{
				ilgen.Emit(OpCodes.Ldnull);
			}
			else if(constant is int || 
				constant is short ||
				constant is ushort ||
				constant is byte ||
				constant is sbyte ||
				constant is char ||
				constant is bool)
			{
				ilgen.EmitLdc_I4(((IConvertible)constant).ToInt32(null));
			}
			else if(constant is string)
			{
				ilgen.Emit(OpCodes.Ldstr, (string)constant);
			}
			else if(constant is float)
			{
				ilgen.EmitLdc_R4((float)constant);
			}
			else if(constant is double)
			{
				ilgen.EmitLdc_R8((double)constant);
			}
			else if(constant is long)
			{
				ilgen.EmitLdc_I8((long)constant);
			}
			else if(constant is uint)
			{
				ilgen.EmitLdc_I4(unchecked((int)((IConvertible)constant).ToUInt32(null)));
			}
			else if(constant is ulong)
			{
				ilgen.EmitLdc_I8(unchecked((long)(ulong)constant));
			}
			else
			{
				throw new InvalidOperationException(constant.GetType().FullName);
			}
		}
Esempio n. 6
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();
        }
Esempio n. 7
0
 internal override void Generate(CodeGenContext context, CodeEmitter ilgen)
 {
     ilgen.EmitLdc_I4(val);
 }