summaryrefslogtreecommitdiff
path: root/src/vm/amd64
diff options
context:
space:
mode:
authorFadi Hanna <fadim@microsoft.com>2016-05-13 20:35:54 -0700
committerFadi Hanna <fadim@microsoft.com>2016-05-13 20:35:54 -0700
commit97b4ff0b438261ba11b357008630076054a6f25d (patch)
tree320c32b25b556124cb354ab06a86c8f6ae806d98 /src/vm/amd64
parent5b065284dc57bc3a9eaee9f86b0df258b1d3d7af (diff)
downloadcoreclr-97b4ff0b438261ba11b357008630076054a6f25d.tar.gz
coreclr-97b4ff0b438261ba11b357008630076054a6f25d.tar.bz2
coreclr-97b4ff0b438261ba11b357008630076054a6f25d.zip
Initial implementation of generic dictionary access for R2R. (#4519)
For now, only TypeHandle dictionary entry slots are supported and encoded in a R2R version resilient format (the rest to come soon). Support is only limited for x64 Windows platforms (rest is still TODO) The basic idea: each dictionary access is initally a call to a DynamicHelper R2R cell that computes the dictionary signature, and patches the R2R cell address with an assembly stub that performs the dictionary lookup.
Diffstat (limited to 'src/vm/amd64')
-rw-r--r--src/vm/amd64/cgenamd64.cpp109
1 files changed, 107 insertions, 2 deletions
diff --git a/src/vm/amd64/cgenamd64.cpp b/src/vm/amd64/cgenamd64.cpp
index a83c166474..e972ae8953 100644
--- a/src/vm/amd64/cgenamd64.cpp
+++ b/src/vm/amd64/cgenamd64.cpp
@@ -953,9 +953,16 @@ PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCOD
END_DYNAMIC_HELPER_EMIT();
}
-PCODE DynamicHelpers::CreateHelperWithArg(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
+void DynamicHelpers::EmitHelperWithArg(BYTE*& p, LoaderAllocator * pAllocator, TADDR arg, PCODE target)
{
- BEGIN_DYNAMIC_HELPER_EMIT(15);
+ CONTRACTL
+ {
+ GC_NOTRIGGER;
+ PRECONDITION(p != NULL && target != NULL);
+ }
+ CONTRACTL_END;
+
+ // Move an an argument into the second argument register and jump to a target function.
#ifdef UNIX_AMD64_ABI
*(UINT16 *)p = 0xBE48; // mov rsi, XXXXXX
@@ -969,6 +976,13 @@ PCODE DynamicHelpers::CreateHelperWithArg(LoaderAllocator * pAllocator, TADDR ar
*p++ = X86_INSTR_JMP_REL32; // jmp rel32
*(INT32 *)p = rel32UsingJumpStub((INT32 *)p, target, NULL, pAllocator);
p += 4;
+}
+
+PCODE DynamicHelpers::CreateHelperWithArg(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
+{
+ BEGIN_DYNAMIC_HELPER_EMIT(15);
+
+ EmitHelperWithArg(p, pAllocator, arg, target);
END_DYNAMIC_HELPER_EMIT();
}
@@ -1126,6 +1140,97 @@ PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADD
END_DYNAMIC_HELPER_EMIT();
}
+PCODE DynamicHelpers::CreateDictionaryLookupHelper(LoaderAllocator * pAllocator, CORINFO_RUNTIME_LOOKUP * pLookup)
+{
+ STANDARD_VM_CONTRACT;
+
+ // TODO: fix codegen for correct Unix ABI...
+
+ // It's available only via the run-time helper function
+ if (pLookup->indirections == CORINFO_USEHELPER)
+ {
+ BEGIN_DYNAMIC_HELPER_EMIT(15);
+
+ // rcx contains the generic context parameter
+ // mov rdx,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 ? 7 : 4);
+
+ int codeSize = indirectionsSize + (pLookup->testForNull ? 30 : 4);
+
+ BEGIN_DYNAMIC_HELPER_EMIT(codeSize);
+
+ if (pLookup->testForNull)
+ {
+ // rcx contains the generic context parameter. Save a copy of it in the rax register
+ // mov rax,rcx
+ *(UINT32*)p = 0x00c88948; p += 3;
+ }
+
+ for (WORD i = 0; i < pLookup->indirections; i++)
+ {
+ // mov rcx,qword ptr [rcx+offset]
+ if (pLookup->offsets[i] >= 0x80)
+ {
+ *(UINT32*)p = 0x00898b48; p += 3;
+ *p = (UINT32)pLookup->offsets[i]; p += 4;
+ }
+ else
+ {
+ *(UINT32*)p = 0x00498b48; p += 3;
+ *p++ = (BYTE)pLookup->offsets[i];
+ }
+ }
+
+ // No null test required
+ if (!pLookup->testForNull)
+ {
+ // No fixups needed for R2R
+
+ // mov rax,rcx
+ *(UINT32*)p = 0x00c88948; p += 3;
+ *p++ = 0xC3; // ret
+ }
+ else
+ {
+ // rcx contains the value of the dictionary slot entry
+
+ _ASSERTE(pLookup->indirections != 0);
+
+ // test rcx,rcx
+ *(UINT32*)p = 0x00c98548; p += 3;
+
+ // je 'HELPER_CALL' (a jump of 4 bytes)
+ *(UINT16*)p = 0x0474; p += 2;
+
+ // mov rax,rcx
+ *(UINT32*)p = 0x00c88948; p += 3;
+ *p++ = 0xC3; // ret
+
+ // 'HELPER_CALL'
+ {
+ // Put the generic context back into rcx (was previously saved in rax)
+ // mov rcx,rax
+ *(UINT32*)p = 0x00c18948; p += 3;
+
+ // mov rdx,pLookup->signature
+ // jmp pLookup->helper
+ EmitHelperWithArg(p, pAllocator, (TADDR)pLookup->signature, CEEJitInfo::getHelperFtnStatic(pLookup->helper));
+ }
+ }
+
+ END_DYNAMIC_HELPER_EMIT();
+ }
+}
+
#endif // FEATURE_READYTORUN
#endif // DACCESS_COMPILE