diff options
Diffstat (limited to 'src/vm/jithelpers.cpp')
-rw-r--r-- | src/vm/jithelpers.cpp | 319 |
1 files changed, 16 insertions, 303 deletions
diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 32be77823c..8cff03ae60 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -4472,19 +4472,18 @@ HCIMPL_MONHELPER(JIT_MonEnterWorker_Portable, Object* obj) result = obj->EnterObjMonitorHelper(pCurThread); if (result == AwareLock::EnterHelperResult_Entered) { - MONHELPER_STATE(*pbLockTaken = 1;) + MONHELPER_STATE(*pbLockTaken = 1); return; } - else if (result == AwareLock::EnterHelperResult_Contention) { - AwareLock::EnterHelperResult resultSpin = obj->EnterObjMonitorHelperSpin(pCurThread); - if (resultSpin == AwareLock::EnterHelperResult_Entered) + result = obj->EnterObjMonitorHelperSpin(pCurThread); + if (result == AwareLock::EnterHelperResult_Entered) { - MONHELPER_STATE(*pbLockTaken = 1;) + MONHELPER_STATE(*pbLockTaken = 1); return; } - if (resultSpin == AwareLock::EnterHelperResult_Contention) + if (result == AwareLock::EnterHelperResult_Contention) { FC_INNER_RETURN_VOID(JIT_MonContention_Helper(obj, MONHELPER_ARG, GetEEFuncEntryPointMacro(JIT_MonEnter))); } @@ -4519,15 +4518,14 @@ HCIMPL1(void, JIT_MonEnter_Portable, Object* obj) { return; } - else if (result == AwareLock::EnterHelperResult_Contention) { - AwareLock::EnterHelperResult resultSpin = obj->EnterObjMonitorHelperSpin(pCurThread); - if (resultSpin == AwareLock::EnterHelperResult_Entered) + result = obj->EnterObjMonitorHelperSpin(pCurThread); + if (result == AwareLock::EnterHelperResult_Entered) { return; } - if (resultSpin == AwareLock::EnterHelperResult_Contention) + if (result == AwareLock::EnterHelperResult_Contention) { FC_INNER_RETURN_VOID(JIT_MonContention_Helper(obj, NULL, GetEEFuncEntryPointMacro(JIT_MonEnter))); } @@ -4563,16 +4561,15 @@ HCIMPL2(void, JIT_MonReliableEnter_Portable, Object* obj, BYTE* pbLockTaken) *pbLockTaken = 1; return; } - else if (result == AwareLock::EnterHelperResult_Contention) { - AwareLock::EnterHelperResult resultSpin = obj->EnterObjMonitorHelperSpin(pCurThread); - if (resultSpin == AwareLock::EnterHelperResult_Entered) + result = obj->EnterObjMonitorHelperSpin(pCurThread); + if (result == AwareLock::EnterHelperResult_Entered) { *pbLockTaken = 1; return; } - if (resultSpin == AwareLock::EnterHelperResult_Contention) + if (result == AwareLock::EnterHelperResult_Contention) { FC_INNER_RETURN_VOID(JIT_MonContention_Helper(obj, pbLockTaken, GetEEFuncEntryPointMacro(JIT_MonReliableEnter))); } @@ -4649,14 +4646,15 @@ HCIMPL3(void, JIT_MonTryEnter_Portable, Object* obj, INT32 timeOut, BYTE* pbLock *pbLockTaken = 1; return; } - else if (result == AwareLock::EnterHelperResult_Contention) { if (timeOut == 0) + { return; + } - AwareLock::EnterHelperResult resultSpin = obj->EnterObjMonitorHelperSpin(pCurThread); - if (resultSpin == AwareLock::EnterHelperResult_Entered) + result = obj->EnterObjMonitorHelperSpin(pCurThread); + if (result == AwareLock::EnterHelperResult_Entered) { *pbLockTaken = 1; return; @@ -4741,7 +4739,6 @@ FCIMPL1(void, JIT_MonExit_Portable, Object* obj) { return; } - else if (action == AwareLock::LeaveHelperAction_Signal) { FC_INNER_RETURN_VOID(JIT_MonExit_Signal(obj)); @@ -4773,7 +4770,6 @@ HCIMPL_MONHELPER(JIT_MonExitWorker_Portable, Object* obj) MONHELPER_STATE(*pbLockTaken = 0;) return; } - else if (action == AwareLock::LeaveHelperAction_Signal) { MONHELPER_STATE(*pbLockTaken = 0;) @@ -4821,7 +4817,7 @@ HCIMPL_MONHELPER(JIT_MonEnterStatic_Portable, AwareLock *lock) goto FramedLockHelper; } - if (lock->EnterHelper(pCurThread) == AwareLock::EnterHelperResult_Entered) + if (lock->EnterHelper(pCurThread, true /* checkRecursiveCase */)) { #if defined(_DEBUG) && defined(TRACK_SYNC) // The best place to grab this is from the ECall frame @@ -4909,289 +4905,6 @@ HCIMPL_MONHELPER(JIT_MonExitStatic_Portable, AwareLock *lock) HCIMPLEND #include <optdefault.h> -/*********************************************************************/ -// JITutil_Mon* are helpers than handle slow paths for JIT_Mon* methods -// implemented in assembly. They are not doing any spinning compared -// to the full fledged portable implementations above. -/*********************************************************************/ - -/*********************************************************************/ -HCIMPL_MONHELPER(JITutil_MonEnterWorker, Object* obj) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - OBJECTREF objRef = ObjectToOBJECTREF(obj); - - // The following makes sure that Monitor.Enter shows up on thread abort - // stack walks (otherwise Monitor.Enter called within a CER can block a - // thread abort indefinitely). Setting the __me internal variable (normally - // only set for fcalls) will cause the helper frame below to be able to - // backtranslate into the method desc for the Monitor.Enter fcall. - // - // Note that we need explicitly initialize Monitor.Enter fcall in - // code:SystemDomain::LoadBaseSystemClasses to make this work in the case - // where the first call ever to Monitor.Enter is done as JIT helper - // for synchronized method. - __me = GetEEFuncEntryPointMacro(JIT_MonEnter); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH, objRef); - - if (objRef == NULL) - COMPlusThrow(kArgumentNullException); - - MONHELPER_STATE(GCPROTECT_BEGININTERIOR(pbLockTaken);) - -#ifdef _DEBUG - Thread *pThread = GetThread(); - DWORD lockCount = pThread->m_dwLockCount; -#endif - if (GET_THREAD()->CatchAtSafePointOpportunistic()) - { - GET_THREAD()->PulseGCMode(); - } - objRef->EnterObjMonitor(); - _ASSERTE ((objRef->GetSyncBlock()->GetMonitor()->m_Recursion == 1 && pThread->m_dwLockCount == lockCount + 1) || - pThread->m_dwLockCount == lockCount); - MONHELPER_STATE(if (pbLockTaken != 0) *pbLockTaken = 1;) - - MONHELPER_STATE(GCPROTECT_END();) - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - -/*********************************************************************/ - -// This helper is only ever used as part of FCall, but it is implemented using HCIMPL macro -// so that it can be tail called from assembly helper without triggering asserts in debug. -HCIMPL2(void, JITutil_MonReliableEnter, Object* obj, BYTE* pbLockTaken) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - OBJECTREF objRef = ObjectToOBJECTREF(obj); - - // The following makes sure that Monitor.Enter shows up on thread abort - // stack walks (otherwise Monitor.Enter called within a CER can block a - // thread abort indefinitely). Setting the __me internal variable (normally - // only set for fcalls) will cause the helper frame below to be able to - // backtranslate into the method desc for the Monitor.Enter fcall. - __me = GetEEFuncEntryPointMacro(JIT_MonReliableEnter); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH, objRef); - - if (objRef == NULL) - COMPlusThrow(kArgumentNullException); - - GCPROTECT_BEGININTERIOR(pbLockTaken); - -#ifdef _DEBUG - Thread *pThread = GetThread(); - DWORD lockCount = pThread->m_dwLockCount; -#endif - if (GET_THREAD()->CatchAtSafePointOpportunistic()) - { - GET_THREAD()->PulseGCMode(); - } - objRef->EnterObjMonitor(); - _ASSERTE ((objRef->GetSyncBlock()->GetMonitor()->m_Recursion == 1 && pThread->m_dwLockCount == lockCount + 1) || - pThread->m_dwLockCount == lockCount); - *pbLockTaken = 1; - - GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - - -/*********************************************************************/ - -// This helper is only ever used as part of FCall, but it is implemented using HCIMPL macro -// so that it can be tail called from assembly helper without triggering asserts in debug. -HCIMPL3(void, JITutil_MonTryEnter, Object* obj, INT32 timeOut, BYTE* pbLockTaken) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - BOOL result = FALSE; - - OBJECTREF objRef = ObjectToOBJECTREF(obj); - - // The following makes sure that Monitor.TryEnter shows up on thread - // abort stack walks (otherwise Monitor.TryEnter called within a CER can - // block a thread abort for long periods of time). Setting the __me internal - // variable (normally only set for fcalls) will cause the helper frame below - // to be able to backtranslate into the method desc for the Monitor.TryEnter - // fcall. - __me = GetEEFuncEntryPointMacro(JIT_MonTryEnter); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH, objRef); - - if (objRef == NULL) - COMPlusThrow(kArgumentNullException); - - if (timeOut < -1) - COMPlusThrow(kArgumentOutOfRangeException); - - GCPROTECT_BEGININTERIOR(pbLockTaken); - - if (GET_THREAD()->CatchAtSafePointOpportunistic()) - { - GET_THREAD()->PulseGCMode(); - } - - result = objRef->TryEnterObjMonitor(timeOut); - *pbLockTaken = result != FALSE; - - GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - -/*********************************************************************/ -HCIMPL_MONHELPER(JITutil_MonExitWorker, Object* obj) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - MONHELPER_STATE(if (pbLockTaken != NULL && *pbLockTaken == 0) return;) - - OBJECTREF objRef = ObjectToOBJECTREF(obj); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB_1(Frame::FRAME_ATTR_NO_THREAD_ABORT|Frame::FRAME_ATTR_EXACT_DEPTH, objRef); - - if (objRef == NULL) - COMPlusThrow(kArgumentNullException); - - if (!objRef->LeaveObjMonitor()) - COMPlusThrow(kSynchronizationLockException); - - MONHELPER_STATE(if (pbLockTaken != 0) *pbLockTaken = 0;) - - TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE)); - - if (GET_THREAD()->IsAbortRequested()) { - GET_THREAD()->HandleThreadAbort(); - } - - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - -/*********************************************************************/ -// A helper for JIT_MonEnter that is on the callee side of an ecall -// frame and handles the contention case. - -HCIMPL_MONHELPER(JITutil_MonContention, AwareLock* lock) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - // The following makes sure that Monitor.Enter shows up on thread abort - // stack walks (otherwise Monitor.Enter called within a CER can block a - // thread abort indefinitely). Setting the __me internal variable (normally - // only set for fcalls) will cause the helper frame below to be able to - // backtranslate into the method desc for the Monitor.Enter fcall. - __me = GetEEFuncEntryPointMacro(JIT_MonEnter); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB(Frame::FRAME_ATTR_EXACT_DEPTH); - MONHELPER_STATE(GCPROTECT_BEGININTERIOR(pbLockTaken);) - -#ifdef _DEBUG - Thread *pThread = GetThread(); - DWORD lockCount = pThread->m_dwLockCount; -#endif - lock->Contention(); - _ASSERTE (pThread->m_dwLockCount == lockCount + 1); - MONHELPER_STATE(if (pbLockTaken != 0) *pbLockTaken = 1;) - - MONHELPER_STATE(GCPROTECT_END();) - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - -// This helper is only ever used as part of FCall, but it is implemented using HCIMPL macro -// so that it can be tail called from assembly helper without triggering asserts in debug. -HCIMPL2(void, JITutil_MonReliableContention, AwareLock* lock, BYTE* pbLockTaken) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - // The following makes sure that Monitor.Enter shows up on thread abort - // stack walks (otherwise Monitor.Enter called within a CER can block a - // thread abort indefinitely). Setting the __me internal variable (normally - // only set for fcalls) will cause the helper frame below to be able to - // backtranslate into the method desc for the Monitor.Enter fcall. - __me = GetEEFuncEntryPointMacro(JIT_MonReliableEnter); - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB(Frame::FRAME_ATTR_EXACT_DEPTH); - GCPROTECT_BEGININTERIOR(pbLockTaken); - -#ifdef _DEBUG - Thread *pThread = GetThread(); - DWORD lockCount = pThread->m_dwLockCount; -#endif - lock->Contention(); - _ASSERTE (pThread->m_dwLockCount == lockCount + 1); - *pbLockTaken = 1; - - GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - -/*********************************************************************/ -// A helper for JIT_MonExit and JIT_MonExitStatic that is on the -// callee side of an ecall frame and handles cases that might allocate, -// throw or block. -HCIMPL_MONHELPER(JITutil_MonSignal, AwareLock* lock) -{ - CONTRACTL - { - FCALL_CHECK; - } - CONTRACTL_END; - - // Monitor helpers are used as both hcalls and fcalls, thus we need exact depth. - HELPER_METHOD_FRAME_BEGIN_ATTRIB(Frame::FRAME_ATTR_EXACT_DEPTH | Frame::FRAME_ATTR_NO_THREAD_ABORT); - - lock->Signal(); - MONHELPER_STATE(if (pbLockTaken != 0) *pbLockTaken = 0;) - - TESTHOOKCALL(AppDomainCanBeUnloaded(GET_THREAD()->GetDomain()->GetId().m_dwId,FALSE)); - - if (GET_THREAD()->IsAbortRequested()) { - GET_THREAD()->HandleThreadAbort(); - } - - HELPER_METHOD_FRAME_END(); -} -HCIMPLEND - HCIMPL1(void *, JIT_GetSyncFromClassHandle, CORINFO_CLASS_HANDLE typeHnd_) CONTRACTL { FCALL_CHECK; |