diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-12-13 19:46:50 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-13 19:46:50 -0800 |
commit | bc5a76d93f21392acbdfb8ec820fa287b31f09e4 (patch) | |
tree | 4c8521fa7bd5024b531ec43485d7f2a8738cb338 /src/vm | |
parent | b3dc9a728ac9ee10ea7df713c8002678120c2e4d (diff) | |
download | coreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.tar.gz coreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.tar.bz2 coreclr-bc5a76d93f21392acbdfb8ec820fa287b31f09e4.zip |
Revert " Revert "[Local GC] Move knowledge of overlapped I/O objects to the EE through four callbacks (#14982)""
Diffstat (limited to 'src/vm')
-rw-r--r-- | src/vm/appdomain.cpp | 38 | ||||
-rw-r--r-- | src/vm/gcenv.ee.cpp | 81 | ||||
-rw-r--r-- | src/vm/gcenv.ee.h | 2 | ||||
-rw-r--r-- | src/vm/gcenv.ee.standalone.cpp | 3 | ||||
-rw-r--r-- | src/vm/gcenv.ee.static.cpp | 3 |
5 files changed, 122 insertions, 5 deletions
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 370847c9a2..07e3280342 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -9053,7 +9053,43 @@ void AppDomain::HandleAsyncPinHandles() // 4. Then we can delete all AsyncPinHandle marked with READYTOCLEAN. IGCHandleStore *pBucketInDefault = SystemDomain::System()->DefaultDomain()->m_handleStore; - pBucket->RelocateAsyncPinnedHandles(pBucketInDefault); + auto clearIfComplete = [](Object* object) + { + LIMITED_METHOD_CONTRACT; + + assert(object != nullptr); + if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) + { + return; + } + + OVERLAPPEDDATAREF overlapped = (OVERLAPPEDDATAREF)(ObjectToOBJECTREF((Object*)object)); + if (overlapped->HasCompleted()) + { + // IO has finished. We don't need to pin the user buffer any longer. + overlapped->m_userObject = NULL; + } + + BashMTForPinnedObject(ObjectToOBJECTREF(object)); + }; + + auto setHandle = [](Object* object, OBJECTHANDLE handle) + { + LIMITED_METHOD_CONTRACT; + + assert(object != nullptr); + assert(handle); + + if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) + { + return; + } + + OverlappedDataObject* overlapped = (OverlappedDataObject*)object; + overlapped->m_pinSelf = handle; + }; + + pBucket->RelocateAsyncPinnedHandles(pBucketInDefault, clearIfComplete, setHandle); OverlappedDataObject::RequestCleanup(); } diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp index e5da889a64..a880fdbca6 100644 --- a/src/vm/gcenv.ee.cpp +++ b/src/vm/gcenv.ee.cpp @@ -1201,7 +1201,7 @@ namespace }; InlineSString<MaxThreadNameSize> wideName; - const WCHAR* namePtr; + const WCHAR* namePtr = nullptr; EX_TRY { if (name != nullptr) @@ -1214,7 +1214,6 @@ namespace { // we're not obligated to provide a name - if it's not valid, // just report nullptr as the name. - namePtr = nullptr; } EX_END_CATCH(SwallowAllExceptions) @@ -1307,3 +1306,81 @@ bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool i return CreateNonSuspendableThread(threadStart, arg, name); } } + +void GCToEEInterface::WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback) +{ + LIMITED_METHOD_CONTRACT; + + assert(object != nullptr); + assert(sc != nullptr); + assert(callback != nullptr); + if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) + { + // not an overlapped data object - nothing to do. + return; + } + + // reporting the pinned user objects + OverlappedDataObject *pOverlapped = (OverlappedDataObject *)object; + if (pOverlapped->m_userObject != NULL) + { + //callback(OBJECTREF_TO_UNCHECKED_OBJECTREF(pOverlapped->m_userObject), (ScanContext *)lp1, GC_CALL_PINNED); + if (pOverlapped->m_isArray) + { + // OverlappedDataObject is very special. An async pin handle keeps it alive. + // During GC, we also make sure + // 1. m_userObject itself does not move if m_userObject is not array + // 2. Every object pointed by m_userObject does not move if m_userObject is array + // We do not want to pin m_userObject if it is array. But m_userObject may be updated + // during relocation phase before OverlappedDataObject is doing relocation. + // m_userObjectInternal is used to track the location of the m_userObject before it is updated. + pOverlapped->m_userObjectInternal = static_cast<void*>(OBJECTREFToObject(pOverlapped->m_userObject)); + ArrayBase* pUserObject = (ArrayBase*)OBJECTREFToObject(pOverlapped->m_userObject); + Object **ppObj = (Object**)pUserObject->GetDataPtr(TRUE); + size_t num = pUserObject->GetNumComponents(); + for (size_t i = 0; i < num; i++) + { + callback(ppObj + i, sc, GC_CALL_PINNED); + } + } + else + { + callback(&OBJECTREF_TO_UNCHECKED_OBJECTREF(pOverlapped->m_userObject), (ScanContext *)sc, GC_CALL_PINNED); + } + } + + if (pOverlapped->GetAppDomainId() != DefaultADID && pOverlapped->GetAppDomainIndex().m_dwIndex == DefaultADID) + { + OverlappedDataObject::MarkCleanupNeededFromGC(); + } +} + +void GCToEEInterface::WalkAsyncPinned(Object* object, void* context, void (*callback)(Object*, Object*, void*)) +{ + LIMITED_METHOD_CONTRACT; + + assert(object != nullptr); + assert(callback != nullptr); + + if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass) + { + return; + } + + OverlappedDataObject *pOverlapped = (OverlappedDataObject *)(object); + if (pOverlapped->m_userObject != NULL) + { + Object * pUserObject = OBJECTREFToObject(pOverlapped->m_userObject); + callback(object, pUserObject, context); + if (pOverlapped->m_isArray) + { + ArrayBase* pUserArrayObject = (ArrayBase*)pUserObject; + Object **pObj = (Object**)pUserArrayObject->GetDataPtr(TRUE); + size_t num = pUserArrayObject->GetNumComponents(); + for (size_t i = 0; i < num; i ++) + { + callback(pUserObject, pObj[i], context); + } + } + } +} diff --git a/src/vm/gcenv.ee.h b/src/vm/gcenv.ee.h index b2ada36bcd..e3867b7e98 100644 --- a/src/vm/gcenv.ee.h +++ b/src/vm/gcenv.ee.h @@ -60,6 +60,8 @@ public: bool IsGCThread(); bool WasCurrentThreadCreatedByGC(); bool CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name); + void WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback); + void WalkAsyncPinned(Object* object, void* context, void(*callback)(Object*, Object*, void*)); }; } // namespace standalone diff --git a/src/vm/gcenv.ee.standalone.cpp b/src/vm/gcenv.ee.standalone.cpp index 5ba2aca812..be8ceca0c1 100644 --- a/src/vm/gcenv.ee.standalone.cpp +++ b/src/vm/gcenv.ee.standalone.cpp @@ -6,6 +6,7 @@ #include "gcenv.h" #include "gcenv.ee.h" #include "threadsuspend.h" +#include "nativeoverlapped.h" #ifdef FEATURE_COMINTEROP #include "runtimecallablewrapper.h" @@ -27,4 +28,4 @@ namespace standalone #include "gcenv.ee.cpp" -} // namespace standalone
\ No newline at end of file +} // namespace standalone diff --git a/src/vm/gcenv.ee.static.cpp b/src/vm/gcenv.ee.static.cpp index 240e325a9e..975decadf4 100644 --- a/src/vm/gcenv.ee.static.cpp +++ b/src/vm/gcenv.ee.static.cpp @@ -6,6 +6,7 @@ #include "gcenv.h" #include "../gc/env/gcenv.ee.h" #include "threadsuspend.h" +#include "nativeoverlapped.h" #ifdef FEATURE_COMINTEROP #include "runtimecallablewrapper.h" @@ -22,4 +23,4 @@ extern MethodTable* pWeakReferenceOfTCanonMT; // Finalizes a weak reference directly. extern void FinalizeWeakReference(Object* obj); -#include "gcenv.ee.cpp"
\ No newline at end of file +#include "gcenv.ee.cpp" |