Skip to content
Merged
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
13 changes: 0 additions & 13 deletions src/coreclr/vm/debugdebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,6 @@ static StackWalkAction GetStackFramesCallback(CrawlFrame* pCf, VOID* data)
MethodDesc* pFunc = pCf->GetFunction();
DebugStackTrace::GetStackFramesData* pData = (DebugStackTrace::GetStackFramesData*)data;

#ifdef TARGET_WASM
// The portable-entrypoint slow path keeps its prestub frame active while it invokes a newly
// discovered R2R body. The body is already reported as a frameless method.
if (!pCf->IsFrameless() &&
pCf->GetFrame()->GetFrameIdentifier() == FrameIdentifier::PrestubMethodFrame &&
pData->cElements > 0 &&
pData->pElements[pData->cElements - 1].pFunc == pFunc &&
pData->pElements[pData->cElements - 1].ip != (PCODE)NULL)
{
return SWA_CONTINUE;
}
#endif // TARGET_WASM

if (pFunc != nullptr && pFunc == g_pEnvironmentCallEntryPointMethodDesc)
{
return SWA_CONTINUE;
Expand Down
26 changes: 26 additions & 0 deletions src/coreclr/vm/frames.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ class Frame
FRAME_ATTR_EXCEPTION = 1, // This frame caused an exception
FRAME_ATTR_FAULTED = 4, // Exception caused by Win32 fault
FRAME_ATTR_RESUMABLE = 8, // We may resume from this frame
FRAME_ATTR_NO_MANAGED_ACTIVATION = 16, // Retained for rooting and unwinding, not an additional managed call
};
unsigned GetFrameAttribs_Impl()
{
Expand Down Expand Up @@ -1397,9 +1398,34 @@ typedef DPTR(class PrestubMethodFrame) PTR_PrestubMethodFrame;

class PrestubMethodFrame : public FramedMethodFrame
{
#ifdef TARGET_WASM
bool m_isPrestubComplete = false;
#endif // TARGET_WASM

public:
PrestubMethodFrame(TransitionBlock * pTransitionBlock, MethodDesc * pMD);

#ifdef TARGET_WASM
void MarkPrestubComplete()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
MODE_COOPERATIVE;
}
CONTRACTL_END;

m_isPrestubComplete = true;
}

unsigned GetFrameAttribs_Impl()
{
LIMITED_METHOD_DAC_CONTRACT;
return m_isPrestubComplete ? FRAME_ATTR_NO_MANAGED_ACTIVATION : FRAME_ATTR_NONE;
}
#endif // TARGET_WASM

void GcScanRoots_Impl(promote_func *fn, ScanContext* sc)
{
WRAPPER_NO_CONTRACT;
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/vm/prestub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2207,6 +2207,15 @@ void ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex(PCODE portableE
if (targetIp == NULL)
{
_ASSERTE(!PortableEntryPoint::PrefersInterpreterEntryPoint(portableEntrypoint));
#ifdef TARGET_WASM
Comment thread
lewing marked this conversation as resolved.
// Keep the transition and argument roots while invoking R2R code, but report
// the managed activation through its R2R body rather than this prestub.
// An FCall can still need the prestub to represent its native implementation.
Comment thread
lewing marked this conversation as resolved.
if (!pMethod->IsFCall())
{
pPFrame->MarkPrestubComplete();
}
Comment thread
lewing marked this conversation as resolved.
#endif // TARGET_WASM
Object* continuationRet = nullptr;
Object** pContinuationRet = nullptr;
#ifdef TARGET_WASM
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/vm/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,13 @@ StackWalkAction StackFrameIterator::Filter(void)
case SFITER_SKIPPED_FRAME_FUNCTION:
if (!fSkippingFunclet)
{
#ifdef TARGET_WASM
if ((m_flags & FUNCTIONSONLY) &&
(m_crawl.pFrame->GetFrameAttribs() & Frame::FRAME_ATTR_NO_MANAGED_ACTIVATION))
{
break;
}
#endif // TARGET_WASM
if (m_flags & GC_FUNCLET_REFERENCE_REPORTING)
{
// If we are enumerating frames for GC reporting and we determined that
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using Xunit;
using TestLibrary;
Expand Down Expand Up @@ -117,10 +118,66 @@ public class Program : ProgramBase<InputData>, TestItf2<InputData>
[Fact]
public static void TestEntryPoint()
{
ValidateCurrentMethod();
new Program().Start();
ValidateExceptionStackTrace();
}

private static void ValidateCurrentMethod()
{
for (int i = 0; i < 2; i++)
{
Assert.Equal(nameof(ValidateCurrentMethod), MethodBase.GetCurrentMethod().Name);
Assert.Equal(nameof(GetCurrentMethodInlineable), GetCurrentMethodInlineable().Name);
MethodBase genericMethod = GetCurrentMethodGeneric<string>();
Assert.Equal(nameof(GetCurrentMethodGeneric), genericMethod.Name);
Assert.True(genericMethod.IsGenericMethodDefinition);
Assert.Equal(typeof(Program).Assembly, Assembly.GetExecutingAssembly());
Assert.Equal(typeof(Program).Assembly, Assembly.GetCallingAssembly());
ValidateRecursiveCurrentMethod(3);
InputData byref = new InputData { i = 2 };
ValidateTransitionRoots(new InputData { i = 1 }, ref byref,
(new InputData { i = 3 }, new InputData { i = 4 }));
}
}

private static MethodBase GetCurrentMethodInlineable() => MethodBase.GetCurrentMethod();

private static MethodBase GetCurrentMethodGeneric<T>() => MethodBase.GetCurrentMethod();

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ValidateTransitionRoots(InputData value, ref InputData byref, (InputData, InputData) pair)
{
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true, compacting: true);
Assert.Equal(1, value.i);
Assert.Equal(2, byref.i);
Assert.Equal(3, pair.Item1.i);
Assert.Equal(4, pair.Item2.i);
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ValidateRecursiveCurrentMethod(int depth)
{
Assert.Equal(nameof(ValidateRecursiveCurrentMethod), MethodBase.GetCurrentMethod().Name);
if (depth > 0)
{
ValidateRecursiveCurrentMethod(depth - 1);
}
else
{
int frameCount = 0;
foreach (System.Diagnostics.StackFrame frame in new System.Diagnostics.StackTrace().GetFrames())
{
if (frame.GetMethod().Name == nameof(ValidateRecursiveCurrentMethod))
{
frameCount++;
}
}

Assert.Equal(4, frameCount);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowForStackTrace() => throw new Exception();

Expand Down
Loading