[Mono-dev] TypeForwardedFrom

Neale Ferguson NealeFerguson at verizon.net
Fri Apr 12 15:17:37 UTC 2013


I wondered if it was a case of needing to "prime the pump" by invoking
aType.Assembly.FullName so that the full name would be set such that
subsequent getId calls would succeed, as I was seeing this in the --trace
output:

[0x7f1650c02740: 2.19819 4] ENTER: (wrapper managed-to-native)
System.Reflection.Assembly:get_fullname
(System.Reflection.Assembly)([System.Reflection.MonoAssembly:0x7f1650a35a20]
, )
[0x7f1650c02740: 2.19822 4] LEAVE: (wrapper managed-to-native)
System.Reflection.Assembly:get_fullname
(System.Reflection.Assembly)[STRING:0x7f1650a36b40:System, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]
[0x7f1650c02740: 2.19836 4] ENTER: (wrapper runtime-invoke)
object:runtime_invoke_void__this__
(object,intptr,intptr,intptr)([System.NullReferenceException:0x7f1650a619a0]
, (nil), (nil), 0x7f164f667120, )
[0x7f1650c02740: 2.19839 4] LEAVE: (wrapper runtime-invoke)
object:runtime_invoke_void__this__
(object,intptr,intptr,intptr)[OBJECT:(nil)]

After which the segv occurs.

I simply added:

string asmName;
int asmId;
asmName = aType.Assembly.FullName;
asmId = GetAssemblyId(aType.Assembly);

Prior to the 

return WriteAssemblyName (writer,
GetForwardedAttribute.GetAssemblyName(aType));
 
However, while the aType.Assembly.FullName returns the expected string into
asmName, the subsequent call to GetAssemblyId(aType.Assembly) ends up with a
segv.

Neale

On 4/12/13 10:46 AM, "Neale Ferguson" <NealeFerguson at verizon.net> wrote:

> In both the MONO_REFLECTION_SERIALIZER=yes & no cases we die in
> GetAssemblyId when called from WriteTypeSpec:
> 
> case TypeTag.GenericType:
>       writer.Write (type.FullName);
>       writer.Write ((int)GetAssemblyId (type.Assembly));
>       break;
> 
> I put a couple of WriteLines in the ObjectWriter version before each call
> and prior to the break and saw:
> 
> type.FullName = TypeTag.GenericType:
> System.Collections.ObjectModel.ObservableCollection`1[[System.String,
> mscorlib, Version=4.0.0.0, Culture=neutral,
> PublicKeyToken=b77a5c561934e089]]
> 
> Type.Assembly = Getting assembly id System, Version=4.0.0.0,
> Culture=neutral, PublicKeyToken=b77a5c561934e089
> 
> I'm not sure why commenting out the EmitLoadType/EmitCall to
> WriteTypeAssembly and using the previous EmitLoadAssemblyType/EmitCall to
> WriteAssembly causes things not to fail.
> 
> 
> On 4/11/13 6:40 PM, "Robert Jordan" <robertj at gmx.net> wrote:
> 
>> This looks good. Maybe the error is somewhere else, so try to
>> disable the IL serializer with
>> 
>> MONO_REFLECTION_SERIALIZER=yes mono yourtest.exe
>> 
>> If it still breaks, the bug is in WriteTypeAssembly.
>> 
>> Robert
>> 
>> On 11.04.2013 20:58, Neale Ferguson wrote:
>>> This, in my naivety, looks like what I want. However, it's not and leads to
>>> a NULL reference exception. What I am attempting to do is change the
>>> generated code from calling ow.WriteAssembly(writer, memberType.Assembly) to
>>> ow.WriteTypeAssembly(writer, memberType)
>>> 
>>> ---
>>> a/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenera
>>> tor.cs
>>> +++
>>> b/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/CodeGenera
>>> tor.cs
>>> @@ -115,8 +115,10 @@ namespace
>>> System.Runtime.Serialization.Formatters.Binary
>>> -                                       // EMIT ow.WriteAssembly (writer,
>>> memberType.Assembly);
>>> +                                       // EMIT ow.WriteTypeAssembly
>>> (writer, memberType);
>>> 
>>>                                          gen.Emit (OpCodes.Ldarg_1);
>>>                                          gen.Emit (OpCodes.Ldarg_2);
>>> -                                       EmitLoadTypeAssembly (gen,
>>> memberType, field.Name);
>>> -                                       gen.EmitCall (OpCodes.Callvirt,
>>> typeof(ObjectWriter).GetMethod("WriteAssembly"), null);
>>> +//                                     EmitLoadTypeAssembly (gen,
>>> memberType, field.Name);
>>> +//                                     gen.EmitCall (OpCodes.Callvirt,
>>> typeof(ObjectWriter).GetMethod("WriteAssembly"), null);
>>> +                                       EmitLoadType (gen, memberType);
>>> +                                       gen.EmitCall (OpCodes.Callvirt,
>>> typeof(ObjectWriter).GetMethod("WriteTypeAssembly"), null);
>>>                                          gen.Emit (OpCodes.Pop);
>>>                                  }
>>>                          }
>>> @@ -318,6 +320,12 @@ namespace
>>> System.Runtime.Serialization.Formatters.Binary
>>>                          gen.EmitCall (OpCodes.Callvirt,
>>> typeof(Type).GetProperty("Assembly").GetGetMethod(), null);
>>>                  }
>>> 
>>> +               static void EmitLoadType (ILGenerator gen, Type type)
>>> +               {
>>> +                       gen.Emit (OpCodes.Ldtoken, type);
>>> +                       gen.EmitCall (OpCodes.Call,
>>> typeof(Type).GetMethod("GetTypeFromHandle"), null);
>>> +               }
>>> +
>>>                  static void EmitWrite (ILGenerator gen, Type type)
>>>                  {
>>>                          gen.EmitCall (OpCodes.Callvirt,
>>> typeof(BinaryWriter).GetMethod("Write", new Type[] { type }), null);
>>> 
>>> 
>>> 
>>> On 4/11/13 1:21 PM, "Robert Jordan" <robertj at gmx.net> wrote:
>>> 
>>>> Neale,
>>>> 
>>>> Rename & Modify WriteAssembly to take a Type argument:
>>>> 
>>>> public int WriteTypeAssembly (BinaryWriter writer, Type type)
>>>> {
>>>> return WriteAssemblyName (writer, type.GetAssemblyName ());
>>>> }
>>>> 
>>>> (GetAssemblyName () is the extension from my first post)
>>>> 
>>>> Then change all call sites such that they pass the type directly
>>>> instead type.Assembly to WriteTypeAssembly. Don't forget
>>>> CodeGenerator.cs, where things get nastier due to IL code
>>>> generation ;)
>>>> 
>>>> Robert
>>>> 
>>>> 
>>>> On 11.04.2013 17:48, Neale Ferguson wrote:
>>>>> Thanks again and apologies for peppering you with questions. In
>>>>> WriteAssemblyName() it retrieves the AssemblyFullName so I'm not sure how
>>>>> I
>>>>> can get the forwarded name without the associated Type value.
>>>>> 
>>>>> Neale
>>>>> 
>>>>> On 4/11/13 10:04 AM, "Robert Jordan" <robertj at gmx.net> wrote:
>>>>> 
>>>>>> Neale,
>>>>>> 
>>>>>> The icall's declaration:
>>>>>> 
>>>>>> mono/metadata/icall-def.h:ICALL(ASSEM_23, "get_fullname",
>>>>>> ves_icall_System_Reflection_Assembly_get_fullName)
>>>>>> 
>>>>>> The function:
>>>>>> 
>>>>>> mono/metadata/icall.c:ves_icall_System_Reflection_Assembly_get_fullName
>>>>>> (MonoReflectionAssembly *assembly)
>>>>>> 
>>>>>> 
>>>>>> I won't add this overhead to the Assembly class because it's a Type
>>>>>> feature after all. You can handle this locally in ObjectWriter,
>>>>>> as this is the only place where TypeForwardedFrom is used at all.
>>>>> 
>>>>> 
>>>> 
>>> 
>>> 
>> 
> 
> 
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list




More information about the Mono-devel-list mailing list