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 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 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 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); }
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(); }
internal static void EmitUnbox(CodeEmitter ilgen, TypeWrapper tw) { if (tw == PrimitiveTypeWrapper.BYTE) { javaLangByte.EmitCheckcast(ilgen); byteValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.BOOLEAN) { javaLangBoolean.EmitCheckcast(ilgen); booleanValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.SHORT) { javaLangShort.EmitCheckcast(ilgen); shortValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.CHAR) { javaLangCharacter.EmitCheckcast(ilgen); charValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.INT) { javaLangInteger.EmitCheckcast(ilgen); intValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.FLOAT) { javaLangFloat.EmitCheckcast(ilgen); floatValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.LONG) { javaLangLong.EmitCheckcast(ilgen); longValue.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.DOUBLE) { javaLangDouble.EmitCheckcast(ilgen); doubleValue.EmitCall(ilgen); } else { throw new InvalidOperationException(); } }
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); } }
private static void DoEmit(DynamicTypeWrapper.FinishContext context, TypeWrapper wrapper, CodeEmitter ilgen, FieldWrapper field) { ConstructorBuilder cb; bool exists; lock (map) { exists = map.TryGetValue(field, out cb); } if (!exists) { // note that we don't need to lock here, because we're running as part of FinishCore, which is already protected by a lock TypeWrapper arfuTypeWrapper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.IntrinsicAtomicReferenceFieldUpdater"); TypeBuilder tb = wrapper.TypeAsBuilder.DefineNestedType("__<ARFU>_" + field.Name + field.Signature.Replace('.', '/'), TypeAttributes.NestedPrivate | TypeAttributes.Sealed, arfuTypeWrapper.TypeAsBaseType); EmitCompareAndSet("compareAndSet", tb, field.GetField()); EmitGet(tb, field.GetField()); EmitSet("set", tb, field.GetField()); cb = tb.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, Type.EmptyTypes); lock (map) { map.Add(field, cb); } CodeEmitter ctorilgen = CodeEmitter.Create(cb); ctorilgen.Emit(OpCodes.Ldarg_0); MethodWrapper basector = arfuTypeWrapper.GetMethodWrapper("<init>", "()V", false); basector.Link(); basector.EmitCall(ctorilgen); ctorilgen.Emit(OpCodes.Ret); ctorilgen.DoEmit(); context.RegisterPostFinishProc(delegate { arfuTypeWrapper.Finish(); tb.CreateType(); }); } ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Newobj, cb); }
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) { #if NETSTANDARD Class = Class.Replace("mscorlib", Universe.CoreLibName); #endif 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); }
internal static void EmitBox(CodeEmitter ilgen, TypeWrapper tw) { if (tw == PrimitiveTypeWrapper.BYTE) { valueOfByte.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.BOOLEAN) { valueOfBoolean.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.SHORT) { valueOfShort.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.CHAR) { valueOfCharacter.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.INT) { valueOfInteger.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.FLOAT) { valueOfFloat.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.LONG) { valueOfLong.EmitCall(ilgen); } else if (tw == PrimitiveTypeWrapper.DOUBLE) { valueOfDouble.EmitCall(ilgen); } else { throw new InvalidOperationException(); } }
private static bool Reflection_getCallerClass(EmitIntrinsicContext eic) { if (eic.Caller.HasCallerID) { int arg = eic.Caller.GetParametersForDefineMethod().Length - 1; if (!eic.Caller.IsStatic) { arg++; } eic.Emitter.EmitLdarg(arg); MethodWrapper mw; if (MatchInvokeStatic(eic, 1, "java.lang.ClassLoader", "getClassLoader", "(Ljava.lang.Class;)Ljava.lang.ClassLoader;")) { eic.PatchOpCode(1, NormalizedByteCode.__nop); mw = [email protected]("getCallerClassLoader", "()Ljava.lang.ClassLoader;", false); } else { mw = [email protected]("getCallerClass", "()Ljava.lang.Class;", false); } mw.Link(); mw.EmitCallvirt(eic.Emitter); return(true); } else if (DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature)) { // since the non-intrinsic version of Reflection.getCallerClass() always throws an exception, we have to redirect to the dynamic version MethodWrapper getCallerClass = ClassLoaderWrapper.LoadClassCritical("sun.reflect.Reflection").GetMethodWrapper("getCallerClass", "(I)Ljava.lang.Class;", false); getCallerClass.Link(); eic.Emitter.EmitLdc_I4(2); getCallerClass.EmitCall(eic.Emitter); return(true); } else { StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature); } return(false); }
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); }
internal sealed override void Generate(CodeGenContext context, CodeEmitter ilgen) { Debug.Assert(Name != null); if (Name == ".ctor") { Debug.Assert(Class == null && type != null); Type[] argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); ConstructorInfo ci = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, CallingConventions.Standard, argTypes, null); if (ci == null) { throw new InvalidOperationException("Missing .ctor: " + type + "..ctor" + Sig); } ilgen.Emit(opcode, ci); } else { Debug.Assert(Class == null ^ type == null); if (Class != null) { Debug.Assert(Sig != null); MethodWrapper method = context.ClassLoader.LoadClassByDottedName(Class).GetMethodWrapper(Name, Sig, false); if (method == null) { throw new InvalidOperationException("method not found: " + Class + "." + Name + Sig); } method.Link(); // TODO this code is part of what Compiler.CastInterfaceArgs (in compiler.cs) does, // it would be nice if we could avoid this duplication... TypeWrapper[] argTypeWrappers = method.GetParameters(); for (int i = 0; i < argTypeWrappers.Length; i++) { if (argTypeWrappers[i].IsGhost) { CodeEmitterLocal[] temps = new CodeEmitterLocal[argTypeWrappers.Length + (method.IsStatic ? 0 : 1)]; for (int j = temps.Length - 1; j >= 0; j--) { TypeWrapper tw; if (method.IsStatic) { tw = argTypeWrappers[j]; } else { if (j == 0) { tw = method.DeclaringType; } else { tw = argTypeWrappers[j - 1]; } } if (tw.IsGhost) { tw.EmitConvStackTypeToSignatureType(ilgen, null); } temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType); ilgen.Emit(OpCodes.Stloc, temps[j]); } for (int j = 0; j < temps.Length; j++) { ilgen.Emit(OpCodes.Ldloc, temps[j]); } break; } } if (opcode.Value == OpCodes.Call.Value) { method.EmitCall(ilgen); } else if (opcode.Value == OpCodes.Callvirt.Value) { method.EmitCallvirt(ilgen); } else if (opcode.Value == OpCodes.Newobj.Value) { method.EmitNewobj(ilgen); } else { // ldftn or ldvirtftn ilgen.Emit(opcode, (MethodInfo)method.GetMethod()); } } else { Type[] argTypes; if (Sig.StartsWith("(")) { argTypes = context.ClassLoader.ArgTypeListFromSig(Sig); } else if (Sig == "") { argTypes = Type.EmptyTypes; } else { string[] types = Sig.Split(';'); argTypes = new Type[types.Length]; for (int i = 0; i < types.Length; i++) { argTypes[i] = StaticCompiler.GetTypeForMapXml(context.ClassLoader, types[i]); } } MethodInfo mi = StaticCompiler.GetTypeForMapXml(context.ClassLoader, type).GetMethod(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, argTypes, null); if (mi == null) { throw new InvalidOperationException("Missing method: " + type + "." + Name + Sig); } ilgen.Emit(opcode, mi); } } }
internal void Call(MethodWrapper mw) { mw.EmitCall(ilgen); }
/** * Emit an invoke for the given name, using the MemberName directly. */ void emitStaticInvoke(MemberName member, Name name) { // push arguments emitPushArguments(name); // invocation if (member.isMethod()) { if (IsMethodHandleLinkTo(member)) { MethodType mt = member.getMethodType(); TypeWrapper[] args = new TypeWrapper[mt.parameterCount()]; for (int j = 0; j < args.Length; j++) { args[j] = TypeWrapper.FromClass(mt.parameterType(j)); args[j].Finish(); } TypeWrapper ret = TypeWrapper.FromClass(mt.returnType()); ret.Finish(); Compiler.MethodHandleMethodWrapper.EmitLinkToCall(ilgen, args, ret); ret.EmitConvSignatureTypeToStackType(ilgen); } else if (IsMethodHandleInvokeBasic(member)) { EmitInvokeBasic(member.getMethodType()); } else { switch (member.getReferenceKind()) { case MethodHandleNatives.Constants.REF_invokeInterface: case MethodHandleNatives.Constants.REF_invokeSpecial: case MethodHandleNatives.Constants.REF_invokeStatic: case MethodHandleNatives.Constants.REF_invokeVirtual: break; default: throw new BailoutException(Bailout.UnsupportedRefKind, member); } MethodWrapper mw = GetMethodWrapper(member); if (!IsStaticallyInvocable(mw)) { throw new BailoutException(Bailout.NotStaticallyInvocable, member); } mw.Link(); mw.DeclaringType.Finish(); mw.ResolveMethod(); if (mw.HasCallerID) { EmitConstant(DynamicCallerIDProvider.Instance); ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCallerID); } if (mw.IsStatic || member.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeSpecial) { mw.EmitCall(ilgen); } else { mw.EmitCallvirt(ilgen); } mw.ReturnType.EmitConvSignatureTypeToStackType(ilgen); } } else if (member.isField()) { FieldWrapper fw = GetFieldWrapper(member); if (!IsStaticallyInvocable(fw)) { throw new BailoutException(Bailout.NotStaticallyInvocable, member); } fw.Link(); fw.DeclaringType.Finish(); fw.ResolveField(); switch (member.getReferenceKind()) { case MethodHandleNatives.Constants.REF_getField: case MethodHandleNatives.Constants.REF_getStatic: fw.EmitGet(ilgen); fw.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilgen); break; case MethodHandleNatives.Constants.REF_putField: case MethodHandleNatives.Constants.REF_putStatic: fw.EmitSet(ilgen); break; default: throw new BailoutException(Bailout.UnsupportedRefKind, member); } } else { throw new BailoutException(Bailout.NotStaticallyInvocable, member); } }