Porting the changes to support generic dictionaries lookups in R2R images to the...
authorFadi Hanna <fadim@microsoft.com>
Wed, 18 May 2016 17:18:53 +0000 (10:18 -0700)
committerFadi Hanna <fadim@microsoft.com>
Wed, 18 May 2016 17:18:53 +0000 (10:18 -0700)
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]

src/vm/i386/cgenx86.cpp
src/vm/jitinterface.cpp
src/vm/prestub.cpp

index 343b6ed..a9c2967 100644 (file)
@@ -2157,8 +2157,89 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator,
 {
     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
index 33c76d1..df141f4 100644 (file)
@@ -3056,10 +3056,10 @@ static BOOL IsTypeSpecForTypicalInstantiation(SigPointer sigptr)
 }
 
 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;
@@ -3075,7 +3075,7 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr
 #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
index 1ae7b39..6ce4973 100644 (file)
@@ -2281,6 +2281,17 @@ static PCODE getHelperForStaticBase(Module * pModule, CORCOMPILE_FIXUP_BLOB_KIND
     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;
@@ -2370,8 +2381,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR
     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;
@@ -2609,11 +2619,7 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR
                 {
                     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)
                     {
@@ -2742,11 +2748,7 @@ extern "C" SIZE_T STDCALL DynamicHelperWorker(TransitionBlock * pTransitionBlock
 
     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)
         {