Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 7e5e9c0

Browse files
Merge pull request #10782 from parjong/fix/x86_funclet_unwinding
[x86/Linux] Use GCInfo for funclet unwinding
2 parents b7af226 + fda1a8d commit 7e5e9c0

File tree

6 files changed

+55
-17
lines changed

6 files changed

+55
-17
lines changed

src/gcdump/i386/gcdumpx86.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,10 @@ size_t GCDump::DumpGCTable(PTR_CBYTE table,
452452
/* non-ptr arg push */
453453

454454
curOffs += (val & 0x07);
455+
#ifndef UNIX_X86_ABI
456+
// For x86/Linux, non-ptr arg pushes can be reported even for EBP frames
455457
_ASSERTE(!header.ebpFrame);
458+
#endif // UNIX_X86_ABI
456459
argCnt++;
457460

458461
DumpEncoding(bp, table-bp); bp = table;

src/jit/emit.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4403,6 +4403,12 @@ unsigned emitter::emitEndCodeGen(Compiler* comp,
44034403
emitFullyInt = fullyInt;
44044404
emitFullGCinfo = fullPtrMap;
44054405

4406+
#ifndef UNIX_X86_ABI
4407+
emitFullArgInfo = !emitHasFramePtr;
4408+
#else
4409+
emitFullArgInfo = fullPtrMap;
4410+
#endif
4411+
44064412
#if EMITTER_STATS
44074413
GCrefsTable.record(emitGCrFrameOffsCnt);
44084414
emitSizeTable.record(static_cast<unsigned>(emitSizeMethod));
@@ -6815,7 +6821,7 @@ void emitter::emitStackPushLargeStk(BYTE* addr, GCtype gcType, unsigned count)
68156821
*u2.emitArgTrackTop++ = (BYTE)gcType;
68166822
assert(u2.emitArgTrackTop <= u2.emitArgTrackTab + emitMaxStackDepth);
68176823

6818-
if (!emitHasFramePtr || needsGC(gcType))
6824+
if (emitFullArgInfo || needsGC(gcType))
68196825
{
68206826
if (emitFullGCinfo)
68216827
{
@@ -6887,7 +6893,7 @@ void emitter::emitStackPopLargeStk(BYTE* addr, bool isCall, unsigned char callIn
68876893

68886894
// This is an "interesting" argument
68896895

6890-
if (!emitHasFramePtr || needsGC(gcType))
6896+
if (emitFullArgInfo || needsGC(gcType))
68916897
{
68926898
argRecCnt += 1;
68936899
}
@@ -7035,7 +7041,7 @@ void emitter::emitStackKillArgs(BYTE* addr, unsigned count, unsigned char callIn
70357041

70367042
/* We're about to kill the corresponding (pointer) arg records */
70377043

7038-
if (emitHasFramePtr)
7044+
if (!emitFullArgInfo)
70397045
{
70407046
u2.emitGcArgTrackCnt -= gcCnt.Value();
70417047
}

src/jit/emit.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,8 +2018,9 @@ class emitter
20182018
/* The following logic keeps track of live GC ref values */
20192019
/************************************************************************/
20202020

2021-
bool emitFullGCinfo; // full GC pointer maps?
2022-
bool emitFullyInt; // fully interruptible code?
2021+
bool emitFullArgInfo; // full arg info (including non-ptr arg)?
2022+
bool emitFullGCinfo; // full GC pointer maps?
2023+
bool emitFullyInt; // fully interruptible code?
20232024

20242025
#if EMIT_TRACK_STACK_DEPTH
20252026
unsigned emitCntStackDepth; // 0 in prolog/epilog, One DWORD elsewhere

src/jit/gcencode.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2424,7 +2424,9 @@ size_t GCInfo::gcMakeRegPtrTable(BYTE* dest, int mask, const InfoHdr& header, un
24242424

24252425
assert((codeDelta & 0x7) == codeDelta);
24262426
*dest++ = 0xB0 | (BYTE)codeDelta;
2427+
#ifndef UNIX_X86_ABI
24272428
assert(!compiler->isFramePointerUsed());
2429+
#endif
24282430

24292431
/* Remember the new 'last' offset */
24302432

src/jit/morph.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16202,7 +16202,9 @@ void Compiler::fgSetOptions()
1620216202
// to use a frame pointer because of EH. But until all the code uses
1620316203
// the same test, leave info.compXcptnsCount here.
1620416204
if (info.compXcptnsCount > 0)
16205+
{
1620516206
codeGen->setFramePointerRequiredEH(true);
16207+
}
1620616208

1620716209
#else // !_TARGET_X86_
1620816210

@@ -16213,6 +16215,15 @@ void Compiler::fgSetOptions()
1621316215

1621416216
#endif // _TARGET_X86_
1621516217

16218+
#ifdef UNIX_X86_ABI
16219+
if (info.compXcptnsCount > 0)
16220+
{
16221+
assert(!codeGen->isGCTypeFixed());
16222+
// Enforce fully interruptible codegen for funclet unwinding
16223+
genInterruptible = true;
16224+
}
16225+
#endif // UNIX_X86_ABI
16226+
1621616227
fgCheckArgCnt();
1621716228

1621816229
if (info.compCallUnmanaged)

src/vm/eetwain.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,6 +2413,18 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
24132413
_ASSERTE(*castto(table, unsigned short *)++ == 0xBABE);
24142414
#endif
24152415

2416+
bool hasPartialArgInfo;
2417+
2418+
#ifndef UNIX_X86_ABI
2419+
hasPartialArgInfo = info->ebpFrame;
2420+
#else
2421+
// For x86/Linux, interruptible code always has full arg info
2422+
//
2423+
// This should be aligned with emitFullArgInfo setting at
2424+
// emitter::emitEndCodeGen (in JIT)
2425+
hasPartialArgInfo = false;
2426+
#endif
2427+
24162428
/*
24172429
Encoding table for methods that are fully interruptible
24182430
@@ -2611,9 +2623,9 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
26112623

26122624
argOfs--;
26132625
}
2614-
else if (info->ebpFrame)
2626+
else if (hasPartialArgInfo)
26152627
argCnt--;
2616-
else /* !ebpFrame && not a ref */
2628+
else /* full arg info && not a ref */
26172629
argOfs--;
26182630

26192631
/* Continue with the next lower bit */
@@ -2622,11 +2634,11 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
26222634
}
26232635
while (argOfs);
26242636

2625-
_ASSERTE((info->ebpFrame != 0) ||
2637+
_ASSERTE(!hasPartialArgInfo ||
26262638
isZero(argHigh) ||
26272639
(argHigh == CONSTRUCT_ptrArgTP(1, (argCnt-1))));
26282640

2629-
if (info->ebpFrame)
2641+
if (hasPartialArgInfo)
26302642
{
26312643
while (!intersect(argHigh, ptrArgs) && (!isZero(argHigh)))
26322644
argHigh >>= 1;
@@ -2643,10 +2655,10 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
26432655
}
26442656
else
26452657
{
2646-
/* For ESP-frames, all pushes are reported, and so
2658+
/* Full arg info reports all pushes, and thus
26472659
argOffs has to be consistent with argCnt */
26482660

2649-
_ASSERTE(info->ebpFrame || argCnt == argOfs);
2661+
_ASSERTE(hasPartialArgInfo || argCnt == argOfs);
26502662

26512663
/* store arg count */
26522664

@@ -2692,7 +2704,7 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
26922704
}
26932705
else {
26942706
/* non-ptr arg push */
2695-
_ASSERTE(!(info->ebpFrame));
2707+
_ASSERTE(!hasPartialArgInfo);
26962708
ptrOffs += (val & 0x07);
26972709
if (ptrOffs > curOffs) {
26982710
iptr = isThis = false;
@@ -2753,9 +2765,9 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
27532765
}
27542766
}
27552767

2756-
// For ebp-frames, need to find the next higest pointer for argHigh
2768+
// For partial arg info, need to find the next higest pointer for argHigh
27572769

2758-
if (info->ebpFrame)
2770+
if (hasPartialArgInfo)
27592771
{
27602772
for(argHigh = ptrArgTP(0); !isZero(argMask); argMask >>= 1)
27612773
{
@@ -2794,7 +2806,7 @@ unsigned scanArgRegTableI(PTR_CBYTE table,
27942806
info->thisPtrResult = thisPtrReg;
27952807
_ASSERTE(thisPtrReg == REGI_NA || (regNumToMask(thisPtrReg) & info->regMaskResult));
27962808

2797-
if (info->ebpFrame)
2809+
if (hasPartialArgInfo)
27982810
{
27992811
return 0;
28002812
}
@@ -3789,7 +3801,9 @@ bool UnwindEbpDoubleAlignFrame(
37893801
PREGDISPLAY pContext,
37903802
EECodeInfo *pCodeInfo,
37913803
hdrInfo *info,
3804+
PTR_CBYTE table,
37923805
PTR_CBYTE methodStart,
3806+
DWORD curOffs,
37933807
unsigned flags,
37943808
StackwalkCacheUnwindInfo *pUnwindInfo) // out-only, perf improvement
37953809
{
@@ -3815,8 +3829,9 @@ bool UnwindEbpDoubleAlignFrame(
38153829
// TODO Currently we assume that ESP of funclet frames is always fixed but actually it could change.
38163830
if (pCodeInfo->IsFunclet())
38173831
{
3832+
baseSP = curESP;
38183833
// Set baseSP as initial SP
3819-
baseSP = pContext->pCurrentContext->ResumeEsp;
3834+
baseSP += GetPushedArgSize(info, table, curOffs);
38203835
// 16-byte stack alignment padding (allocated in genFuncletProlog)
38213836
baseSP += 12;
38223837

@@ -4014,7 +4029,7 @@ bool UnwindStackFrame(PREGDISPLAY pContext,
40144029
* Now we know that have an EBP frame
40154030
*/
40164031

4017-
if (!UnwindEbpDoubleAlignFrame(pContext, pCodeInfo, info, methodStart, flags, pUnwindInfo))
4032+
if (!UnwindEbpDoubleAlignFrame(pContext, pCodeInfo, info, table, methodStart, curOffs, flags, pUnwindInfo))
40184033
return false;
40194034
}
40204035

0 commit comments

Comments
 (0)