Modify conservative GC code for unaligned InlinedCallFrames
authorRichard L Ford <richford@microsoft.com>
Wed, 8 Jul 2015 07:17:53 +0000 (00:17 -0700)
committerRichard L Ford <richford@microsoft.com>
Wed, 8 Jul 2015 23:46:46 +0000 (16:46 -0700)
When making pinvoke calls the JITs allocate InlinedCallFrames
within their stack frames to record the location
of the managed stack frame. These InlinedCallFrames are
not necessarily 8-byte aligned. These were being used
as the topStack in src/vm/gcenv.cpp, in the method
GCToEEInterface::ScanStackRoots.

This change checks to see if a frame is an InlinedCallFrame.
If so then its GetCallSiteSP method is used to
get the real top of stack. This will always be aligned.

There were two problem before this change wwhen the
frame was misaligned (e.g. ending with 4 or c):

1. GCToEEInterface::ScanStackRoots starts at the
topStack and look at every 8-byte chunk as if it were a
pointer. But if topStack is unaligned it is not really
finding the pointers on the stack.

2. When it gets to the bottom the 8-byte access
read the first 4 bytes ok, but the last 4 bytes
go beyond mapped addresses and an access violation
results.

src/vm/gcenv.cpp

index ea7d634..963ca3a 100644 (file)
@@ -511,7 +511,14 @@ VOID GCToEEInterface::ScanStackRoots(Thread * pThread, promote_func* fn, ScanCon
         // Since we report every thing as pinned, we don't need to run following code for relocation phase.
         if (sc->promotion)
         {
-            Object ** topStack = (Object **)pThread->GetFrame();
+            Frame* pTopFrame = pThread->GetFrame();
+            Object ** topStack = (Object **)pTopFrame;
+            if ((pTopFrame != ((Frame*)-1)) 
+                && (pTopFrame->GetVTablePtr() == InlinedCallFrame::GetMethodFrameVPtr())) {
+                // It is an InlinedCallFrame. Get SP from it.
+                InlinedCallFrame* pInlinedFrame = (InlinedCallFrame*)pTopFrame;
+                topStack = (Object **)pInlinedFrame->GetCallSiteSP();
+            } 
             Object ** bottomStack = (Object **) pThread->GetCachedStackBase();
             Object ** walk;
             for (walk = topStack; walk < bottomStack; walk ++)