private static void EmitConversion(CodeEmitter ilgen, Type converterType, string method) { CodeEmitterLocal converter = ilgen.UnsafeAllocTempLocal(converterType); ilgen.Emit(OpCodes.Ldloca, converter); ilgen.Emit(OpCodes.Call, converterType.GetMethod(method)); }
internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) { #if !WINRT ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return(false); } LambdaMetafactory lmf = context.GetValue <LambdaMetafactory>(constantPoolIndex); if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) { #if STATIC_COMPILER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) { StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); } #endif return(false); } ilgen.Emit(OpCodes.Newobj, lmf.ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); return(true); #else throw new NotImplementedException(); #endif }
internal static bool Emit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, ClassFile classFile, int i, ClassFile.Method.Instruction[] code, InstructionFlags[] flags) { if (i >= 3 && (flags[i - 0] & InstructionFlags.BranchTarget) == 0 && (flags[i - 1] & InstructionFlags.BranchTarget) == 0 && (flags[i - 2] & InstructionFlags.BranchTarget) == 0 && (flags[i - 3] & InstructionFlags.BranchTarget) == 0 && code[i - 1].NormalizedOpCode == NormalizedByteCode.__ldc_nothrow && code[i - 2].NormalizedOpCode == NormalizedByteCode.__ldc && code[i - 3].NormalizedOpCode == NormalizedByteCode.__ldc) { // we now have a structural match, now we need to make sure that the argument values are what we expect TypeWrapper tclass = classFile.GetConstantPoolClassType(code[i - 3].Arg1); TypeWrapper vclass = classFile.GetConstantPoolClassType(code[i - 2].Arg1); string fieldName = classFile.GetConstantPoolConstantString(code[i - 1].Arg1); if (tclass == wrapper && !vclass.IsUnloadable && !vclass.IsPrimitive && !vclass.IsNonPrimitiveValueType) { FieldWrapper field = wrapper.GetFieldWrapper(fieldName, vclass.SigName); if (field != null && !field.IsStatic && field.IsVolatile && field.DeclaringType == wrapper && field.FieldTypeWrapper == vclass) { // everything matches up, now call the actual emitter ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Newobj, context.GetAtomicReferenceFieldUpdater(field)); return true; } } } return false; }
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 bool Object_getClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { // this is the null-check idiom that javac uses (both in its own source and in the code it generates) if (code[opcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__pop) { ilgen.Emit(OpCodes.Dup); ilgen.EmitNullCheck(); return(true); } // this optimizes obj1.getClass() ==/!= obj2.getClass() else if (opcodeIndex + 3 < code.Length && (flags[opcodeIndex + 1] & InstructionFlags.BranchTarget) == 0 && (flags[opcodeIndex + 2] & InstructionFlags.BranchTarget) == 0 && (flags[opcodeIndex + 3] & InstructionFlags.BranchTarget) == 0 && code[opcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__aload && code[opcodeIndex + 2].NormalizedOpCode == NormalizedByteCode.__invokevirtual && (code[opcodeIndex + 3].NormalizedOpCode == NormalizedByteCode.__if_acmpeq || code[opcodeIndex + 3].NormalizedOpCode == NormalizedByteCode.__if_acmpne) && (IsSafeForGetClassOptimization(ma.GetStackTypeWrapper(opcodeIndex, 0)) || IsSafeForGetClassOptimization(ma.GetStackTypeWrapper(opcodeIndex + 2, 0)))) { ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(code[opcodeIndex + 2].Arg1); if (cpi.Class == "java.lang.Object" && cpi.Name == "getClass" && cpi.Signature == "()Ljava.lang.Class;") { // we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); code[opcodeIndex + 2].PatchOpCode(NormalizedByteCode.__intrinsic_gettype); return(true); } } return(false); }
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 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 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(); } }
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(); }
internal override void Emit(CodeEmitter ilgen) { base.Emit(ilgen); // unbox leaves a pointer to the value of the stack (instead of the value) // so we have to copy the value into a local variable and load the address // of the local onto the stack LocalBuilder local = ilgen.DeclareLocal(Type); ilgen.Emit(OpCodes.Stloc, local); ilgen.Emit(OpCodes.Ldloca, local); }
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(); }
private static bool ThreadLocal_new(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { // it is only valid to replace a ThreadLocal instantiation by our ThreadStatic based version, if we can prove that the instantiation only happens once // (which is the case when we're in <clinit> and there aren't any branches that lead to the current position) if (caller.Name != StringConstants.CLINIT) { return(false); } #if CLASSGC if (JVM.classUnloading) { // RunAndCollect assemblies do not support ThreadStaticAttribute return(false); } #endif for (int i = 0; i <= opcodeIndex; i++) { if ((flags[i] & InstructionFlags.BranchTarget) != 0) { return(false); } } ilgen.Emit(OpCodes.Newobj, DefineThreadLocalType(context, opcodeIndex, caller)); return(true); }
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(); } } }
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 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 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 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); genericEnumEnumType = tb.CreateType(); }
private static bool Class_getPrimitiveClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { ilgen.LazyEmitPop(); ilgen.Emit(OpCodes.Ldnull); MethodWrapper mw = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("<init>", "(Lcli.System.Type;)V", false); mw.Link(); mw.EmitNewobj(ilgen); return(true); }
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 bool Util_getInstanceTypeFromClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { TypeWrapper tw = ilgen.PeekLazyClassLiteral(); if (tw != null) { ilgen.LazyEmitPop(); if (tw.IsRemapped && tw.IsFinal) { ilgen.Emit(OpCodes.Ldtoken, tw.TypeAsTBD); } else { ilgen.Emit(OpCodes.Ldtoken, tw.TypeAsBaseType); } ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); return(true); } return(false); }
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); } }
internal sealed override void Emit(CodeEmitter ilgen) { LocalBuilder value1 = ilgen.AllocTempLocal(FloatOrDouble()); LocalBuilder value2 = ilgen.AllocTempLocal(FloatOrDouble()); ilgen.Emit(OpCodes.Stloc, value2); ilgen.Emit(OpCodes.Stloc, value1); ilgen.Emit(OpCodes.Ldloc, value1); ilgen.Emit(OpCodes.Ldloc, value2); ilgen.Emit(OpCodes.Cgt_Un); ilgen.Emit(OpCodes.Ldloc, value1); ilgen.Emit(OpCodes.Ldloc, value2); ilgen.Emit(OpCodes.Clt); ilgen.Emit(OpCodes.Sub); ilgen.ReleaseTempLocal(value1); ilgen.ReleaseTempLocal(value2); }
internal sealed override void Emit(CodeEmitter ilgen) { LocalBuilder value1 = ilgen.AllocTempLocal(Types.Int64); LocalBuilder value2 = ilgen.AllocTempLocal(Types.Int64); ilgen.Emit(OpCodes.Stloc, value2); ilgen.Emit(OpCodes.Stloc, value1); ilgen.Emit(OpCodes.Ldloc, value1); ilgen.Emit(OpCodes.Ldloc, value2); ilgen.Emit(OpCodes.Cgt); ilgen.Emit(OpCodes.Ldloc, value1); ilgen.Emit(OpCodes.Ldloc, value2); ilgen.Emit(OpCodes.Clt); ilgen.Emit(OpCodes.Sub); ilgen.ReleaseTempLocal(value2); ilgen.ReleaseTempLocal(value1); }
internal sealed override void EmitBcc(CodeEmitter ilgen, Comparison comp, CodeEmitterLabel label) { switch (comp) { case Comparison.LessOrEqual: ilgen.Emit(OpCodes.Ble, label); break; case Comparison.LessThan: ilgen.Emit(OpCodes.Blt, label); break; case Comparison.GreaterOrEqual: ilgen.Emit(OpCodes.Bge_Un, label); break; case Comparison.GreaterThan: ilgen.Emit(OpCodes.Bgt_Un, label); break; } }
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(); }
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.Emit(OpCodes.Ldc_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); // MONOBUG Type.Equals(Type) is broken on Mono. We have to use the virtual method that ends up in our implementation if (!fb.FieldType.Equals((object)type)) { // this is actually relatively harmless, but I would like to know about it, so we abort and hope that users report this when they encounter it JVM.CriticalFailure("Unsupported runtime: ModuleBuilder.DefineInitializedData() field type mispredicted", null); } 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)) })); }
internal static bool Emit(DynamicTypeWrapper.FinishContext context, ClassFile classFile, int constantPoolIndex, ClassFile.ConstantPoolItemInvokeDynamic cpi, CodeEmitter ilgen) { ClassFile.BootstrapMethod bsm = classFile.GetBootstrapMethod(cpi.BootstrapMethod); if (!IsLambdaMetafactory(classFile, bsm) && !IsLambdaAltMetafactory(classFile, bsm)) { return false; } LambdaMetafactory lmf = context.GetValue<LambdaMetafactory>(constantPoolIndex); if (lmf.ctor == null && !lmf.EmitImpl(context, classFile, cpi, bsm, ilgen)) { #if STATIC_COMPILER if (context.TypeWrapper.GetClassLoader().DisableDynamicBinding) { StaticCompiler.IssueMessage(Message.UnableToCreateLambdaFactory); } #endif return false; } ilgen.Emit(OpCodes.Newobj, lmf.ctor); // the CLR verification rules about type merging mean we have to explicitly cast to the interface type here ilgen.Emit(OpCodes.Castclass, cpi.GetRetType().TypeAsBaseType); return true; }
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); }
private static bool System_arraycopy(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { // if the array arguments on the stack are of a known array type, we can redirect to an optimized version of arraycopy. // Note that we also have to handle VMSystem.arraycopy, because on GNU Classpath StringBuffer directly calls // this method to avoid prematurely initialising System. TypeWrapper dst_type = ma.GetStackTypeWrapper(opcodeIndex, 2); TypeWrapper src_type = ma.GetStackTypeWrapper(opcodeIndex, 4); if (!dst_type.IsUnloadable && dst_type.IsArray && dst_type == src_type) { switch (dst_type.Name[1]) { case 'J': case 'D': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_8); break; case 'I': case 'F': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_4); break; case 'S': case 'C': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_2); break; case 'B': case 'Z': ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_1); break; default: // TODO once the verifier tracks actual types (i.e. it knows that // a particular reference is the result of a "new" opcode) we can // use the fast version if the exact destination type is known // (in that case the "dst_type == src_type" above should // be changed to "src_type.IsAssignableTo(dst_type)". TypeWrapper elemtw = dst_type.ElementTypeWrapper; // note that IsFinal returns true for array types, so we have to be careful! if (!elemtw.IsArray && elemtw.IsFinal) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_fast); } else { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy); } break; } return(true); } else { return(false); } }
private static bool String_toCharArray(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { string str = ilgen.PopLazyLdstr(); if (str != null) { // arbitrary length for "big" strings if (str.Length > 128) { EmitLoadCharArrayLiteral(ilgen, str, caller.DeclaringType); return(true); } ilgen.Emit(OpCodes.Ldstr, str); } return(false); }
private static bool ClassLoader_getCallerClassLoader(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { if (caller.HasCallerID) { int arg = caller.GetParametersForDefineMethod().Length - 1; if (!caller.IsStatic) { arg++; } ilgen.Emit(OpCodes.Ldarg, (short)arg); MethodWrapper mw = [email protected]("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false); mw.Link(); mw.EmitCallvirt(ilgen); return(true); } return(false); }
private static bool CallerID_getCallerID(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags) { if (caller.HasCallerID) { int arg = caller.GetParametersForDefineMethod().Length - 1; if (!caller.IsStatic) { arg++; } ilgen.Emit(OpCodes.Ldarg, (short)arg); return(true); } else { JVM.CriticalFailure("CallerID.getCallerID() requires a HasCallerID annotation", null); } return(false); }
protected override void EmitGetImpl(CodeEmitter ilgen) { MethodInfo getter = property.GetGetMethod(true); if(getter == null) { DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForGetter(ilgen, this.FieldTypeWrapper, this.IsStatic); } else if(getter.IsStatic) { ilgen.Emit(OpCodes.Call, getter); } else { ilgen.Emit(OpCodes.Callvirt, getter); } }
protected override void CallvirtImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Callvirt, stubVirtual); }
protected override void NewobjImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Newobj, stub); }
protected override void EmitSetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) { CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temp); ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); ilgen.Emit(OpCodes.Ldloc, temp); } if(IsVolatile) { ilgen.Emit(OpCodes.Volatile); } ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi); if(IsVolatile) { ilgen.EmitMemoryBarrier(); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); CodeEmitterLocal temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temp); if(fi.IsStatic) { ilgen.Emit(OpCodes.Ldsflda, fi); } else { if(DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } ilgen.Emit(OpCodes.Ldflda, fi); } ilgen.Emit(OpCodes.Ldloc, temp); if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteDouble); } else { Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileWriteLong); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { if(setter == null) { if(this.IsFinal) { ilgen.Emit(OpCodes.Pop); if(!this.IsStatic) { ilgen.Emit(OpCodes.Pop); } } else { EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic); } } else if(setter.IsStatic) { setter.EmitCall(ilgen); } else { setter.EmitCallvirt(ilgen); } }
internal override void EmitCallvirt(CodeEmitter ilgen) { ilgen.Emit(SimpleOpCodeToOpCode(callvirt), (MethodInfo)GetMethod()); }
protected override void CallImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, (ConstructorInfo)GetMethod()); }
protected override void CallvirtImpl(CodeEmitter ilgen) { ilgen.Emit(SimpleOpCodeToOpCode(callvirt), (MethodInfo)GetMethod()); }
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.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null)); } else if(constant is string) { ilgen.Emit(OpCodes.Ldstr, (string)constant); } else if(constant is float) { ilgen.Emit(OpCodes.Ldc_R4, (float)constant); } else if(constant is double) { ilgen.Emit(OpCodes.Ldc_R8, (double)constant); } else if(constant is long) { ilgen.Emit(OpCodes.Ldc_I8, (long)constant); } else if(constant is uint) { ilgen.Emit(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null))); } else if(constant is ulong) { ilgen.Emit(OpCodes.Ldc_I8, unchecked((long)(ulong)constant)); } else { throw new InvalidOperationException(constant.GetType().FullName); } }
protected override void NewobjImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Newobj, (ConstructorInfo)GetMethod()); }
protected override void EmitSetImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, setter); }
protected override void CallImpl(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, stub); }
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) { if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } if(IsVolatile) { ilgen.Emit(OpCodes.Volatile); } ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField()); }
internal override void EmitInstanceOf(CodeEmitter ilgen) { if(IsGhost) { ilgen.Emit(OpCodes.Call, ghostIsInstanceMethod); } else if(IsGhostArray) { ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod); } else { base.EmitInstanceOf(ilgen); } }
protected override void EmitGetImpl(CodeEmitter ilgen) { FieldInfo fi = GetField(); if(fi.IsStatic) { ilgen.Emit(OpCodes.Ldsflda, fi); } else { if(DeclaringType.IsNonPrimitiveValueType) { ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); } ilgen.Emit(OpCodes.Ldflda, fi); } if(FieldTypeWrapper == PrimitiveTypeWrapper.DOUBLE) { ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadDouble); } else { Debug.Assert(FieldTypeWrapper == PrimitiveTypeWrapper.LONG); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.volatileReadLong); } }
internal override void EmitCall(CodeEmitter ilgen) { ilgen.Emit(OpCodes.Call, (ConstructorInfo)GetMethod()); }
internal static void EmitThrowNoSuchMethodErrorForGetter(CodeEmitter ilgen, TypeWrapper type, bool isStatic) { // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Brtrue_S, label); ilgen.EmitThrow("java.lang.NoSuchMethodError"); ilgen.MarkLabel(label); if (!isStatic) { ilgen.Emit(OpCodes.Pop); } ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(type.TypeAsLocalOrStackType)); }
internal override void EmitNewobj(CodeEmitter ilgen) { if(mbHelper != null) { ilgen.Emit(OpCodes.Call, mbHelper); } else { ilgen.Emit(OpCodes.Newobj, (ConstructorInfo)GetMethod()); } }
internal static void EmitThrowNoSuchMethodErrorForSetter(CodeEmitter ilgen, bool isStatic) { // HACK the branch around the throw is to keep the verifier happy CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Brtrue_S, label); ilgen.EmitThrow("java.lang.NoSuchMethodError"); ilgen.MarkLabel(label); ilgen.Emit(OpCodes.Pop); if (!isStatic) { ilgen.Emit(OpCodes.Pop); } }
internal override void EmitCall(CodeEmitter ilgen) { if(!IsStatic && IsFinal) { // When calling a final instance method on a remapped type from a class derived from a .NET class (i.e. a cli.System.Object or cli.System.Exception derived base class) // then we can't call the java.lang.Object or java.lang.Throwable methods and we have to go through the instancehelper_ method. Note that since the method // is final, this won't affect the semantics. EmitCallvirt(ilgen); } else { ilgen.Emit(OpCodes.Call, (MethodInfo)GetMethod()); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { MethodInfo setter = property.GetSetMethod(true); if (setter == null) { if(this.IsFinal) { ilgen.Emit(OpCodes.Pop); if(!this.IsStatic) { ilgen.Emit(OpCodes.Pop); } } else { DynamicPropertyFieldWrapper.EmitThrowNoSuchMethodErrorForSetter(ilgen, this.IsStatic); } } else if(setter.IsStatic) { ilgen.Emit(OpCodes.Call, setter); } else { ilgen.Emit(OpCodes.Callvirt, setter); } }
private void EmitCallvirtImpl(CodeEmitter ilgen, bool cloneOrFinalizeHack) { if(mbHelper != null && !cloneOrFinalizeHack) { ilgen.Emit(OpCodes.Call, mbHelper); } else { ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod()); } }
protected override void EmitSetImpl(CodeEmitter ilgen) { // when constant static final fields are updated, the JIT normally doesn't see that (because the // constant value is inlined), so we emulate that behavior by emitting a Pop ilgen.Emit(OpCodes.Pop); }
private void EmitRedirect(Type baseType, CodeEmitter ilgen) { string redirName = m.redirect.Name; string redirSig = m.redirect.Sig; if(redirName == null) { redirName = m.Name; } if(redirSig == null) { redirSig = m.Sig; } ClassLoaderWrapper classLoader = DeclaringType.GetClassLoader(); // HACK if the class name contains a comma, we assume it is a .NET type if(m.redirect.Class == null || m.redirect.Class.IndexOf(',') >= 0) { // TODO better error handling Type type = m.redirect.Class == null ? baseType : StaticCompiler.Universe.GetType(m.redirect.Class, true); Type[] redirParamTypes = classLoader.ArgTypeListFromSig(redirSig); MethodInfo mi = type.GetMethod(m.redirect.Name, redirParamTypes); if(mi == null) { throw new InvalidOperationException(); } ilgen.Emit(OpCodes.Call, mi); } else { TypeWrapper tw = classLoader.LoadClassByDottedName(m.redirect.Class); MethodWrapper mw = tw.GetMethodWrapper(redirName, redirSig, false); if(mw == null) { throw new InvalidOperationException("Missing redirect method: " + tw.Name + "." + redirName + redirSig); } mw.Link(); mw.EmitCall(ilgen); } }
protected override void CallvirtImpl(CodeEmitter ilgen) { ResolveGhostMethod(); ilgen.Emit(OpCodes.Call, ghostMethod); }
internal void Emit(IKVM.Internal.MapXml.CodeGenContext context, CodeEmitter ilgen) { MethodWrapper mwSuppressFillInStackTrace = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper("__<suppressFillInStackTrace>", "()V", false); mwSuppressFillInStackTrace.Link(); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod); for(int i = 0; i < map.Length; i++) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Ldtoken, StaticCompiler.Universe.GetType(map[i].src, true)); ilgen.Emit(OpCodes.Call, Compiler.getTypeFromHandleMethod); ilgen.Emit(OpCodes.Ceq); CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Brfalse_S, label); ilgen.Emit(OpCodes.Pop); if(map[i].code != null) { ilgen.Emit(OpCodes.Ldarg_0); if(map[i].code.invoke != null) { foreach(MapXml.Instruction instr in map[i].code.invoke) { MapXml.NewObj newobj = instr as MapXml.NewObj; if(newobj != null && newobj.Class != null && context.ClassLoader.LoadClassByDottedName(newobj.Class).IsSubTypeOf(CoreClasses.java.lang.Throwable.Wrapper)) { mwSuppressFillInStackTrace.EmitCall(ilgen); } instr.Generate(context, ilgen); } } ilgen.Emit(OpCodes.Ret); } else { TypeWrapper tw = context.ClassLoader.LoadClassByDottedName(map[i].dst); MethodWrapper mw = tw.GetMethodWrapper("<init>", "()V", false); mw.Link(); mwSuppressFillInStackTrace.EmitCall(ilgen); mw.EmitNewobj(ilgen); ilgen.Emit(OpCodes.Ret); } ilgen.MarkLabel(label); } ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ret); }