[RyuJIT/ARM32] Add the optimization case on CreateDictionaryLookupHelper (#13933)
authorSujin Kim <sjsujin.kim@samsung.com>
Tue, 17 Oct 2017 13:33:51 +0000 (22:33 +0900)
committerJan Kotas <jkotas@microsoft.com>
Tue, 17 Oct 2017 13:33:51 +0000 (06:33 -0700)
* Implement optimization case for CreateDictionaryLookupHelper

Signed-off-by: Hyung-Kyu Choi <hk0110.choi@samsung.com>
* Reenable mainv1/mainv2 tests

src/vm/arm/stubs.cpp
src/vm/prestub.cpp
tests/arm/Tests.lst

index e057476..f2500c3 100644 (file)
@@ -3600,16 +3600,121 @@ PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator,
     pArgs->module = (CORINFO_MODULE_HANDLE)pModule;
 
     // It's available only via the run-time helper function,
-    // since optimization cases are not yet implemented.
-    assert(pLookup->indirections == CORINFO_USEHELPER);
 
-    BEGIN_DYNAMIC_HELPER_EMIT(18);
+    if (pLookup->indirections == CORINFO_USEHELPER)
+    {
+        BEGIN_DYNAMIC_HELPER_EMIT(18);
 
-    EmitHelperWithArg(p, pAllocator, (TADDR)pArgs, helperAddress);
+        EmitHelperWithArg(p, pAllocator, (TADDR)pArgs, helperAddress);
 
-    END_DYNAMIC_HELPER_EMIT();
+        END_DYNAMIC_HELPER_EMIT();
+    }
+    else
+    {
+        int indirectionsSize = 0;
+        for (WORD i = 0; i < pLookup->indirections; i++)
+        {
+            if ((i == 0 && pLookup->indirectFirstOffset) || (i == 1 && pLookup->indirectSecondOffset))
+            {
+                indirectionsSize += (pLookup->offsets[i] >= 0xFFF ? 10 : 2);
+                indirectionsSize += 4;
+            }
+            else
+            {
+                indirectionsSize += (pLookup->offsets[i] >= 0xFFF ? 10 : 4);
+            }
+        }
+
+        int codeSize = indirectionsSize + (pLookup->testForNull ? 26 : 2);
+
+        BEGIN_DYNAMIC_HELPER_EMIT(codeSize);
+
+        if (pLookup->testForNull)
+        {
+            // mov r3, r0
+            *(WORD *)p = 0x4603;
+            p += 2;
+        }
 
-    // @TODO : Additional implementation is required for optimization cases.
+        for (WORD i = 0; i < pLookup->indirections; i++)
+        {
+            if ((i == 0 && pLookup->indirectFirstOffset) || (i == 1 && pLookup->indirectSecondOffset))
+            {
+                if (pLookup->offsets[i] >= 0xFF)
+                {
+                    // mov r2, offset
+                    MovRegImm(p, 2, pLookup->offsets[i]);
+                    p += 8;
+
+                    // add r0, r2
+                    *(WORD *)p = 0x4410;
+                    p += 2;
+                }
+                else
+                {
+                    // add r0, <offset>
+                   *(WORD *)p = (WORD)((WORD)0x3000 | (WORD)((0x00FF) & pLookup->offsets[i]));
+                   p += 2;
+                }
+
+                // r0 is pointer + offset[0]
+                // ldr r2, [r0]
+                *(WORD *)p = 0x6802;
+                p += 2;
+
+                // r2 is offset1
+                // add r0, r2
+                *(WORD *)p = 0x4410;
+                p += 2;
+            }
+            else
+            {
+                if (pLookup->offsets[i] >= 0xFFF)
+                {
+                    // mov r2, offset
+                    MovRegImm(p, 2, pLookup->offsets[i]);
+                    p += 8;
+
+                    // ldr r0, [r0, r2]
+                    *(WORD *)p = 0x5880;
+                    p += 2;
+                }
+                else
+                {
+                    // ldr r0, [r0 + offset]
+                    *(WORD *)p = 0xF8D0;
+                    p += 2;
+                    *(WORD *)p = (WORD)(0xFFF & pLookup->offsets[i]);
+                    p += 2;
+                }
+            }
+        }
+
+        // No null test required
+        if (!pLookup->testForNull)
+        {
+            // mov pc, lr
+            *(WORD *)p = 0x46F7;
+            p += 2;
+        }
+        else
+        {
+            // cbz r0, nullvaluelabel
+            *(WORD *)p = 0xB100;
+            p += 2;
+            // mov pc, lr
+            *(WORD *)p = 0x46F7;
+            p += 2;
+            // nullvaluelabel:
+            // mov r0, r3
+            *(WORD *)p = 0x4618;
+            p += 2;
+
+            EmitHelperWithArg(p, pAllocator, (TADDR)pArgs, helperAddress);
+        }
+
+        END_DYNAMIC_HELPER_EMIT();
+    }
 }
 #endif // FEATURE_READYTORUN
 
index d2f24bd..813af75 100644 (file)
@@ -2586,9 +2586,6 @@ void ProcessDynamicDictionaryLookup(TransitionBlock *           pTransitionBlock
     //
     // Optimization cases
     //
-    // TODO-ARM : If the optimization cases are implemented in CreateDictionaryLookupHelper,
-    //            It's ifndef for ARM will be removed.
-#ifndef _TARGET_ARM_
     if (signatureKind == ENCODE_TYPE_HANDLE)
     {
         SigPointer sigptr(pBlob, -1);
@@ -2631,7 +2628,6 @@ void ProcessDynamicDictionaryLookup(TransitionBlock *           pTransitionBlock
             return;
         }
     }
-#endif // !_TARGET_ARM_
 
     if (pContextMT != NULL && pContextMT->GetNumDicts() > 0xFFFF)
         ThrowHR(COR_E_BADIMAGEFORMAT);
index a94ba02..b423d3d 100644 (file)
@@ -625,7 +625,7 @@ RelativePath=readytorun\tests\mainv1\mainv1.cmd
 WorkingDir=readytorun\tests\mainv1
 Expected=0
 MaxAllowedDurationSeconds=600
-Categories=EXPECTED_FAIL;13952
+Categories=EXPECTED_PASS
 HostStyle=0
 
 [ComparerCompare2.cmd_80]
@@ -85153,7 +85153,7 @@ RelativePath=readytorun\tests\mainv2\mainv2.cmd
 WorkingDir=readytorun\tests\mainv2
 Expected=0
 MaxAllowedDurationSeconds=600
-Categories=EXPECTED_FAIL;13952
+Categories=EXPECTED_PASS
 HostStyle=0
 
 [Generated1463.cmd_10690]