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 && 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 DoEmit(context, wrapper, ilgen, field); return true; } } } return false; }
internal override string AllocMangledName(DynamicTypeWrapper tw) { lock (dynamicTypes) { return(TypeNameMangleImpl(dynamicTypes, tw.Name, tw)); } }
internal static ConstructorInfo AddAutomagicSerialization(DynamicTypeWrapper wrapper, TypeBuilder typeBuilder) { ConstructorInfo serializationCtor = null; if (wrapper.GetClassLoader().NoAutomagicSerialization) { // do nothing } else if ((wrapper.Modifiers & IKVM.Attributes.Modifiers.Enum) != 0) { MarkSerializable(typeBuilder); } else if (wrapper.IsSubTypeOf(serializable) && IsSafeForAutomagicSerialization(wrapper)) { if (wrapper.IsSubTypeOf(externalizable)) { MethodWrapper ctor = wrapper.GetMethodWrapper("<init>", "()V", false); if (ctor != null && ctor.IsPublic) { MarkSerializable(typeBuilder); ctor.Link(); serializationCtor = AddConstructor(typeBuilder, ctor, null, true); if (!wrapper.BaseTypeWrapper.IsSubTypeOf(serializable)) { AddGetObjectData(typeBuilder); } if (wrapper.BaseTypeWrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", true) != null) { RemoveReadResolve(typeBuilder); } } } else if (wrapper.BaseTypeWrapper.IsSubTypeOf(serializable)) { ConstructorInfo baseCtor = wrapper.GetBaseSerializationConstructor(); if (baseCtor != null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly)) { MarkSerializable(typeBuilder); serializationCtor = AddConstructor(typeBuilder, null, baseCtor, false); AddReadResolve(wrapper, typeBuilder); } } else { MethodWrapper baseCtor = wrapper.BaseTypeWrapper.GetMethodWrapper("<init>", "()V", false); if (baseCtor != null && baseCtor.IsAccessibleFrom(wrapper.BaseTypeWrapper, wrapper, wrapper)) { MarkSerializable(typeBuilder); AddGetObjectData(typeBuilder); #if STATIC_COMPILER // because the base type can be a __WorkaroundBaseClass__, we may need to replace the constructor baseCtor = ((AotTypeWrapper)wrapper).ReplaceMethodWrapper(baseCtor); #endif baseCtor.Link(); serializationCtor = AddConstructor(typeBuilder, baseCtor, null, true); AddReadResolve(wrapper, typeBuilder); } } } return serializationCtor; }
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)) { StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature); } return(false); }
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 InitMethodImpl(MemberName self, MethodWrapper mw, bool wantSpecial) { #if !FIRST_PASS int flags = (int)mw.Modifiers; flags |= mw.IsConstructor ? MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR : MethodHandleNatives.Constants.MN_IS_METHOD; if (mw.IsStatic) { flags |= MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; } else if (mw.IsPrivate || mw.IsFinal || mw.IsConstructor || wantSpecial) { flags |= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; } else if (mw.DeclaringType.IsInterface) { flags |= MethodHandleNatives.Constants.REF_invokeInterface << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; } else { flags |= MethodHandleNatives.Constants.REF_invokeVirtual << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; } if (mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature)) { flags |= MemberName.CALLER_SENSITIVE; } if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper) { java.lang.Class[] parameters1 = new java.lang.Class[mw.GetParameters().Length]; for (int i = 0; i < mw.GetParameters().Length; i++) { parameters1[i] = mw.GetParameters()[i].ClassObject; } MethodType mt = MethodType.methodType(typeof(string), parameters1); typeof(MemberName).GetField("type", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(self, mt); self.vmtarget = CreateMemberNameDelegate(mw, null, false, mt); flags -= MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; flags += MethodHandleNatives.Constants.REF_invokeStatic << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; flags -= MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR; flags += MethodHandleNatives.Constants.MN_IS_METHOD; flags += MethodHandleNatives.Constants.ACC_STATIC; self._flags(flags); self._clazz(mw.DeclaringType.ClassObject); return; } self._flags(flags); self._clazz(mw.DeclaringType.ClassObject); int firstParam = mw.IsStatic ? 0 : 1; java.lang.Class[] parameters = new java.lang.Class[mw.GetParameters().Length + firstParam]; for (int i = 0; i < mw.GetParameters().Length; i++) { parameters[i + firstParam] = mw.GetParameters()[i].ClassObject; } if (!mw.IsStatic) { parameters[0] = mw.DeclaringType.ClassObject; } self.vmtarget = CreateMemberNameDelegate(mw, mw.ReturnType.ClassObject, !wantSpecial, MethodType.methodType(mw.ReturnType.ClassObject, parameters)); #endif }
internal static MethodBuilder AddAutomagicSerialization(DynamicTypeWrapper wrapper, TypeBuilder typeBuilder) { MethodBuilder serializationCtor = null; if ((wrapper.Modifiers & IKVM.Attributes.Modifiers.Enum) != 0) { MarkSerializable(typeBuilder); } else if (wrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper) && IsSafeForAutomagicSerialization(wrapper)) { if (wrapper.IsSubTypeOf(externalizable)) { MethodWrapper ctor = wrapper.GetMethodWrapper("<init>", "()V", false); if (ctor != null && ctor.IsPublic) { MarkSerializable(typeBuilder); ctor.Link(); serializationCtor = AddConstructor(typeBuilder, ctor, null, true); if (!wrapper.BaseTypeWrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper)) { AddGetObjectData(typeBuilder); } if (wrapper.BaseTypeWrapper.GetMethodWrapper("readResolve", "()Ljava.lang.Object;", true) != null) { RemoveReadResolve(typeBuilder); } } } else if (wrapper.BaseTypeWrapper.IsSubTypeOf(CoreClasses.java.io.Serializable.Wrapper)) { MethodBase baseCtor = wrapper.GetBaseSerializationConstructor(); if (baseCtor != null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly)) { MarkSerializable(typeBuilder); serializationCtor = AddConstructor(typeBuilder, null, baseCtor, false); AddReadResolve(wrapper, typeBuilder); } } else { MethodWrapper baseCtor = wrapper.BaseTypeWrapper.GetMethodWrapper("<init>", "()V", false); if (baseCtor != null && baseCtor.IsAccessibleFrom(wrapper.BaseTypeWrapper, wrapper, wrapper)) { MarkSerializable(typeBuilder); AddGetObjectData(typeBuilder); #if STATIC_COMPILER // because the base type can be a __WorkaroundBaseClass__, we may need to replace the constructor baseCtor = ((AotTypeWrapper)wrapper).ReplaceMethodWrapper(baseCtor); #endif baseCtor.Link(); serializationCtor = AddConstructor(typeBuilder, baseCtor, null, true); AddReadResolve(wrapper, typeBuilder); } } } return(serializationCtor); }
public void CanSetProperty() { var expectedValue = "TestValue"; var propName = "TestProp"; var wrapper = new DynamicTypeWrapper(); wrapper.SetPropertyValue(propName, expectedValue); var actual = wrapper.GetPropertyValue(propName); Assert.Equal(expectedValue, actual); }
internal sealed override TypeWrapper DefineClassImpl(Dictionary <string, TypeWrapper> types, ClassFile f, ClassLoaderWrapper classLoader, object protectionDomain) { DynamicTypeWrapper type; #if STATIC_COMPILER type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader); #else type = new DynamicTypeWrapper(f, classLoader); #endif // this step can throw a retargettable exception, if the class is incorrect bool hasclinit; type.CreateStep1(out hasclinit); // now we can allocate the mangledTypeName, because the next step cannot fail string mangledTypeName = AllocMangledName(f.Name); // This step actually creates the TypeBuilder. It is not allowed to throw any exceptions, // if an exception does occur, it is due to a programming error in the IKVM or CLR runtime // and will cause a CriticalFailure and exit the process. type.CreateStep2NoFail(hasclinit, mangledTypeName); lock (types) { // in very extreme conditions another thread may have beaten us to it // and loaded (not defined) a class with the same name, in that case // we'll leak the the Reflection.Emit defined type. Also see the comment // in ClassLoaderWrapper.RegisterInitiatingLoader(). TypeWrapper race; types.TryGetValue(f.Name, out race); if (race == null) { lock (dynamicTypes) { Debug.Assert(dynamicTypes.ContainsKey(mangledTypeName) && dynamicTypes[mangledTypeName] == null); dynamicTypes[mangledTypeName] = type; } types[f.Name] = type; #if !STATIC_COMPILER && !FIRST_PASS java.lang.Class clazz = new java.lang.Class(null); #if __MonoCS__ TypeWrapper.SetTypeWrapperHack(clazz, type); #else clazz.typeWrapper = type; #endif clazz.pd = (java.security.ProtectionDomain)protectionDomain; type.SetClassObject(clazz); #endif } else { throw new LinkageError("duplicate class definition: " + f.Name); } } return(type); }
public void GetHashCodeEqualForEqualWrappers() { var expectedValue = "TestValue"; var propName = "TestProp"; var wrapper = new DynamicTypeWrapper(); wrapper.SetPropertyValue(propName, expectedValue); var wrapper2 = new DynamicTypeWrapper(); wrapper2.SetPropertyValue(propName, expectedValue); Assert.Equal(wrapper.GetHashCode(), wrapper2.GetHashCode()); }
public void CanEqualWrappers() { var expectedValue = "TestValue"; var propName = "TestProp"; var wrapper = new DynamicTypeWrapper(); wrapper.SetPropertyValue(propName, expectedValue); var wrapper2 = new DynamicTypeWrapper(); wrapper2.SetPropertyValue(propName, expectedValue); Assert.Equal(wrapper, wrapper2); }
public void CanTryGetProperty() { var expectedValue = "TestValue"; var propName = "TestProp"; var wrapper = new DynamicTypeWrapper(); wrapper.SetPropertyValue(propName, expectedValue); object actual; Assert.True(wrapper.TryGetPropertyValue(propName, out actual)); Assert.Equal(expectedValue, actual); }
/// <summary> /// Writes the JSON representation of the object. /// </summary> /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param> /// <param name="value">The value.</param> /// <param name="serializer">The calling serializer.</param> public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (serializer is null) { throw new ArgumentNullException(nameof(serializer)); } DynamicTypeWrapper dynamicTypeWrapper = value as DynamicTypeWrapper; if (dynamicTypeWrapper != null) { serializer.Serialize(writer, dynamicTypeWrapper.Values); } }
private static bool IsSupportedImplMethod(ClassFile.ConstantPoolItemMethodHandle implMethod, TypeWrapper caller, TypeWrapper[] captured, ClassFile.ConstantPoolItemMethodType instantiatedMethodType) { switch (implMethod.Kind) { case ClassFile.RefKind.invokeVirtual: case ClassFile.RefKind.invokeInterface: case ClassFile.RefKind.newInvokeSpecial: case ClassFile.RefKind.invokeStatic: case ClassFile.RefKind.invokeSpecial: break; default: return(false); } MethodWrapper mw = (MethodWrapper)implMethod.Member; if (mw == null || mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature)) { return(false); } TypeWrapper instance; if (mw.IsConstructor) { instance = mw.DeclaringType; } else if (mw.IsStatic) { instance = null; } else { // if implMethod is an instance method, the type of the first captured value must be subtype of implMethod.DeclaringType instance = captured.Length == 0 ? instantiatedMethodType.GetArgTypes()[0] : captured[0]; if (!instance.IsAssignableTo(mw.DeclaringType)) { return(false); } } if (!mw.IsAccessibleFrom(mw.DeclaringType, caller, instance)) { return(false); } mw.Link(); return(true); }
private object GetValue(DynamicTypeWrapper wrapper, string path) { var parts = path.Split('/'); foreach (var part in parts) { object value; wrapper.TryGetPropertyValue(part, out value); wrapper = value as DynamicTypeWrapper; if (wrapper == null) { return(value); } } Assert.False(true, "Property " + path + " not found"); return(null); }
internal sealed override TypeWrapper DefineClassImpl(Dictionary <string, TypeWrapper> types, TypeWrapper host, ClassFile f, ClassLoaderWrapper classLoader, ProtectionDomain protectionDomain) { #if STATIC_COMPILER AotTypeWrapper type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader); type.CreateStep1(); types[f.Name] = type; return(type); #elif FIRST_PASS return(null); #else // this step can throw a retargettable exception, if the class is incorrect DynamicTypeWrapper type = new DynamicTypeWrapper(host, f, classLoader, protectionDomain); // This step actually creates the TypeBuilder. It is not allowed to throw any exceptions, // if an exception does occur, it is due to a programming error in the IKVM or CLR runtime // and will cause a CriticalFailure and exit the process. type.CreateStep1(); type.CreateStep2(); if (types == null) { // we're defining an anonymous class, so we don't need any locking TieClassAndWrapper(type, protectionDomain); return(type); } lock (types) { // in very extreme conditions another thread may have beaten us to it // and loaded (not defined) a class with the same name, in that case // we'll leak the the Reflection.Emit defined type. Also see the comment // in ClassLoaderWrapper.RegisterInitiatingLoader(). TypeWrapper race; types.TryGetValue(f.Name, out race); if (race == null) { types[f.Name] = type; TieClassAndWrapper(type, protectionDomain); } else { throw new LinkageError("duplicate class definition: " + f.Name); } } return(type); #endif // STATIC_COMPILER }
public NodeInStream(INodeIn nodeIn, IConnectionHandler handler, T defaultValue = default(T)) { handler = handler ?? new DefaultConnectionHandler(null, typeof(T)); FNodeIn = nodeIn; object inputInterface; if (typeof(T).UsesDynamicAssembly()) { inputInterface = new DynamicTypeWrapper(this); } else { inputInterface = this; } FNodeIn.SetConnectionHandler(handler, inputInterface); FAutoValidate = nodeIn.AutoValidate; FDefaultValue = defaultValue; FUpstreamStream = FNullStream; }
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); context.RegisterPostFinishProc(delegate { arfuTypeWrapper.Finish(); tb.CreateType(); }); } ilgen.LazyEmitPop(); ilgen.LazyEmitPop(); ilgen.LazyEmitPop(); ilgen.Emit(OpCodes.Newobj, cb); }
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); }
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 ResolveMethod(MemberName self, JlClass caller) { bool invokeSpecial = self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeSpecial; bool newInvokeSpecial = self.getReferenceKind() == MethodHandleNatives.Constants.REF_newInvokeSpecial; bool searchBaseClasses = !newInvokeSpecial; MethodWrapper mw = TypeWrapper.FromClass(self.getDeclaringClass()).GetMethodWrapper(self.getName(), self.getSignature().Replace('/', '.'), searchBaseClasses); if (mw == null) { if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeInterface) { mw = TypeWrapper.FromClass(self.getDeclaringClass()).GetInterfaceMethod(self.getName(), self.getSignature().Replace('/', '.')); if (mw == null) { mw = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(self.getName(), self.getSignature().Replace('/', '.'), false); } if (mw != null && mw.IsConstructor) { throw new java.lang.IncompatibleClassChangeError("Found interface " + self.getDeclaringClass().getName() + ", but class was expected"); } } if (mw == null) { string msg = String.Format(invokeSpecial ? "{0}: method {1}{2} not found" : "{0}.{1}{2}", self.getDeclaringClass().getName(), self.getName(), self.getSignature()); throw new java.lang.NoSuchMethodError(msg); } } if (mw.IsStatic != IsReferenceKindStatic(self.getReferenceKind())) { string msg = String.Format(mw.IsStatic ? "Expecting non-static method {0}.{1}{2}" : "Expected static method {0}.{1}{2}", mw.DeclaringType.Name, self.getName(), self.getSignature()); throw new java.lang.IncompatibleClassChangeError(msg); } if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeVirtual && mw.DeclaringType.IsInterface) { throw new java.lang.IncompatibleClassChangeError("Found interface " + mw.DeclaringType.Name + ", but class was expected"); } if (!mw.IsPublic && self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeInterface) { throw new java.lang.IncompatibleClassChangeError("private interface method requires invokespecial, not invokeinterface: method " + self.getDeclaringClass().getName() + "." + self.getName() + self.getSignature()); } if (mw.IsConstructor && mw.DeclaringType == CoreClasses.java.lang.String.Wrapper) { self.vmtarget = CreateMemberNameDelegate(mw, caller, false, self.getMethodType().changeReturnType(CoreClasses.java.lang.String.Wrapper.ClassObject)); } else if (!mw.IsConstructor || invokeSpecial || newInvokeSpecial) { MethodType methodType = self.getMethodType(); if (!mw.IsStatic) { methodType = methodType.insertParameterTypes(0, mw.DeclaringType.ClassObject); if (newInvokeSpecial) { methodType = methodType.changeReturnType(java.lang.Void.TYPE); } } self.vmtarget = CreateMemberNameDelegate(mw, caller, self.hasReceiverTypeDispatch(), methodType); } SetModifiers(self, mw); self._flags(self._flags() | (mw.IsConstructor ? MethodHandleNatives.Constants.MN_IS_CONSTRUCTOR : MethodHandleNatives.Constants.MN_IS_METHOD)); if (self.getReferenceKind() == MethodHandleNatives.Constants.REF_invokeVirtual && (mw.IsPrivate || mw.IsFinal || mw.IsConstructor)) { int flags = self._flags(); flags -= MethodHandleNatives.Constants.REF_invokeVirtual << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; flags += MethodHandleNatives.Constants.REF_invokeSpecial << MethodHandleNatives.Constants.MN_REFERENCE_KIND_SHIFT; self._flags(flags); } if (mw.HasCallerID || DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(mw.DeclaringType.Name, mw.Name, mw.Signature)) { self._flags(self._flags() | MemberName.CALLER_SENSITIVE); } }
internal override string AllocMangledName(DynamicTypeWrapper tw) { lock(dynamicTypes) { return TypeNameMangleImpl(dynamicTypes, tw.Name, tw); } }
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 bool EmitImpl(DynamicTypeWrapper.FinishContext context, ClassFile classFile, ClassFile.ConstantPoolItemInvokeDynamic cpi, ClassFile.BootstrapMethod bsm, CodeEmitter ilgen) { if (HasUnloadable(cpi)) { Fail("cpi has unloadable"); return false; } bool serializable = false; TypeWrapper[] markers = TypeWrapper.EmptyArray; ClassFile.ConstantPoolItemMethodType[] bridges = null; if (bsm.ArgumentCount > 3) { AltFlags flags = (AltFlags)classFile.GetConstantPoolConstantInteger(bsm.GetArgument(3)); serializable = (flags & AltFlags.Serializable) != 0; int argpos = 4; if ((flags & AltFlags.Markers) != 0) { markers = new TypeWrapper[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < markers.Length; i++) { if ((markers[i] = classFile.GetConstantPoolClassType(bsm.GetArgument(argpos++))).IsUnloadable) { Fail("unloadable marker"); return false; } } } if ((flags & AltFlags.Bridges) != 0) { bridges = new ClassFile.ConstantPoolItemMethodType[classFile.GetConstantPoolConstantInteger(bsm.GetArgument(argpos++))]; for (int i = 0; i < bridges.Length; i++) { bridges[i] = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(argpos++)); if (HasUnloadable(bridges[i])) { Fail("unloadable bridge"); return false; } } } } ClassFile.ConstantPoolItemMethodType samMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(0)); ClassFile.ConstantPoolItemMethodHandle implMethod = classFile.GetConstantPoolConstantMethodHandle(bsm.GetArgument(1)); ClassFile.ConstantPoolItemMethodType instantiatedMethodType = classFile.GetConstantPoolConstantMethodType(bsm.GetArgument(2)); if (HasUnloadable(samMethodType) || HasUnloadable((ClassFile.ConstantPoolItemMI)implMethod.MemberConstantPoolItem) || HasUnloadable(instantiatedMethodType)) { Fail("bsm args has unloadable"); return false; } TypeWrapper interfaceType = cpi.GetRetType(); MethodWrapper[] methodList; if (!CheckSupportedInterfaces(context.TypeWrapper, interfaceType, markers, bridges, out methodList)) { Fail("unsupported interface"); return false; } if (serializable && Array.Exists(methodList, delegate(MethodWrapper mw) { return mw.Name == "writeReplace" && mw.Signature == "()Ljava.lang.Object;"; })) { Fail("writeReplace"); return false; } if (!IsSupportedImplMethod(implMethod, context.TypeWrapper, cpi.GetArgTypes(), instantiatedMethodType)) { Fail("implMethod " + implMethod.MemberConstantPoolItem.Class + "::" + implMethod.MemberConstantPoolItem.Name + implMethod.MemberConstantPoolItem.Signature); return false; } TypeWrapper[] implParameters = GetImplParameters(implMethod); CheckConstraints(instantiatedMethodType, samMethodType, cpi.GetArgTypes(), implParameters); if (bridges != null) { foreach (ClassFile.ConstantPoolItemMethodType bridge in bridges) { if (bridge.Signature == samMethodType.Signature) { Fail("bridge signature matches sam"); return false; } if (!CheckConstraints(instantiatedMethodType, bridge, cpi.GetArgTypes(), implParameters)) { Fail("bridge constraints"); return false; } } } if (instantiatedMethodType.GetRetType() != PrimitiveTypeWrapper.VOID) { TypeWrapper Rt = instantiatedMethodType.GetRetType(); TypeWrapper Ra = GetImplReturnType(implMethod); if (Ra == PrimitiveTypeWrapper.VOID || !IsAdaptable(Ra, Rt, true)) { Fail("The return type Rt is void, or the return type Ra is not void and is adaptable to Rt"); return false; } } MethodWrapper interfaceMethod = null; List<MethodWrapper> methods = new List<MethodWrapper>(); foreach (MethodWrapper mw in methodList) { if (mw.Name == cpi.Name && mw.Signature == samMethodType.Signature) { interfaceMethod = mw; methods.Add(mw); } else if (mw.IsAbstract && !IsObjectMethod(mw)) { methods.Add(mw); } } if (interfaceMethod == null || !interfaceMethod.IsAbstract || IsObjectMethod(interfaceMethod) || !MatchSignatures(interfaceMethod, samMethodType)) { Fail("interfaceMethod"); return false; } TypeBuilder tb = context.DefineAnonymousClass(); // we're not implementing the interfaces recursively (because we don't care about .NET Compact anymore), // but should we decide to do that, we'd need to somehow communicate to AnonymousTypeWrapper what the 'real' interface is tb.AddInterfaceImplementation(interfaceType.TypeAsBaseType); if (serializable && Array.IndexOf(markers, CoreClasses.java.io.Serializable.Wrapper) == -1) { tb.AddInterfaceImplementation(CoreClasses.java.io.Serializable.Wrapper.TypeAsBaseType); } foreach (TypeWrapper marker in markers) { tb.AddInterfaceImplementation(marker.TypeAsBaseType); } ctor = CreateConstructorAndDispatch(context, cpi, tb, methods, implParameters, samMethodType, implMethod, instantiatedMethodType, serializable); AddDefaultInterfaceMethods(context, methodList, tb); return true; }
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; }
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.EmitBeq(label); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(label); } ilgen.Emit(OpCodes.Ldarg_0); mw.EmitCall(ilgen); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } }
internal override sealed TypeWrapper DefineClassImpl(Dictionary<string, TypeWrapper> types, ClassFile f, ClassLoaderWrapper classLoader, object protectionDomain) { DynamicTypeWrapper type; #if STATIC_COMPILER type = new AotTypeWrapper(f, (CompilerClassLoader)classLoader); #else type = new DynamicTypeWrapper(f, classLoader); #endif // this step can throw a retargettable exception, if the class is incorrect bool hasclinit; type.CreateStep1(out hasclinit); // now we can allocate the mangledTypeName, because the next step cannot fail string mangledTypeName = AllocMangledName(f.Name); // This step actually creates the TypeBuilder. It is not allowed to throw any exceptions, // if an exception does occur, it is due to a programming error in the IKVM or CLR runtime // and will cause a CriticalFailure and exit the process. type.CreateStep2NoFail(hasclinit, mangledTypeName); lock(types) { // in very extreme conditions another thread may have beaten us to it // and loaded (not defined) a class with the same name, in that case // we'll leak the the Reflection.Emit defined type. Also see the comment // in ClassLoaderWrapper.RegisterInitiatingLoader(). TypeWrapper race; types.TryGetValue(f.Name, out race); if(race == null) { lock(dynamicTypes) { Debug.Assert(dynamicTypes.ContainsKey(mangledTypeName) && dynamicTypes[mangledTypeName] == null); dynamicTypes[mangledTypeName] = type; } types[f.Name] = type; #if !STATIC_COMPILER && !FIRST_PASS java.lang.Class clazz = new java.lang.Class(null); #if __MonoCS__ TypeWrapper.SetTypeWrapperHack(clazz, type); #else clazz.typeWrapper = type; #endif clazz.pd = (java.security.ProtectionDomain)protectionDomain; type.SetClassObject(clazz); #endif } else { throw new LinkageError("duplicate class definition: " + f.Name); } } return type; }