summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergiy Kuryata <sergeyk@microsoft.com>2015-10-14 09:36:12 -0700
committerSergiy Kuryata <sergeyk@microsoft.com>2015-10-14 09:36:12 -0700
commitba3a1552fdacac4047681e45256edef2599c8b0b (patch)
tree89c5f65f84fe7c768548e05d8a39ee75ede12702 /src
parentd1c27d62267d08a0c1c9be454e896984aa6b55fa (diff)
parentd7772f3feb5fd09ea841add320f6e2f25642686d (diff)
downloadcoreclr-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.cpp68
-rw-r--r--src/vm/jitinterface.h6
-rw-r--r--src/vm/jitinterfacegen.cpp2
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)