diff options
author | Sergiy Kuryata <sergeyk@microsoft.com> | 2015-10-14 09:36:12 -0700 |
---|---|---|
committer | Sergiy Kuryata <sergeyk@microsoft.com> | 2015-10-14 09:36:12 -0700 |
commit | ba3a1552fdacac4047681e45256edef2599c8b0b (patch) | |
tree | 89c5f65f84fe7c768548e05d8a39ee75ede12702 /src | |
parent | d1c27d62267d08a0c1c9be454e896984aa6b55fa (diff) | |
parent | d7772f3feb5fd09ea841add320f6e2f25642686d (diff) | |
download | coreclr-ba3a1552fdacac4047681e45256edef2599c8b0b.tar.gz coreclr-ba3a1552fdacac4047681e45256edef2599c8b0b.tar.bz2 coreclr-ba3a1552fdacac4047681e45256edef2599c8b0b.zip |
Merge pull request #1763 from kouvel/PerfFix
Add string allocation fast path outside Windows
Diffstat (limited to 'src')
-rw-r--r-- | src/vm/jithelpers.cpp | 68 | ||||
-rw-r--r-- | src/vm/jitinterface.h | 6 | ||||
-rw-r--r-- | src/vm/jitinterfacegen.cpp | 2 |
3 files changed, 74 insertions, 2 deletions
diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 12d4458ccc..a1ba4beee5 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -2988,6 +2988,74 @@ HCIMPLEND // //======================================================================== +#include <optsmallperfcritical.h> + +//************************************************************* +// Allocation fast path for typical objects +// +HCIMPL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength) +{ + FCALL_CONTRACT; + + do + { + _ASSERTE(GCHeap::UseAllocationContexts()); + + // Instead of doing elaborate overflow checks, we just limit the number of elements. This will avoid all overflow + // problems, as well as making sure big string objects are correctly allocated in the big object heap. + if (stringLength >= (LARGE_OBJECT_SIZE - 256) / sizeof(WCHAR)) + { + break; + } + + // This is typically the only call in the fast path. Making the call early seems to be better, as it allows the compiler + // to use volatile registers for intermediate values. This reduces the number of push/pop instructions and eliminates + // some reshuffling of intermediate values into nonvolatile registers around the call. + Thread *thread = GetThread(); + + SIZE_T totalSize = StringObject::GetSize(stringLength); + + // The method table's base size includes space for a terminating null character + _ASSERTE(totalSize >= g_pStringClass->GetBaseSize()); + _ASSERTE((totalSize - g_pStringClass->GetBaseSize()) / sizeof(WCHAR) == stringLength); + + SIZE_T alignedTotalSize = ALIGN_UP(totalSize, DATA_ALIGNMENT); + _ASSERTE(alignedTotalSize >= totalSize); + totalSize = alignedTotalSize; + + alloc_context *allocContext = thread->GetAllocContext(); + BYTE *allocPtr = allocContext->alloc_ptr; + _ASSERTE(allocPtr <= allocContext->alloc_limit); + if (totalSize > static_cast<SIZE_T>(allocContext->alloc_limit - allocPtr)) + { + break; + } + allocContext->alloc_ptr = allocPtr + totalSize; + + _ASSERTE(allocPtr != nullptr); + StringObject *stringObject = reinterpret_cast<StringObject *>(allocPtr); + stringObject->SetMethodTable(g_pStringClass); + stringObject->SetStringLength(stringLength); + _ASSERTE(stringObject->GetBuffer()[stringLength] == W('\0')); + +#if CHECK_APP_DOMAIN_LEAKS + if (g_pConfig->AppDomainLeaks()) + { + stringObject->SetAppDomain(); + } +#endif // CHECK_APP_DOMAIN_LEAKS + + return stringObject; + } while (false); + + // Tail call to the slow helper + ENDFORBIDGC(); + return HCCALL1(FramedAllocateString, stringLength); +} +HCIMPLEND + +#include <optdefault.h> + /*********************************************************************/ /* We don't use HCIMPL macros because this is not a real helper call */ /* This function just needs mangled arguments like a helper call */ diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 035d164254..ad34fa9a8c 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -203,6 +203,10 @@ extern FCDECL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL1(Object*, JIT_NewCrossContext, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL1(Object*, JIT_NewCrossContext_Portable, CORINFO_CLASS_HANDLE typeHnd_); +extern FCDECL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength); +extern FCDECL1(StringObject*, UnframedAllocateString, DWORD stringLength); +extern FCDECL1(StringObject*, FramedAllocateString, DWORD stringLength); + extern FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); extern FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); extern FCDECL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); @@ -1615,8 +1619,6 @@ void DoGcStress (PT_CONTEXT regs, MethodDesc *pMD); #endif //HAVE_GCCOVER EXTERN_C FCDECL2(LPVOID, ArrayStoreCheck, Object** pElement, PtrArray** pArray); -FCDECL1(StringObject*, FramedAllocateString, DWORD stringLength); -FCDECL1(StringObject*, UnframedAllocateString, DWORD stringLength); OBJECTHANDLE ConstructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok); diff --git a/src/vm/jitinterfacegen.cpp b/src/vm/jitinterfacegen.cpp index 5cf1de911c..3c9166556c 100644 --- a/src/vm/jitinterfacegen.cpp +++ b/src/vm/jitinterfacegen.cpp @@ -229,6 +229,8 @@ void InitJITHelpers1() SetJitHelperFunction(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_NewS_MP_FastPortable); SetJitHelperFunction(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1VC_MP_FastPortable); SetJitHelperFunction(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1OBJ_MP_FastPortable); + + ECall::DynamicallyAssignFCallImpl(GetEEFuncEntryPoint(AllocateString_MP_FastPortable), ECall::FastAllocateString); #else // !FEATURE_IMPLICIT_TLS // If the TLS for Thread is low enough use the super-fast helpers if (gThreadTLSIndex < TLS_MINIMUM_AVAILABLE) |