Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordotnet bot <dotnet-bot@microsoft.com>2016-04-14 23:59:59 +0300
committerMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2016-04-14 23:59:59 +0300
commit9ed921ffded2f76e55e9a24fd8b8c9d3d2570c43 (patch)
tree62a773a7c336793f6b17f4be98c1ebbbd99d82f5 /src/Native/Runtime/MiscHelpers.cpp
parent9804f42dce998498b693915ff1b2051478dadc97 (diff)
Improve Reverse PInvoke performance in ProjectN (#1138)
Recently while experimenting with interop performance micro-benchmarks, I observed that Reverse PInvoke code path in ProjectN is 8-10x slower than Desktop CLR. Morgan also noticed the slow down and extra memory allocation on this code path while doing the Unity app investigation. This change aims to improve this code path to achieve parity with Desktop CLR. This change improve Reverse PInvoke performance by: 1. Remove the dictionary in McgModuleManager which maps between thunk address and delegate. Instead store a weak GCHandle of the delegate in the thunk data section. 2. Optimize open static delegate by storing the static function pointer directly in the thunk data. And later on reverse pinvoke code path directly do a CallI on the function pointer. Modified MCG to generate special function to handle open static delegates. 3. While storing the function pointer, store jump stub code target address. Added a runtime helper to get the jump stub target. 4. Reorder some instructions in RhpReversePInvoke and InteropNative_CommonStub functions so that the hot path get better instruction cache use. Results: X86 33% slower than Desktop CLR (75 vs 92 instruction) 5.5x faster than latest ProjectN AMD64 9% faster than Desktop CLR (54 vs 67 instructions) 7.5x faster than latest ProjectN [tfs-changeset: 1596255]
Diffstat (limited to 'src/Native/Runtime/MiscHelpers.cpp')
-rw-r--r--src/Native/Runtime/MiscHelpers.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/Native/Runtime/MiscHelpers.cpp b/src/Native/Runtime/MiscHelpers.cpp
index 4d08e4e06..ff7346177 100644
--- a/src/Native/Runtime/MiscHelpers.cpp
+++ b/src/Native/Runtime/MiscHelpers.cpp
@@ -483,6 +483,65 @@ COOP_PINVOKE_HELPER(UInt8 *, RhGetCodeTarget, (UInt8 * pCodeOrg))
return pCodeOrg;
}
+// Given a pointer to code, find out if this points to a jump stub, and if so, return the address that stub jumps to
+COOP_PINVOKE_HELPER(UInt8 *, RhGetJmpStubCodeTarget, (UInt8 * pCodeOrg))
+{
+ // Search for the module containing the code
+ FOREACH_MODULE(pModule)
+ {
+ // If the code pointer doesn't point to a module's stub range,
+ // it can't be pointing to a stub
+ if (!pModule->ContainsStubAddress(pCodeOrg))
+ continue;
+
+#ifdef _TARGET_AMD64_
+ UInt8 * pCode = pCodeOrg;
+
+ // if this is a jmp stub
+ if (pCode[0] == 0xe9)
+ {
+ // relative jump - dist is relative to the point *after* the instruction
+ Int32 distToTarget = *(Int32 *)&pCode[1];
+ UInt8 * target = pCode + 5 + distToTarget;
+ return target;
+ }
+ return pCodeOrg;
+
+#elif _TARGET_X86_
+ UInt8 * pCode = pCodeOrg;
+
+ // if this is a jmp stub
+ if (pCode[0] == 0xe9)
+ {
+ // relative jump - dist is relative to the point *after* the instruction
+ Int32 distToTarget = *(Int32 *)&pCode[1];
+ UInt8 * pTarget = pCode + 5 + distToTarget;
+ return pTarget;
+ }
+ return pCodeOrg;
+
+#elif _TARGET_ARM_
+ const UInt16 THUMB_BIT = 1;
+ UInt16 * pCode = (UInt16 *)((size_t)pCodeOrg & ~THUMB_BIT);
+ // if this is a jmp stub
+ if ((pCode[0] & 0xf800) == 0xf000 && (pCode[1] & 0xd000) == 0x9000)
+ {
+ Int32 distToTarget = GetThumb2BlRel24(pCode);
+ UInt8 * pTarget = (UInt8 *)(pCode + 2) + distToTarget + THUMB_BIT;
+ return (UInt8 *)pTarget;
+ }
+#elif _TARGET_ARM64_
+ PORTABILITY_ASSERT("@TODO: FIXME:ARM64");
+#else
+#error 'Unsupported Architecture'
+#endif
+ }
+ END_FOREACH_MODULE;
+
+ return pCodeOrg;
+}
+
+
//
// Return true if the array slice is valid
//