summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/inc/corcompile.h3
-rw-r--r--src/inc/readytorun.h4
-rw-r--r--src/vm/codeman.cpp14
-rw-r--r--src/vm/compile.cpp6
-rw-r--r--src/vm/compile.h7
-rw-r--r--src/vm/genericdict.cpp52
-rw-r--r--src/vm/jitinterface.cpp7
-rw-r--r--src/vm/zapsig.cpp48
-rw-r--r--src/vm/zapsig.h62
-rw-r--r--src/zap/zapimport.cpp8
-rw-r--r--src/zap/zapimport.h2
-rw-r--r--tests/src/readytorun/fieldgetter.il215
-rw-r--r--tests/src/readytorun/fieldgetter.ilproj36
-rw-r--r--tests/src/readytorun/main.cs40
-rw-r--r--tests/src/readytorun/mainv1.csproj3
-rw-r--r--tests/src/readytorun/mainv2.csproj3
-rw-r--r--tests/src/readytorun/test.cs26
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()