diff options
-rw-r--r-- | src/inc/corcompile.h | 3 | ||||
-rw-r--r-- | src/inc/readytorun.h | 4 | ||||
-rw-r--r-- | src/vm/codeman.cpp | 14 | ||||
-rw-r--r-- | src/vm/compile.cpp | 6 | ||||
-rw-r--r-- | src/vm/compile.h | 7 | ||||
-rw-r--r-- | src/vm/genericdict.cpp | 52 | ||||
-rw-r--r-- | src/vm/jitinterface.cpp | 7 | ||||
-rw-r--r-- | src/vm/zapsig.cpp | 48 | ||||
-rw-r--r-- | src/vm/zapsig.h | 62 | ||||
-rw-r--r-- | src/zap/zapimport.cpp | 8 | ||||
-rw-r--r-- | src/zap/zapimport.h | 2 | ||||
-rw-r--r-- | tests/src/readytorun/fieldgetter.il | 215 | ||||
-rw-r--r-- | tests/src/readytorun/fieldgetter.ilproj | 36 | ||||
-rw-r--r-- | tests/src/readytorun/main.cs | 40 | ||||
-rw-r--r-- | tests/src/readytorun/mainv1.csproj | 3 | ||||
-rw-r--r-- | tests/src/readytorun/mainv2.csproj | 3 | ||||
-rw-r--r-- | tests/src/readytorun/test.cs | 26 |
17 files changed, 454 insertions, 82 deletions
diff --git a/src/inc/corcompile.h b/src/inc/corcompile.h index d3120d44dd..965de2845f 100644 --- a/src/inc/corcompile.h +++ b/src/inc/corcompile.h @@ -1784,7 +1784,8 @@ class ICorCompileInfo SigBuilder * pSigBuilder, LPVOID encodeContext, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL) = 0; + CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, + BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE) = 0; // Encode generic dictionary signature diff --git a/src/inc/readytorun.h b/src/inc/readytorun.h index 0fa1a1410e..fbcfc22046 100644 --- a/src/inc/readytorun.h +++ b/src/inc/readytorun.h @@ -15,8 +15,8 @@ #define READYTORUN_SIGNATURE 0x00525452 // 'RTR' -#define READYTORUN_MAJOR_VERSION 0x0001 -#define READYTORUN_MINOR_VERSION 0x0002 +#define READYTORUN_MAJOR_VERSION 0x0002 +#define READYTORUN_MINOR_VERSION 0x0000 struct READYTORUN_HEADER { diff --git a/src/vm/codeman.cpp b/src/vm/codeman.cpp index 8e1800d24f..9ce6bb2a20 100644 --- a/src/vm/codeman.cpp +++ b/src/vm/codeman.cpp @@ -6412,18 +6412,12 @@ UINT32 ReadyToRunJitManager::JitTokenToGCInfoVersion(const METHODTOKEN& MethodTo { CONTRACTL{ NOTHROW; - GC_NOTRIGGER; - HOST_NOCALLS; - SUPPORTS_DAC; + GC_NOTRIGGER; + HOST_NOCALLS; + SUPPORTS_DAC; } CONTRACTL_END; - READYTORUN_HEADER * header = JitTokenToReadyToRunInfo(MethodToken)->GetImage()->GetReadyToRunHeader(); - UINT32 gcInfoVersion = header->MajorVersion; - - // Currently there's only one version of GCInfo. - _ASSERTE(gcInfoVersion == GCINFO_VERSION); - - return gcInfoVersion; + return GCINFO_VERSION; } PTR_RUNTIME_FUNCTION ReadyToRunJitManager::JitTokenToRuntimeFunction(const METHODTOKEN& MethodToken) diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp index 7a3507eed6..b381b3f074 100644 --- a/src/vm/compile.cpp +++ b/src/vm/compile.cpp @@ -2368,7 +2368,8 @@ void CEECompileInfo::EncodeField( SigBuilder * pSigBuilder, LPVOID encodeContext, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken) + CORINFO_RESOLVED_TOKEN * pResolvedToken, + BOOL fEncodeUsingResolvedTokenSpecStreams) { STANDARD_VM_CONTRACT; @@ -2379,7 +2380,8 @@ void CEECompileInfo::EncodeField( pSigBuilder, encodeContext, pfnEncodeModule, - pResolvedToken); + pResolvedToken, + fEncodeUsingResolvedTokenSpecStreams); COOPERATIVE_TRANSITION_END(); } diff --git a/src/vm/compile.h b/src/vm/compile.h index c7a2d06ce9..19bbac3228 100644 --- a/src/vm/compile.h +++ b/src/vm/compile.h @@ -281,8 +281,8 @@ class CEECompileInfo : public ICorCompileInfo SigBuilder *pSigBuilder, LPVOID encodeContext, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, + CORINFO_RESOLVED_TOKEN *pResolvedToken, + CORINFO_RESOLVED_TOKEN *pConstrainedResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams); virtual mdToken TryEncodeMethodAsToken(CORINFO_METHOD_HANDLE handle, @@ -296,7 +296,8 @@ class CEECompileInfo : public ICorCompileInfo SigBuilder *pSigBuilder, LPVOID encodeContext, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken); + CORINFO_RESOLVED_TOKEN *pResolvedToken, + BOOL fEncodeUsingResolvedTokenSpecStreams); // Encode generic dictionary signature virtual void EncodeGenericSignature( diff --git a/src/vm/genericdict.cpp b/src/vm/genericdict.cpp index 70a4b8a627..4aca9e140b 100644 --- a/src/vm/genericdict.cpp +++ b/src/vm/genericdict.cpp @@ -690,6 +690,7 @@ Dictionary::PopulateEntry( switch (signatureKind) { case ENCODE_TYPE_HANDLE: kind = TypeHandleSlot; break; + case ENCODE_FIELD_HANDLE: kind = FieldDescSlot; break; case ENCODE_METHOD_HANDLE: kind = MethodDescSlot; break; case ENCODE_METHOD_ENTRY: kind = MethodEntrySlot; break; case ENCODE_VIRTUAL_ENTRY: kind = DispatchStubAddrSlot; break; @@ -1124,30 +1125,43 @@ Dictionary::PopulateEntry( case FieldDescSlot: { - TypeHandle th = ptr.GetTypeHandleThrowing( - pLookupModule, - &typeContext, - (nonExpansive ? ClassLoader::DontLoadTypes : ClassLoader::LoadTypes), - CLASS_LOADED, - FALSE, - NULL, - pZapSigContext); - if (th.IsNull()) + TypeHandle ownerType; + + if (isReadyToRunModule) { - _ASSERTE(nonExpansive); - return NULL; + FieldDesc* pField = ZapSig::DecodeField((Module*)pZapSigContext->pModuleContext, pZapSigContext->pInfoModule, ptr.GetPtr(), &typeContext, &ownerType); + _ASSERTE(!ownerType.IsNull()); + + if (!IsCompilationProcess()) + ownerType.AsMethodTable()->EnsureInstanceActive(); + + result = (CORINFO_GENERIC_HANDLE)pField; } - IfFailThrow(ptr.SkipExactlyOne()); + else + { + ownerType = ptr.GetTypeHandleThrowing( + pLookupModule, + &typeContext, + (nonExpansive ? ClassLoader::DontLoadTypes : ClassLoader::LoadTypes), + CLASS_LOADED, + FALSE, + NULL, + pZapSigContext); + if (ownerType.IsNull()) + { + _ASSERTE(nonExpansive); + return NULL; + } + IfFailThrow(ptr.SkipExactlyOne()); - DWORD fieldIndex; - IfFailThrow(ptr.GetData(&fieldIndex)); + DWORD fieldIndex; + IfFailThrow(ptr.GetData(&fieldIndex)); - if (!IsCompilationProcess()) - { - th.AsMethodTable()->EnsureInstanceActive(); - } + if (!IsCompilationProcess()) + ownerType.AsMethodTable()->EnsureInstanceActive(); - result = (CORINFO_GENERIC_HANDLE)th.AsMethodTable()->GetFieldDescByIndex(fieldIndex); + result = (CORINFO_GENERIC_HANDLE)ownerType.AsMethodTable()->GetFieldDescByIndex(fieldIndex); + } break; } diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index b72eaf3826..59172fe220 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -3137,10 +3137,8 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr switch (entryKind) { case TypeHandleSlot: - { pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_TypeHandle; break; - } case MethodDescSlot: case MethodEntrySlot: @@ -3161,8 +3159,11 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr break; } - case DeclaringTypeHandleSlot: case FieldDescSlot: + pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_FieldHandle; + break; + + case DeclaringTypeHandleSlot: case ConstrainedMethodEntrySlot: ThrowHR(E_NOTIMPL); diff --git a/src/vm/zapsig.cpp b/src/vm/zapsig.cpp index 93b34db31e..c619610f42 100644 --- a/src/vm/zapsig.cpp +++ b/src/vm/zapsig.cpp @@ -836,7 +836,7 @@ MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule, Module *pInfoModule, PCCOR_SIGNATURE pBuffer, SigTypeContext *pContext, - TypeHandle * ppTH, /*=NULL*/ + TypeHandle *ppTH, /*=NULL*/ PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars, /*=NULL*/ PCCOR_SIGNATURE *ppMethodSpecWithVars /*=NULL*/) { @@ -1013,7 +1013,20 @@ MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule, FieldDesc * ZapSig::DecodeField(Module *pReferencingModule, Module *pInfoModule, PCCOR_SIGNATURE pBuffer, - TypeHandle * ppTH /*=NULL*/) + TypeHandle *ppTH /*=NULL*/) +{ + STANDARD_VM_CONTRACT; + + SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables. + + return DecodeField(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH); +} + +FieldDesc * ZapSig::DecodeField(Module *pReferencingModule, + Module *pInfoModule, + PCCOR_SIGNATURE pBuffer, + SigTypeContext *pContext, + TypeHandle *ppTH /*=NULL*/) { CONTRACTL { @@ -1037,10 +1050,8 @@ FieldDesc * ZapSig::DecodeField(Module *pReferencingModule, ZapSig::Context zapSigContext(pInfoModule, pReferencingModule); ZapSig::Context * pZapSigContext = &zapSigContext; - SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables. - pOwnerMT = sig.GetTypeHandleThrowing(pInfoModule, - &typeContext, + pContext, ClassLoader::LoadTypes, CLASS_LOADED, FALSE, @@ -1371,7 +1382,8 @@ void ZapSig::EncodeField( SigBuilder *pSigBuilder, LPVOID pEncodeModuleContext, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken) + CORINFO_RESOLVED_TOKEN *pResolvedToken, + BOOL fEncodeUsingResolvedTokenSpecStreams) { CONTRACTL { @@ -1452,15 +1464,23 @@ void ZapSig::EncodeField( if (fieldFlags & ENCODE_FIELD_SIG_OwnerType) { - ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens, - (EncodeModuleCallback) pfnEncodeModule, NULL); + if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL) + { + _ASSERTE(pResolvedToken->cbTypeSpec > 0); + pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); + } + else + { + ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens, + (EncodeModuleCallback)pfnEncodeModule, NULL); - // - // Write class - // - BOOL fSuccess; - fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder); - _ASSERTE(fSuccess); + // + // Write class + // + BOOL fSuccess; + fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder); + _ASSERTE(fSuccess); + } } if ((fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) == 0) diff --git a/src/vm/zapsig.h b/src/vm/zapsig.h index ef837ad2d2..258e821aa8 100644 --- a/src/vm/zapsig.h +++ b/src/vm/zapsig.h @@ -154,28 +154,39 @@ public: // fromModule is the module in which the type is defined. // pBuffer contains the signature encoding for the type. // level is the class load level (see classloadlevel.h) to which the type should be loaded - static TypeHandle DecodeType(Module *referencingModule, - Module *fromModule, - PCCOR_SIGNATURE pBuffer, - ClassLoadLevel level = CLASS_LOADED); - - static MethodDesc *DecodeMethod(Module *referencingModule, - Module *fromModule, - PCCOR_SIGNATURE pBuffer, - TypeHandle * ppTH = NULL); - - static MethodDesc *DecodeMethod(Module *referencingModule, - Module *fromModule, - PCCOR_SIGNATURE pBuffer, - SigTypeContext *pContext, - TypeHandle * ppTH = NULL, - PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars = NULL, - PCCOR_SIGNATURE *ppMethodSpecWithVars = NULL); - - static FieldDesc *DecodeField(Module *referencingModule, - Module *fromModule, - PCCOR_SIGNATURE pBuffer, - TypeHandle * ppTH = NULL); + static TypeHandle DecodeType( + Module *referencingModule, + Module *fromModule, + PCCOR_SIGNATURE pBuffer, + ClassLoadLevel level = CLASS_LOADED); + + static MethodDesc *DecodeMethod( + Module *referencingModule, + Module *fromModule, + PCCOR_SIGNATURE pBuffer, + TypeHandle *ppTH = NULL); + + static MethodDesc *DecodeMethod( + Module *referencingModule, + Module *fromModule, + PCCOR_SIGNATURE pBuffer, + SigTypeContext *pContext, + TypeHandle *ppTH = NULL, + PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars = NULL, + PCCOR_SIGNATURE *ppMethodSpecWithVars = NULL); + + static FieldDesc *DecodeField( + Module *referencingModule, + Module *fromModule, + PCCOR_SIGNATURE pBuffer, + TypeHandle *ppTH = NULL); + + static FieldDesc *DecodeField( + Module *pReferencingModule, + Module *pInfoModule, + PCCOR_SIGNATURE pBuffer, + SigTypeContext *pContext, + TypeHandle *ppTH = NULL); static BOOL EncodeMethod( MethodDesc *pMethod, @@ -184,8 +195,8 @@ public: LPVOID pReferencingModule, ENCODEMODULE_CALLBACK pfnEncodeModule, DEFINETOKEN_CALLBACK pfnDefineToken, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, - CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL, + CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL, + CORINFO_RESOLVED_TOKEN *pConstrainedResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); static void EncodeField( @@ -194,7 +205,8 @@ public: SigBuilder *pSigBuilder, LPVOID pReferencingModule, ENCODEMODULE_CALLBACK pfnEncodeModule, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL); + CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL, + BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); }; diff --git a/src/zap/zapimport.cpp b/src/zap/zapimport.cpp index 1412adcbf3..400ea7884d 100644 --- a/src/zap/zapimport.cpp +++ b/src/zap/zapimport.cpp @@ -999,13 +999,13 @@ void ZapImportTable::EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO } void ZapImportTable::EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken) + CORINFO_RESOLVED_TOKEN * pResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams) { CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getFieldClass(handle); CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); GetCompileInfo()->EncodeField(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper, - pResolvedToken); + pResolvedToken, fEncodeUsingResolvedTokenSpecStreams); } void ZapImportTable::EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, @@ -1834,6 +1834,10 @@ ZapImport * ZapImportTable::GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND k EncodeMethod(ENCODE_VIRTUAL_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE); break; + case READYTORUN_FIXUP_FieldHandle: + EncodeField(ENCODE_FIELD_HANDLE, pResolvedToken->hField, &sigBuilder, pResolvedToken, TRUE); + break; + // TODO: support for the rest of the dictionary signature kinds default: diff --git a/src/zap/zapimport.h b/src/zap/zapimport.h index b1a5fbbe95..34a673ecf5 100644 --- a/src/zap/zapimport.h +++ b/src/zap/zapimport.h @@ -339,7 +339,7 @@ public: void EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); void EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); void EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL); + CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); void EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); diff --git a/tests/src/readytorun/fieldgetter.il b/tests/src/readytorun/fieldgetter.il new file mode 100644 index 0000000000..c2eff200af --- /dev/null +++ b/tests/src/readytorun/fieldgetter.il @@ -0,0 +1,215 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly extern test { } + +.assembly fieldgetter { } +.module fieldgetter.dll + +//========================================================================================== + +.class public auto ansi beforefieldinit Gen`1<T> + extends [mscorlib]System.Object +{ + .field public int32 m_Field1 + .field public string m_Field2 + .field public !T m_Field3 + .field public static class [mscorlib]System.Collections.Generic.List`1<!T> m_Field4 + .field public static valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!T,int32> m_Field5 + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Gen`1::.ctor +} // end of class Gen`1 + +.class interface public abstract auto ansi IFieldGetter +{ + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field1() cil managed + { + } // end of method IFieldGetter::GetGenT_Field1 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field2() cil managed + { + } // end of method IFieldGetter::GetGenT_Field2 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field3() cil managed + { + } // end of method IFieldGetter::GetGenT_Field3 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field4() cil managed + { + } // end of method IFieldGetter::GetGenT_Field4 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field5() cil managed + { + } // end of method IFieldGetter::GetGenT_Field5 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field1() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field1 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field2() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field2 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field3() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field3 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field4() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field4 + + .method public hidebysig newslot abstract virtual + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field5() cil managed + { + } // end of method IFieldGetter::GetGenDllT_Field5 + +} // end of class IFieldGetter + +.class public auto ansi beforefieldinit FieldGetter`1<T> + extends [mscorlib]System.Object + implements IFieldGetter +{ + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field1() cil managed + { + ldtoken field int32 class Gen`1<!0>::m_Field1 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field1 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field2() cil managed + { + ldtoken field string class Gen`1<!0>::m_Field2 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field2 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field3() cil managed + { + ldtoken field !0 class Gen`1<!0>::m_Field3 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field3 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field4() cil managed + { + ldtoken field class [mscorlib]System.Collections.Generic.List`1<!0> class Gen`1<!0>::m_Field4 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field4 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenT_Field5() cil managed + { + ldtoken field valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,int32> class Gen`1<!0>::m_Field5 + ldtoken class Gen`1<!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenT_Field5 + + + + + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field1() cil managed + { + ldtoken field string class [test]MyGeneric`2<!0,!0>::m_Field1 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field1 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field2() cil managed + { + ldtoken field !0 class [test]MyGeneric`2<!0,!0>::m_Field2 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field2 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field3() cil managed + { + ldtoken field class [mscorlib]System.Collections.Generic.List`1<!0> class [test]MyGeneric`2<!0,!0>::m_Field3 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field3 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field4() cil managed + { + ldtoken field valuetype [mscorlib]System.Collections.Generic.KeyValuePair`2<!0,int32> class [test]MyGeneric`2<!0,!0>::m_Field4 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field4 + + .method public hidebysig newslot virtual final + instance class [mscorlib]System.Reflection.FieldInfo + GetGenDllT_Field5() cil managed + { + ldtoken field int32 class [test]MyGeneric`2<!0,!0>::m_Field5 + ldtoken class [test]MyGeneric`2<!0,!0> + call class [mscorlib]System.Reflection.FieldInfo [mscorlib]System.Reflection.FieldInfo::GetFieldFromHandle(valuetype [mscorlib]System.RuntimeFieldHandle, valuetype [mscorlib]System.RuntimeTypeHandle) + ret + } // end of method FieldGetter`1::GetGenDllT_Field5 + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method FieldGetter`1::.ctor + +} // end of class FieldGetter`1 + diff --git a/tests/src/readytorun/fieldgetter.ilproj b/tests/src/readytorun/fieldgetter.ilproj new file mode 100644 index 0000000000..0f6f6875fb --- /dev/null +++ b/tests/src/readytorun/fieldgetter.ilproj @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>fieldgetter</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Library</OutputType> + <CLRTestKind>SharedLibrary</CLRTestKind> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="fieldgetter.il" /> + </ItemGroup> + + <ItemGroup> + <None Include="app.config" /> + </ItemGroup> + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/readytorun/main.cs b/tests/src/readytorun/main.cs index b01702f7da..cce03b4586 100644 --- a/tests/src/readytorun/main.cs +++ b/tests/src/readytorun/main.cs @@ -379,6 +379,44 @@ class Program Func<string, object> idClosed = "World".OpenClosedDelegateTarget; Assert.AreEqual(idClosed("hey"), "World, hey"); } + + static void GenericLdtokenFieldsTest() + { + Func<FieldInfo, string> FieldFullName = (fi) => fi.FieldType + " " + fi.DeclaringType.ToString() + "::" + fi.Name; + + IFieldGetter getter1 = new FieldGetter<string>(); + IFieldGetter getter2 = new FieldGetter<object>(); + IFieldGetter getter3 = new FieldGetter<int>(); + + foreach (var instArg in new Type[]{typeof(String), typeof(object), typeof(int)}) + { + IFieldGetter getter = (IFieldGetter)Activator.CreateInstance(typeof(FieldGetter<>).MakeGenericType(instArg)); + + string expectedField1 = "System.Int32 Gen`1[???]::m_Field1".Replace("???", instArg.ToString()); + string expectedField2 = "System.String Gen`1[???]::m_Field2".Replace("???", instArg.ToString()); + string expectedField3 = "??? Gen`1[???]::m_Field3".Replace("???", instArg.ToString()); + string expectedField4 = "System.Collections.Generic.List`1[???] Gen`1[???]::m_Field4".Replace("???", instArg.ToString()); + string expectedField5 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] Gen`1[???]::m_Field5".Replace("???", instArg.ToString()); + + string expectedDllField1 = "System.String MyGeneric`2[???,???]::m_Field1".Replace("???", instArg.ToString()); + string expectedDllField2 = "??? MyGeneric`2[???,???]::m_Field2".Replace("???", instArg.ToString()); + string expectedDllField3 = "System.Collections.Generic.List`1[???] MyGeneric`2[???,???]::m_Field3".Replace("???", instArg.ToString()); + string expectedDllField4 = "System.Collections.Generic.KeyValuePair`2[???,System.Int32] MyGeneric`2[???,???]::m_Field4".Replace("???", instArg.ToString()); + string expectedDllField5 = "System.Int32 MyGeneric`2[???,???]::m_Field5".Replace("???", instArg.ToString()); + + Assert.AreEqual(expectedField1, FieldFullName(getter.GetGenT_Field1())); + Assert.AreEqual(expectedField2, FieldFullName(getter.GetGenT_Field2())); + Assert.AreEqual(expectedField3, FieldFullName(getter.GetGenT_Field3())); + Assert.AreEqual(expectedField4, FieldFullName(getter.GetGenT_Field4())); + Assert.AreEqual(expectedField5, FieldFullName(getter.GetGenT_Field5())); + + Assert.AreEqual(expectedDllField1, FieldFullName(getter.GetGenDllT_Field1())); + Assert.AreEqual(expectedDllField2, FieldFullName(getter.GetGenDllT_Field2())); + Assert.AreEqual(expectedDllField3, FieldFullName(getter.GetGenDllT_Field3())); + Assert.AreEqual(expectedDllField4, FieldFullName(getter.GetGenDllT_Field4())); + Assert.AreEqual(expectedDllField5, FieldFullName(getter.GetGenDllT_Field5())); + } + } static void RunAllTests() { @@ -430,6 +468,8 @@ class Program TestRangeCheckElimination(); TestOpenClosedDelegate(); + + GenericLdtokenFieldsTest(); } static int Main() diff --git a/tests/src/readytorun/mainv1.csproj b/tests/src/readytorun/mainv1.csproj index 8da9bc2276..855c3578a6 100644 --- a/tests/src/readytorun/mainv1.csproj +++ b/tests/src/readytorun/mainv1.csproj @@ -27,6 +27,7 @@ </CodeAnalysisDependentAssemblyPaths> </ItemGroup> <ItemGroup> + <ProjectReference Include="fieldgetter.ilproj" /> <ProjectReference Include="testv1\test.csproj"> <Project>{F74F55A1-DFCF-4C7C-B462-E96E1D0BB667}</Project> </ProjectReference> @@ -47,6 +48,7 @@ $(CLRTestBatchPreCommands) DEL test.dll COPY /Y ..\testv1\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out test.ni.dll test.dll +%Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out fieldgetter.ni.dll fieldgetter.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out mainv1.ni.exe mainv1.exe ]]></CLRTestBatchPreCommands> <BashCLRTestPreCommands><![CDATA[ @@ -54,6 +56,7 @@ $(BashCLRTestPreCommands) rm -f test.dll cp ../testv1/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out test.ni.dll test.dll +$CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out fieldgetter.ni.dll fieldgetter.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out mainv1.ni.exe mainv1.exe ]]></BashCLRTestPreCommands> </PropertyGroup> diff --git a/tests/src/readytorun/mainv2.csproj b/tests/src/readytorun/mainv2.csproj index 19f16b308f..52a3720483 100644 --- a/tests/src/readytorun/mainv2.csproj +++ b/tests/src/readytorun/mainv2.csproj @@ -27,6 +27,7 @@ </CodeAnalysisDependentAssemblyPaths> </ItemGroup> <ItemGroup> + <ProjectReference Include="fieldgetter.ilproj" /> <ProjectReference Include="testv1\test.csproj" /> </ItemGroup> <ItemGroup> @@ -45,6 +46,7 @@ $(CLRTestBatchPreCommands) DEL test.dll COPY /Y ..\testv1\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out mainv2.ni.exe mainv2.exe +%Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out fieldgetter.ni.dll fieldgetter.dll DEL test.dll COPY /Y ..\testv2\test\test.dll test.dll %Core_Root%\crossgen /readytorun /platform_assemblies_paths %Core_Root%%3B%25CD% /out test.ni.dll test.dll @@ -54,6 +56,7 @@ $(BashCLRTestPreCommands) rm -f test.dll cp ../testv1/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out mainv2.ni.exe mainv2.exe +$CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out fieldgetter.ni.dll fieldgetter.dll rm -f test.dll cp ../testv2/test/test.dll test.dll $CORE_ROOT/crossgen -readytorun -platform_assemblies_paths $CORE_ROOT:`pwd` -out test.ni.dll test.dll diff --git a/tests/src/readytorun/test.cs b/tests/src/readytorun/test.cs index 39afbd218e..40199b41e8 100644 --- a/tests/src/readytorun/test.cs +++ b/tests/src/readytorun/test.cs @@ -225,6 +225,32 @@ public struct MyStruct : IDisposable public class MyGeneric<T,U> { +#if V2 + public object m_unused1; + public string m_Field1; + + public object m_unused2; + public T m_Field2; + + public object m_unused3; + public List<T> m_Field3; + + static public object m_unused4; + static public KeyValuePair<T, int> m_Field4; + + static public object m_unused5; + static public int m_Field5; + + public object m_unused6; + static public object m_unused7; +#else + public string m_Field1; + public T m_Field2; + public List<T> m_Field3; + static public KeyValuePair<T, int> m_Field4; + static public int m_Field5; +#endif + [ThreadStatic] public static Object ThreadStatic; public MyGeneric() |