All of the changes in importer.cpp were ported from JIT\importer.cpp, which was merged to the coreclr master branch last Friday evening (reviewed and signed-off in a PR on GitHub).
The remaining changes include:
1) Adjusting #ifdefs to enable the x86 scenario
2) Implementation of the R2R stub for generic dictionary lookups
3) Small change in prestub.cpp required for x86 to work correctly
[tfs-changeset: 1605906]
{
STANDARD_VM_CONTRACT;
- // TODO (NYI)
- ThrowHR(E_NOTIMPL);
+ // It's available only via the run-time helper function
+ if (pLookup->indirections == CORINFO_USEHELPER)
+ {
+ BEGIN_DYNAMIC_HELPER_EMIT(10);
+
+ // ecx contains the generic context parameter
+ // mov edx,pLookup->signature
+ // jmp pLookup->helper
+ EmitHelperWithArg(p, pAllocator, (TADDR)pLookup->signature, CEEJitInfo::getHelperFtnStatic(pLookup->helper));
+
+ END_DYNAMIC_HELPER_EMIT();
+ }
+ else
+ {
+ int indirectionsSize = 0;
+ for (WORD i = 0; i < pLookup->indirections; i++)
+ indirectionsSize += (pLookup->offsets[i] >= 0x80 ? 6 : 3);
+
+ int codeSize = indirectionsSize + (pLookup->testForNull ? 21 : 3);
+
+ BEGIN_DYNAMIC_HELPER_EMIT(codeSize);
+
+ if (pLookup->testForNull)
+ {
+ // ecx contains the generic context parameter. Save a copy of it in the eax register
+ // mov eax,ecx
+ *(UINT16*)p = 0xc889; p += 2;
+ }
+
+ for (WORD i = 0; i < pLookup->indirections; i++)
+ {
+ // mov ecx,qword ptr [ecx+offset]
+ if (pLookup->offsets[i] >= 0x80)
+ {
+ *(UINT16*)p = 0x898b; p += 2;
+ *(UINT32*)p = (UINT32)pLookup->offsets[i]; p += 4;
+ }
+ else
+ {
+ *(UINT16*)p = 0x498b; p += 2;
+ *p++ = (BYTE)pLookup->offsets[i];
+ }
+ }
+
+ // No null test required
+ if (!pLookup->testForNull)
+ {
+ // No fixups needed for R2R
+
+ // mov eax,ecx
+ *(UINT16*)p = 0xc889; p += 2;
+ *p++ = 0xC3; // ret
+ }
+ else
+ {
+ // ecx contains the value of the dictionary slot entry
+
+ _ASSERTE(pLookup->indirections != 0);
+
+ // test ecx,ecx
+ *(UINT16*)p = 0xc985; p += 2;
+
+ // je 'HELPER_CALL' (a jump of 3 bytes)
+ *(UINT16*)p = 0x0374; p += 2;
+
+ // mov eax,ecx
+ *(UINT16*)p = 0xc889; p += 2;
+ *p++ = 0xC3; // ret
+
+ // 'HELPER_CALL'
+ {
+ // Put the generic context back into rcx (was previously saved in eax)
+ // mov ecx,eax
+ *(UINT16*)p = 0xc189; p += 2;
+
+ // mov edx,pLookup->signature
+ // jmp pLookup->helper
+ EmitHelperWithArg(p, pAllocator, (TADDR)pLookup->signature, CEEJitInfo::getHelperFtnStatic(pLookup->helper));
+ }
+ }
+
+ END_DYNAMIC_HELPER_EMIT();
+ }
}
#endif // FEATURE_READYTORUN
}
void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entryKind,
- CORINFO_RESOLVED_TOKEN * pResolvedToken,
- CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken /* for ConstrainedMethodEntrySlot */,
- MethodDesc * pTemplateMD /* for method-based slots */,
- CORINFO_LOOKUP *pResultLookup)
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
+ MethodDesc * pTemplateMD /* for method-based slots */,
+ CORINFO_LOOKUP *pResultLookup)
{
CONTRACTL{
STANDARD_VM_CHECK;
#ifdef FEATURE_READYTORUN_COMPILER
if (IsReadyToRunCompilation())
{
-#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) || defined(_TARGET_X86_)
+#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
// TODO
ThrowHR(E_NOTIMPL);
#endif
return pHelper;
}
+TADDR GetFirstArgumentRegisterValuePtr(TransitionBlock * pTransitionBlock)
+{
+ TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
+#ifdef _TARGET_X86_
+ // x86 is special as always
+ pArgument += offsetof(ArgumentRegisters, ECX);
+#endif
+
+ return pArgument;
+}
+
PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWORD sectionIndex, Module * pModule, CORCOMPILE_FIXUP_BLOB_KIND * pKind, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD)
{
STANDARD_VM_CONTRACT;
case ENCODE_DICTIONARY_LOOKUP_TYPE:
case ENCODE_DICTIONARY_LOOKUP_METHOD:
{
- // Generic context is the first argument on the pTransitionBlock (either a methodtable or a methoddesc pointer)
- TADDR genericContextPtr = *(TADDR*)(((TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters()));
+ TADDR genericContextPtr = *(TADDR*)GetFirstArgumentRegisterValuePtr(pTransitionBlock);
DWORD numGenericArgs = 0;
MethodTable* pContextMT = NULL;
{
GCX_COOP();
- TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
-#ifdef _TARGET_X86_
- // x86 is special as always
- pArgument += offsetof(ArgumentRegisters, ECX);
-#endif
+ TADDR pArgument = GetFirstArgumentRegisterValuePtr(pTransitionBlock);
if (pArgument != NULL)
{
if (pHelper == NULL)
{
- TADDR pArgument = (TADDR)pTransitionBlock + TransitionBlock::GetOffsetOfArgumentRegisters();
-#ifdef _TARGET_X86_
- // x86 is special as always
- pArgument += offsetof(ArgumentRegisters, ECX);
-#endif
+ TADDR pArgument = GetFirstArgumentRegisterValuePtr(pTransitionBlock);
switch (kind)
{