summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarol Eidt <carol.eidt@microsoft.com>2018-03-30 16:46:05 -0700
committerCarol Eidt <carol.eidt@microsoft.com>2018-03-30 16:46:05 -0700
commit2fbbf62d365fec4d778d7342908ddbb3f924a2eb (patch)
tree70ecd0fbde5fddb480c053b73c3968d6bb1fbe7c
parent757cb82a5800fd043713d7ee40feba1dd2c89793 (diff)
downloadcoreclr-2fbbf62d365fec4d778d7342908ddbb3f924a2eb.tar.gz
coreclr-2fbbf62d365fec4d778d7342908ddbb3f924a2eb.tar.bz2
coreclr-2fbbf62d365fec4d778d7342908ddbb3f924a2eb.zip
GC info fix: correctly adjust argCnt
When there are nested calls, and there is a non-ptr on the stack below the last ptr popped by the inner call, the `argHigh` and `argCnt` values can get out of sync.
-rw-r--r--src/vm/eetwain.cpp25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/vm/eetwain.cpp b/src/vm/eetwain.cpp
index fcaa010895..1fb332ecd4 100644
--- a/src/vm/eetwain.cpp
+++ b/src/vm/eetwain.cpp
@@ -2402,6 +2402,11 @@ FINISHED:
this function is called to find all live objects (pushed arguments)
and to get the stack base for fully interruptible methods.
Returns size of things pushed on the stack for ESP frames
+
+ Arguments:
+ table - The pointer table
+ curOffs - The current code offset
+ info - Incoming arg used to determine if there's a frame, and to save results
*/
static
@@ -2416,14 +2421,14 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
} CONTRACTL_END;
regNum thisPtrReg = REGI_NA;
- unsigned ptrRegs = 0;
- unsigned iptrRegs = 0;
- unsigned ptrOffs = 0;
- unsigned argCnt = 0;
+ unsigned ptrRegs = 0; // The mask of registers that contain pointers
+ unsigned iptrRegs = 0; // The subset of ptrRegs that are interior pointers
+ unsigned ptrOffs = 0; // The code offset of the table entry we are currently looking at
+ unsigned argCnt = 0; // The number of args that have been pushed
- ptrArgTP ptrArgs(0);
- ptrArgTP iptrArgs(0);
- ptrArgTP argHigh(0);
+ ptrArgTP ptrArgs(0); // The mask of stack values that contain pointers.
+ ptrArgTP iptrArgs(0); // The subset of ptrArgs that are interior pointers.
+ ptrArgTP argHigh(0); // The current mask position that corresponds to the top of the stack.
bool isThis = false;
bool iptr = false;
@@ -2659,8 +2664,14 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
if (hasPartialArgInfo)
{
+ // We always leave argHigh pointing to the next ptr arg.
+ // So, while argHigh is non-zero, and not a ptrArg, we shift right (and subtract
+ // one arg from our argCnt) until it is a ptrArg.
while (!intersect(argHigh, ptrArgs) && (!isZero(argHigh)))
+ {
argHigh >>= 1;
+ argCnt--;
+ }
}
}