Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion docs/design/datacontracts/RuntimeTypeSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ static class RuntimeTypeSystem_1_Helpers
| `EEClass` | `NumStaticFields` | `uint16` | Count of static fields of the EEClass |
| `EEClass` | `NumThreadStaticFields` | `uint16` | Count of threadstatic fields of the EEClass |
| `EEClass` | `OptionalFields` | `pointer` | Pointer to the `EEClassOptionalFields` for this type, or null if it has none |
| `EEClass` | `VMFlags` | `uint32` | Optional flags for the EEClass. Bit `0x40` (`VMFLAG_HASLAYOUT`) indicates the EEClass is a `LayoutEEClass` and its `LayoutInfo` may be read |
| `EEClass` | `VMFlags` | `uint32` | Optional flags for the EEClass. Bit `0x40` (`VMFLAG_HASLAYOUT`) indicates the EEClass is a `LayoutEEClass`; bit `0x10000` (`VMFLAG_INLINE_ARRAY`) indicates repeated inline-array field layout |
| `EEClassLayoutInfo` | `AlignmentRequirement` | `uint8` | Largest alignment requirement of all members of the type |
| `EEClassLayoutInfo` | `Flags` | `uint8` | Layout flags. Bit `0x01` (`e_BLITTABLE`) indicates the type is blittable |
| `EEClassLayoutInfo` | `LayoutType` | `uint8` | Layout kind: `Auto` (0), `Sequential` (1), `Explicit` (2), `CStruct` (3), `CUnion` (4) |
Expand Down Expand Up @@ -2565,3 +2565,37 @@ void GetCoreLibFieldDescAndDef(string @namespace, string typeName, string fieldN
fieldDef = mdReader.GetFieldDefinition(fieldHandle);
}
```

## Version 2

Version 2 adds inline-array inspection APIs:

<!-- BEGIN GENERATED: usage contract=RuntimeTypeSystem version=c2 diff-from=c1 -->
### Data descriptor changes from `c1`

_No changes._

### Global variable changes from `c1`

_No changes._

### Contract dependency changes from `c1`

_No changes._
<!-- END GENERATED: usage contract=RuntimeTypeSystem version=c2 diff-from=c1 -->

```csharp
partial interface IRuntimeTypeSystem : IContract
{
// True if the MethodTable represents an inline array.
bool IsInlineArray(ITypeHandle typeHandle);

// Returns the size of a single inline-array element represented by a field type.
uint GetInlineArrayElementSize(CorElementType fieldType, ITypeHandle? nestedType);
}
```

`IsInlineArray` follows a MethodTable's `EEClassOrCanonMT` link to its canonical `EEClass` and
returns whether the `EEClass.VMFlags` inline-array bit is set. `GetInlineArrayElementSize`
returns the target pointer size for a byref field, the nested value type's instance-field size for
a value-type field, and zero when the element type cannot be determined.
34 changes: 32 additions & 2 deletions docs/design/datacontracts/StackWalk.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Unwinding call frames on the stack usually requires an OS specific implementatio
| `FramedMethodFrame` | `TransitionBlockPtr` | `pointer` | Pointer to Frame's TransitionBlock |
| `FuncEvalFrame` | `DebuggerEvalPtr` | `pointer` | Pointer to the Frame's DebuggerEval object |
| `FuncEvalFrame` | `ReturnAddress` | `CodePointer` | Return address of the frame |
| `GCFrame` | `GCFlags` | `uint32` | GC_CALL_* promotion flags applied when reporting the protected slots |
| `GCFrame` | `GCFlags` | `uint32` | GC_CALL_* promotion flags or the value-class discriminator applied when reporting protected data |
| `GCFrame` | `Next` | `pointer` | Pointer to the next GCFrame toward the top of the chain |
| `GCFrame` | `NumObjRefs` | `uint32` | Count of protected object reference slots starting at ObjRefs |
| `GCFrame` | `ObjRefs` | `pointer` | Pointer to the array of protected object reference slots |
Expand Down Expand Up @@ -771,7 +771,7 @@ See [GCRefMap Format and Resolution](#gcrefmap-format-and-resolution) for the GC

After walking the thread's frames, `WalkStackReferences` reports two additional sets of roots that the GC keeps alive but that are not surfaced by per-frame GC info (matching native `gcenv.ee.cpp` `ScanStackRoots`):

- **GCFrame (GCPROTECT) chain**: starting from `Thread.GCFrame` (obtained via the `Thread` contract's `GetThreadData`), each `GCFrame` is walked via its `Next` pointer until TargetPointer.Null is reached. For each node, the `NumObjRefs` slots starting at `ObjRefs` are reported, applying the node's `GCFlags` (`GC_CALL_INTERIOR` / `GC_CALL_PINNED`) as the promotion flags. This mirrors native `GCFrame::GcScanRoots`.
- **GCFrame (GCPROTECT) chain**: starting from `Thread.GCFrame` (obtained via the `Thread` contract's `GetThreadData`), each `GCFrame` is walked via its `Next` pointer until TargetPointer.Null is reached. Each node reports the `NumObjRefs` slots starting at `ObjRefs`, applying `GC_CALL_INTERIOR` / `GC_CALL_PINNED` from `GCFlags`. This mirrors native `GCFrame::GcScanRoots`.
- **Exception tracker (ExInfo) chain**: starting from the thread's exception tracker, each in-flight exception object (the current one and any superseded/nested ones reached via `PreviousNestedInfo`) is reported through its thrown-object slot.

Both sets carry a non-zero, stack-resident `Source` and `StackPointer` set to the GCFrame / ExInfo node address (the node lives on the stack). A `GCFrame` node belongs to a separate chain from the explicit `Frame` chain, and an ExInfo node is likewise not a capital-F `Frame`, so neither is reported with the `Frame` source type. Both use the `Other` source type, which marks a root reported outside the per-frame walk.
Expand Down Expand Up @@ -818,3 +818,33 @@ The x86 GCInfo decoder lives under the [GCInfo contract](GCInfo.md) at `src/nati
The x86 architecture uses a custom unwinding algorithm defined in `gc_unwind_x86.inl`. The cDAC uses a copy of this algorithm ported to managed code in `X86Unwinder.cs`.

Currently there isn't great documentation on the algorithm, beyond inspecting the implementations.

## Version 2

Version 2 uses the Version 1 stack-walking algorithm and adds support for reporting
off-heap value classes from the thread's GCFrame chain. A GCFrame whose `GCFlags`
contains `GCFrameValueClassFlag` uses its `ValueClassInfoList` union arm to identify
the unboxed value classes whose embedded references
must be reported using each value class's method-table GC descriptor. Byref-like
inline arrays repeat their element's interior-pointer layout across the full value.

<!-- BEGIN GENERATED: usage contract=StackWalk version=c2 diff-from=c1 -->
### Data descriptor changes from `c1`

| Change | Data Descriptor | Field | Type | Meaning |
| --- | --- | --- | --- | --- |
| Added | `GCFrame` | `ValueClassInfoList` | `pointer` | Pointer to the head pointer of the off-heap value-class list protected by this GCFrame |
| Added | `ValueClassInfo` | `Data` | `pointer` | Pointer to the unboxed value-class data |
| Added | `ValueClassInfo` | `MethodTable` | `pointer` | Method table describing the value-class layout |
| Added | `ValueClassInfo` | `Next` | `pointer` | Pointer to the next protected value class |

### Global variable changes from `c1`

| Change | Global | Type | Meaning |
| --- | --- | --- | --- |
| Added | `GCFrameValueClassFlag` | `uint32` | GCFrame flag identifying a value-class payload |

### Contract dependency changes from `c1`

_No changes._
<!-- END GENERATED: usage contract=StackWalk version=c2 diff-from=c1 -->
9 changes: 7 additions & 2 deletions docs/design/datacontracts/data-descriptor-meanings.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
"EEClass.NumStaticFields": "Count of static fields of the EEClass",
"EEClass.NumThreadStaticFields": "Count of threadstatic fields of the EEClass",
"EEClass.OptionalFields": "Pointer to the `EEClassOptionalFields` for this type, or null if it has none",
"EEClass.VMFlags": "Optional flags for the EEClass. Bit `0x40` (`VMFLAG_HASLAYOUT`) indicates the EEClass is a `LayoutEEClass` and its `LayoutInfo` may be read",
"EEClass.VMFlags": "Optional flags for the EEClass. Bit `0x40` (`VMFLAG_HASLAYOUT`) indicates the EEClass is a `LayoutEEClass`; bit `0x10000` (`VMFLAG_INLINE_ARRAY`) indicates repeated inline-array field layout",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are redoing dynamic registration of GC stack reporting, it may be nice to redo to something that can work for NAOT as well.

"EEClassLayoutInfo.AlignmentRequirement": "Largest alignment requirement of all members of the type",
"EEClassLayoutInfo.Flags": "Layout flags. Bit `0x01` (`e_BLITTABLE`) indicates the type is blittable",
"EEClassLayoutInfo.LayoutType": "Layout kind: `Auto` (0), `Sequential` (1), `Explicit` (2), `CStruct` (3), `CUnion` (4)",
Expand Down Expand Up @@ -204,10 +204,11 @@
"GCAllocContext.Limit": "Allocation limit pointer",
"GCAllocContext.Pointer": "GC allocation pointer",
"GCCoverageInfo.SavedCode": "Pointer to the GCCover saved code copy, if supported",
"GCFrame.GCFlags": "GC_CALL_* promotion flags applied when reporting the protected slots",
"GCFrame.GCFlags": "GC_CALL_* promotion flags or the value-class discriminator applied when reporting protected data",
"GCFrame.Next": "Pointer to the next GCFrame toward the top of the chain",
"GCFrame.NumObjRefs": "Count of protected object reference slots starting at ObjRefs",
"GCFrame.ObjRefs": "Pointer to the array of protected object reference slots",
"GCFrame.ValueClassInfoList": "Pointer to the head pointer of the off-heap value-class list protected by this GCFrame",
"GCHeap.AllocAllocated": "Heap's highest address allocated by Alloc (in sever builds)",
"GCHeap.BackgroundMaxSavedAddr": "Heap's background saved highest address (only in server builds with background GC)",
"GCHeap.BackgroundMinSavedAddr": "Heap's background saved lowest address (only in server builds with background GC)",
Expand Down Expand Up @@ -699,6 +700,9 @@
"VASigCookie.SignatureLength": "Length in bytes of the raw vararg signature blob.",
"VASigCookie.SignaturePointer": "Target address of the raw vararg signature blob.",
"VASigCookie.SizeOfArgs": "Total size in bytes of the varargs argument area; used on x86 to locate the argument base",
"ValueClassInfo.Data": "Pointer to the unboxed value-class data",
"ValueClassInfo.MethodTable": "Method table describing the value-class layout",
"ValueClassInfo.Next": "Pointer to the next protected value class",
"VirtualCallStubManager.CacheEntryHeap": "Cache-entry heap (optional, present with virtual stub dispatch)",
"VirtualCallStubManager.IndcellHeap": "Indirection-cell heap",
"WebcilHeader.CoffSections": "Number of COFF section headers in the Webcil image",
Expand Down Expand Up @@ -780,6 +784,7 @@
"GCHeapOomData": "OOM related data in a struct (in workstation builds)",
"GCHeapSavedSweepEphemeralSeg": "Pointer to the static heap's saved sweep ephemeral segment (in workstation builds with segment and background GC)",
"GCHeapSavedSweepEphemeralStart": "Start of the static heap's sweep ephemeral segment (in workstation builds with segment and background GC)",
"GCFrameValueClassFlag": "GCFrame flag identifying a value-class payload",
"GCHighestAddress": "Highest GC address as recorded by the VM/GC interface",
"GCIdentifiers": "CSV string containing identifiers of the GC. Current values are \"server\", \"workstation\", \"regions\", and \"segments\"",
"GCInfoVersion": "JITted code GCInfo version",
Expand Down
9 changes: 5 additions & 4 deletions src/coreclr/debug/ee/funceval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3535,7 +3535,8 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE,
INT64 *pBufferForArgsArray = (INT64*)_alloca(cbAllocSize);
memset(pBufferForArgsArray, 0, cbAllocSize);

ProtectValueClassFrame protectValueClassFrame;
ValueClassInfo *pValueClasses = NULL;
GCFrame valueClassGCFrame(GetThread(), &pValueClasses);

Comment on lines +3538 to 3540
//
// Initialize our tracking array
Expand Down Expand Up @@ -3577,7 +3578,7 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE,
pMaybeInteriorPtrArray,
pByRefMaybeInteriorPtrArray,
pBufferForArgsArray,
protectValueClassFrame.GetValueClassInfoList()
&pValueClasses
DEBUG_ARG(pDataLocationArray)
);
}
Expand All @@ -3592,9 +3593,9 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE,
// the funceval. If a ThreadAbort occurred other than for a funcEval abort, we'll re-throw it manually.
EX_END_CATCH

protectValueClassFrame.Pop();
valueClassGCFrame.Pop();

CleanUpTemporaryVariables(protectValueClassFrame.GetValueClassInfoList());
CleanUpTemporaryVariables(&pValueClasses);

GCPROTECT_END(); // pByRefMaybeInteriorPtrArray
GCPROTECT_END(); // pMaybeInteriorPtrArray
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/nativeaot/Runtime/inc/MethodTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ class MethodTable
bool IsValueType()
{ return GetElementType() < ElementType_Class; }

bool IsByRefLike()
{ return (m_uFlags & IsByRefLikeFlag) && !HasComponentSize(); }

bool HasFinalizer()
{
return (m_uFlags & HasFinalizerFlag) != 0;
Expand Down
50 changes: 47 additions & 3 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "gcenv.h"
#include "gcheaputilities.h"
#include "gchandleutilities.h"
#include "gcdesc.h"

#include "CommonTypes.h"
#include "CommonMacros.h"
Expand Down Expand Up @@ -587,10 +588,53 @@ void Thread::GcScanRootsWorker(ScanFunc * pfnEnumCallback, ScanContext * pvCallb
{
ASSERT(pCurGCFrame->m_pThread == this);

for (uint32_t i = 0; i < pCurGCFrame->m_numObjRefs; i++)
if ((pCurGCFrame->m_gcFlags & GCFrameRegistration::GCFRAME_FLAG_VALUECLASS) != 0)
{
EnumGcRef(dac_cast<PTR_OBJECTREF>(pCurGCFrame->m_pObjRefs + i),
pCurGCFrame->m_MaybeInterior ? GCRK_Byref : GCRK_Object, pfnEnumCallback, pvCallbackData);
for (ValueClassInfo* pValueClass = *pCurGCFrame->m_ppValueClasses;
pValueClass != nullptr;
pValueClass = pValueClass->m_pNext)
{
MethodTable* pMethodTable = pValueClass->m_pMethodTable;

ASSERT(pMethodTable->IsValueType());
ASSERT(!pMethodTable->IsByRefLike());

if (!pMethodTable->ContainsGCPointers())
continue;

CGCDesc* pGCDesc = CGCDesc::GetCGCDescFromMT(pMethodTable);
CGCDescSeries* pSeries = pGCDesc->GetHighestSeries();
CGCDescSeries* pLastSeries = pGCDesc->GetLowestSeries();
uint32_t baseSize = pMethodTable->GetBaseSize();

ASSERT(pSeries >= pLastSeries);

do
{
size_t offset = pSeries->GetSeriesOffset() - sizeof(void*);
PTR_OBJECTREF pObjectRef =
dac_cast<PTR_OBJECTREF>(dac_cast<PTR_uint8_t>(pValueClass->m_pData) + offset);
PTR_OBJECTREF pObjectRefStop =
dac_cast<PTR_OBJECTREF>(
dac_cast<PTR_uint8_t>(pObjectRef) + pSeries->GetSeriesSize() + baseSize);

while (pObjectRef < pObjectRefStop)
{
EnumGcRef(pObjectRef, GCRK_Object, pfnEnumCallback, pvCallbackData);
pObjectRef++;
}

pSeries--;
} while (pSeries >= pLastSeries);
}
}
else
{
for (uint32_t i = 0; i < pCurGCFrame->m_numObjRefs; i++)
{
EnumGcRef(dac_cast<PTR_OBJECTREF>(pCurGCFrame->m_pObjRefs + i),
pCurGCFrame->m_gcFlags ? GCRK_Byref : GCRK_Object, pfnEnumCallback, pvCallbackData);
}
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,26 @@ struct ExInfo
volatile void* m_notifyDebuggerSP;
};

struct ValueClassInfo
{
ValueClassInfo* m_pNext;
MethodTable* m_pMethodTable;
void* m_pData;
};

struct GCFrameRegistration
{
static const uint32_t GCFRAME_FLAG_VALUECLASS = 0x80000000;

Thread* m_pThread;
GCFrameRegistration* m_pNext;
void** m_pObjRefs;
union
{
void** m_pObjRefs;
ValueClassInfo** m_ppValueClasses;
};
uint32_t m_numObjRefs;
int m_MaybeInterior;
uint32_t m_gcFlags;
};

struct InlinedThreadStaticRoot
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/FrameTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ FRAME_TYPE_NAME(ResolveHelperFrame)
#endif // FEATURE_RESOLVE_HELPER_DISPATCH
FRAME_TYPE_NAME(ExternalMethodFrame)
FRAME_TYPE_NAME(DynamicHelperFrame)
FRAME_TYPE_NAME(ProtectValueClassFrame)
FRAME_TYPE_NAME(DebuggerClassInitMarkFrame)
FRAME_TYPE_NAME(DebuggerExitFrame)
FRAME_TYPE_NAME(DebuggerU2MCatchHandlerFrame)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/callhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ class MethodDescCallSite
// variants. Using the WithValueTypes variant indicates that the caller
// has gc-protected the contents of value types of size greater than
// ENREGISTERED_PARAMTYPE_MAXSIZE (when it is defined, which is currently
// only on AMD64). ProtectValueClassFrame can be used to accomplish this,
// only on AMD64). A value-class GCFrame can be used to accomplish this,
// see CallDescrWithObjectArray in stackbuildersink.cpp.
//
// Not all usages of MethodDesc::CallXXX have been ported to the new convention. The end goal is to port them all and get
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,21 @@ DEFINE_CLASS(STACKFRAMEITERATOR, Runtime, StackFrameIterator)

DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo)

DEFINE_CLASS_U(Runtime, GCFrameRegistration, GCFrame)
DEFINE_FIELD_U(_reserved1, GCFrame, m_Next)
DEFINE_FIELD_U(_reserved2, GCFrame, m_pCurThread)
DEFINE_FIELD_U(_pObjRefs, GCFrame, m_pointers.m_pObjRefs)
DEFINE_FIELD_U(_numObjRefs, GCFrame, m_numObjRefs)
DEFINE_FIELD_U(_gcFlags, GCFrame, m_gcFlags)
#ifdef FEATURE_INTERPRETER
DEFINE_FIELD_U(_osStackLocation, GCFrame, m_osStackLocation)
#endif

DEFINE_CLASS_U(Runtime, ValueClassInfo, ValueClassInfo)
DEFINE_FIELD_U(_next, ValueClassInfo, pNext)
DEFINE_FIELD_U(_methodTable, ValueClassInfo, pMT)
DEFINE_FIELD_U(_data, ValueClassInfo, pData)

DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData)
DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes)
DEFINE_FIELD_U(_totalAvailableMemoryBytes, GCMemoryInfoData, totalAvailableMemoryBytes)
Expand Down
13 changes: 11 additions & 2 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,17 @@ CDAC_TYPE_INDETERMINATE(GCFrame)
CDAC_TYPE_FIELD(GCFrame, T_POINTER, Next, cdac_data<GCFrame>::Next)
CDAC_TYPE_FIELD(GCFrame, T_POINTER, ObjRefs, cdac_data<GCFrame>::ObjRefs)
CDAC_TYPE_FIELD(GCFrame, T_UINT32, NumObjRefs, cdac_data<GCFrame>::NumObjRefs)
CDAC_TYPE_FIELD(GCFrame, T_POINTER, ValueClassInfoList, cdac_data<GCFrame>::ValueClassInfoList)
CDAC_TYPE_FIELD(GCFrame, T_UINT32, GCFlags, cdac_data<GCFrame>::GCFlags)
CDAC_TYPE_END(GCFrame)

CDAC_TYPE_BEGIN(ValueClassInfo)
CDAC_TYPE_SIZE(sizeof(ValueClassInfo))
CDAC_TYPE_FIELD(ValueClassInfo, T_POINTER, Next, offsetof(ValueClassInfo, pNext))
CDAC_TYPE_FIELD(ValueClassInfo, T_POINTER, MethodTable, offsetof(ValueClassInfo, pMT))
CDAC_TYPE_FIELD(ValueClassInfo, T_POINTER, Data, offsetof(ValueClassInfo, pData))
CDAC_TYPE_END(ValueClassInfo)

CDAC_TYPE_BEGIN(RuntimeThreadLocals)
CDAC_TYPE_INDETERMINATE(RuntimeThreadLocals)
CDAC_TYPE_FIELD(RuntimeThreadLocals, TYPE(EEAllocContext), AllocContext, offsetof(RuntimeThreadLocals, alloc_context))
Expand Down Expand Up @@ -1733,6 +1741,7 @@ CDAC_GLOBAL_POINTER(MetadataUpdatesApplied, &::g_metadataUpdatesApplied)

#include "frames.h"
#undef FRAME_TYPE_NAME
CDAC_GLOBAL(GCFrameValueClassFlag, T_UINT32, GCFrame::GCFRAME_FLAG_VALUECLASS)

CDAC_GLOBAL(MethodDescTokenRemainderBitCount, T_UINT8, METHOD_TOKEN_REMAINDER_BIT_COUNT)

Expand Down Expand Up @@ -1902,10 +1911,10 @@ CDAC_GLOBAL_CONTRACT(PrecodeStubs, c1)
CDAC_GLOBAL_CONTRACT(ReJIT, c1)
#endif // PROFILING_SUPPORTED
CDAC_GLOBAL_CONTRACT(RuntimeInfo, c1)
CDAC_GLOBAL_CONTRACT(RuntimeTypeSystem, c1)
CDAC_GLOBAL_CONTRACT(RuntimeTypeSystem, c2)
CDAC_GLOBAL_CONTRACT(SHash, c1)
CDAC_GLOBAL_CONTRACT(Signature, c1)
CDAC_GLOBAL_CONTRACT(StackWalk, c1)
CDAC_GLOBAL_CONTRACT(StackWalk, c2)
CDAC_GLOBAL_CONTRACT(StressLog, c2)
CDAC_GLOBAL_CONTRACT(SyncBlock, c1)
CDAC_GLOBAL_CONTRACT(Thread, c1)
Expand Down
6 changes: 0 additions & 6 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3846,12 +3846,6 @@ static void NotifyExceptionPassStarted(StackFrameIterator *pThis, Thread *pThrea
if (pThis->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION)
{
Frame* pFrame = pThis->m_crawl.GetFrame();
// If the frame is ProtectValueClassFrame, move to the next one as we want to report the FuncEvalFrame
if (pFrame->GetFrameIdentifier() == FrameIdentifier::ProtectValueClassFrame)
{
pFrame = pFrame->PtrNextFrame();
_ASSERTE(pFrame != FRAME_TOP);
}
if ((pFrame->GetFrameIdentifier() == FrameIdentifier::FuncEvalFrame) || IsTopmostDebuggerU2MCatchHandlerFrame(pFrame))
{
EEToDebuggerExceptionInterfaceWrapper::NotifyOfCHFFilter((EXCEPTION_POINTERS *)&pExInfo->m_ptrs, pFrame);
Expand Down
Loading
Loading