Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,8 @@ enum CorInfoHelpFunc
CORINFO_HELP_ALLOC_CONTINUATION_METHOD,
CORINFO_HELP_ALLOC_CONTINUATION_CLASS,

CORINFO_HELP_WASM_PROF_SAMPLEPOINT, // WASM only: cooperative EventPipe CPU-sampling samplepoint

CORINFO_HELP_COUNT,
};

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* 406b139f-b910-4579-a9a8-91eb153ab024 */
0x406b139f,
0xb910,
0x4579,
{0xa9, 0xa8, 0x91, 0xeb, 0x15, 0x3a, 0xb0, 0x24}
constexpr GUID JITEEVersionIdentifier = { /* c957e556-a232-49bd-8fa4-f18fab00f111 */
0xc957e556,
0xa232,
0x49bd,
{0x8f, 0xa4, 0xf1, 0x8f, 0xab, 0x00, 0xf1, 0x11}
};

#endif // JIT_EE_VERSIONING_GUID_H
8 changes: 8 additions & 0 deletions src/coreclr/inc/jithelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,14 @@
DYNAMICJITHELPER(CORINFO_HELP_ALLOC_CONTINUATION_METHOD, NULL, METHOD__ASYNC_HELPERS__ALLOC_CONTINUATION_METHOD)
DYNAMICJITHELPER(CORINFO_HELP_ALLOC_CONTINUATION_CLASS, NULL, METHOD__ASYNC_HELPERS__ALLOC_CONTINUATION_CLASS)

// WASM EventPipe CPU-sampling samplepoint. Native helper (no managed fallback), auto-wrapped in a
// PortableEntryPoint by getHelperFtnAddr. Never emitted on other targets; NULL keeps enum/table aligned.
#ifdef TARGET_WASM
JITHELPER(CORINFO_HELP_WASM_PROF_SAMPLEPOINT, JIT_WasmProfSamplepoint, METHOD__NIL)
#else
JITHELPER(CORINFO_HELP_WASM_PROF_SAMPLEPOINT, NULL, METHOD__NIL)
#endif

#undef JITHELPER
#undef DYNAMICJITHELPER
#undef JITHELPER
Expand Down
4 changes: 3 additions & 1 deletion src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION`
// and handle pending work.
#define READYTORUN_MAJOR_VERSION 32
#define READYTORUN_MINOR_VERSION 0x0000
#define READYTORUN_MINOR_VERSION 0x0001

#define MINIMUM_READYTORUN_MAJOR_VERSION 26

Expand Down Expand Up @@ -82,6 +82,7 @@
// method's ReadyToRun entry point and fixups.
// R2R Version 31.1 adds READYTORUN_FLAG_SINGLE_THREADED, which records that the image lays out [ThreadStatic] fields as regular statics
// for a runtime built without FEATURE_MULTITHREADING.
// R2R Version 32.1 adds READYTORUN_HELPER_WasmProfSamplepoint (used on WebAssembly)

struct READYTORUN_CORE_HEADER
{
Expand Down Expand Up @@ -528,6 +529,7 @@ enum ReadyToRunHelper
READYTORUN_HELPER_InitClass = 0x116,
READYTORUN_HELPER_InitInstClass = 0x117,
READYTORUN_HELPER_R2RToInterpreter = 0x118,
READYTORUN_HELPER_WasmProfSamplepoint = 0x119,
};

#include "readytoruninstructionset.h"
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/inc/readytorunhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ HELPER(READYTORUN_HELPER_PInvokeBegin, CORINFO_HELP_JIT_PINVOKE_BEG
HELPER(READYTORUN_HELPER_PInvokeEnd, CORINFO_HELP_JIT_PINVOKE_END, )
HELPER(READYTORUN_HELPER_ResumeAfterCatch, CORINFO_HELP_JIT_RESUME_AFTER_CATCH, )
HELPER(READYTORUN_HELPER_GCPoll, CORINFO_HELP_POLL_GC, )
HELPER(READYTORUN_HELPER_WasmProfSamplepoint, CORINFO_HELP_WASM_PROF_SAMPLEPOINT, )
HELPER(READYTORUN_HELPER_ReversePInvokeEnter, CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, )
HELPER(READYTORUN_HELPER_ReversePInvokeExit, CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, )

Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5018,6 +5018,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Transform any strongly connected components into reducible flow.
//
DoPhase(this, PHASE_WASM_TRANSFORM_SCCS, &Compiler::fgWasmTransformSccs);

// Insert EventPipe CPU-sampling samplepoints before lowering.
//
DoPhase(this, PHASE_WASM_PROF_INSTRUMENT, &Compiler::fgWasmProfInstrument);
#endif

// Assign registers to variables, etc.
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7026,6 +7026,7 @@ class Compiler
PhaseStatus fgWasmRepairTryEntries();
PhaseStatus fgWasmVirtualIP();
PhaseStatus fgWasmSpillRefs();
PhaseStatus fgWasmProfInstrument();
#ifdef DEBUG
void fgDumpWasmControlFlow();
void fgDumpWasmControlFlowDot();
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compphases.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ CompPhaseNameMacro(PHASE_WASM_TRANSFORM_SCCS, "Wasm transform sccs",
CompPhaseNameMacro(PHASE_WASM_CONTROL_FLOW, "Wasm control flow", false, -1, false)
CompPhaseNameMacro(PHASE_WASM_SPILL_REFS, "Wasm spill refs", false, -1, false)
CompPhaseNameMacro(PHASE_WASM_VIRTUAL_IP, "Wasm virtual IP", false, -1, false)
CompPhaseNameMacro(PHASE_WASM_PROF_INSTRUMENT, "Wasm profiler instrumentation", false, -1, false)

CompPhaseNameMacro(PHASE_ASYNC, "Transform async", false, -1, true)
CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", true, -1, false)
Expand Down
76 changes: 75 additions & 1 deletion src/coreclr/jit/fgwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2466,7 +2466,7 @@ PhaseStatus Compiler::fgWasmSpillRefs()

for (GenTree* tree : LIR::AsRange(block))
{
if (tree->IsCall())
if (tree->IsCall() && IsPotentialGCSafePoint(tree))

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.

I think this guard skips more than intended. Because the operand-removal VisitOperands(removeUses) lives inside this if, and the fallback removal further down is guarded by if (!tree->IsCall()), the ref/byref operands of a NoGC helper call are now never removed from defs.

One concrete case is CORINFO_HELP_BULK_WRITEBARRIER_SMALL from Lowering::LowerBlockStoreAsGcBulkCopyCall: its destination is typically a non-invariant byref (e.g. ADD(obj, offset)), so it gets pushed into defs and stays there. In a checked JIT that should trip assert(defs.empty()) at the start of the next block; in release it would lead to unnecessary pinned spills at the next GC-safe call. This affects all wasm methods, not only instrumented ones.

As far as I can tell, the samplepoints themselves don't need this change: they're inserted at the start of a block, where no LIR values are live, so they never cause spills anyway. Would it work to either revert this line, or keep operand removal unconditional for all calls and gate only the spilling? Something like:

if (tree->IsCall())
{
    tree->VisitOperands(...removeUses...);

    if (!defs.empty() && IsPotentialGCSafePoint(tree))
    {
        // spill
    }
}

(I found this by reading the code; I haven't reproduced it.)

Note

This comment was generated with GitHub Copilot assistance.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1, the code here is meant to consume all outstanding refs for the closest parent call, regardless of whether it's a safepoint or not. It's true that we only need to spill not-yet-consumed refs if the tree is a safe point though, so I think it is sound to change the code to what @lewing is suggesting.

{
// If we have a call, consume the call's operands from the defs list BEFORE spilling
// any live refs. This is because a GC-ref node which is only live INTO (and not across) another call
Expand Down Expand Up @@ -3503,6 +3503,80 @@ void Compiler::fgWasmEhTransformTry(ArrayStack<BasicBlock*>* catchRetBlocks,
}
}

//-----------------------------------------------------------------------------
// fgWasmProfInstrument: insert EventPipe CPU-sampling samplepoints
//
// Returns:
// suitable phase status
//
// Notes:
// Mirrors the interpreter's INTOP_PROF_SAMPLEPOINT placement (see
// src/coreclr/interpreter/compiler.cpp): one samplepoint at method entry and
// one on every loop back-edge. Emitted only for methods matching the
// WasmPerformanceInstrumentation MethodSet filter (same key the interpreter
// uses, so both engines share the filter and the runtime skip counter).
//
// Each samplepoint is a call to CORINFO_HELP_WASM_PROF_SAMPLEPOINT. The later
// fgWasmVirtualIP phase inserts its per-block Virtual IP store ahead of the
// samplepoint, giving the cooperative stack walk a correct Virtual IP.
//
PhaseStatus Compiler::fgWasmProfInstrument()
{
// Codegen only supports single-threaded wasm today; the shared runtime skip
// counter and cooperative sampling both assume PERFTRACING_DISABLE_THREADS.
assert(!WASM_THREAD_SUPPORT);

if (!JitConfig.WasmPerformanceInstrumentation().contains(info.compMethodHnd, info.compClassHnd,
&info.compMethodInfo->args))
{
return PhaseStatus::MODIFIED_NOTHING;
}

auto insertSamplepoint = [this](BasicBlock* block) {
GenTree* samplepoint = gtNewHelperCallNode(CORINFO_HELP_WASM_PROF_SAMPLEPOINT, TYP_VOID);
samplepoint = fgMorphCall(samplepoint->AsCall());
gtSetEvalOrder(samplepoint);
LIR::AsRange(block).InsertAtBeginning(LIR::SeqTree(this, samplepoint));

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.

For methods compiled with opts.IsReversePInvoke() ([UnmanagedCallersOnly]), fgAddReversePInvokeEnterExit has already placed the CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER call at the start of fgFirstBB during fgAddInternal. So InsertAtBeginning here puts the entry samplepoint before the transition to cooperative mode.

When a sampling session is active, JIT_WasmProfSamplepoint would then push an InlinedCallFrame and call SamplingProfiler_OnSamplepoint (which is MODE_COOPERATIVE) while the thread is still preemptive.

Would it make sense to insert the entry samplepoint after the reverse P/Invoke enter call, or simply skip the entry samplepoint for reverse P/Invoke methods? (I found this by reading the code; I haven't reproduced it.)

Note

This comment was generated with GitHub Copilot assistance.

};

unsigned samplepointsAdded = 0;

// A DFS back edge identifies its ancestor target as a loop header. Sample at
// every unique loop header, including loops formed through EH flow.
// Unlike fgHasCycleWithoutGCSafePoint we do NOT skip BBF_GC_SAFE_POINT blocks:
// the framework is not instrumented, so a loop calling only BCL methods would
// otherwise never sample.
FlowGraphDfsTree* const dfsTree = fgComputeDfs();
BitVecTraits traits = dfsTree->PostOrderTraits();
BitVec samplepointBlocks(BitVecOps::MakeEmpty(&traits));

// Method entry.
BitVecOps::AddElemD(&traits, samplepointBlocks, fgFirstBB->bbPostorderNum);

for (unsigned i = 0; i < dfsTree->GetPostOrderCount(); i++)
{
BasicBlock* const source = dfsTree->GetPostOrder(i);
source->VisitAllSuccs(this, [&](BasicBlock* target) {

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.

VisitAllSuccs also follows the modeled two-pass EH edges (VisitEHEnclosedHandlerSecondPassSuccs in compiler.hpp), which can form cycles that aren't real loops. For example, with a try/finally (e.g. using) nested inside a try { } catch when (...): the inner finally's blocks have an EH successor edge to the outer filter, and the filter has a second-pass edge back to the inner finally's entry.

Depending on the DFS order, either the filter entry or the finally entry becomes a "back-edge target". If it's the filter entry, InsertAtBeginning puts the samplepoint ahead of GT_CATCH_ARG, which needs to stay first (see LIR::Range::FirstNonCatchArgNode). Either way, a non-loop funclet ends up with a samplepoint and an unwindable frame.

Would walking the wasm control-flow graph instead (FgWasm::WasmDfs / WasmSuccessorEnumerator, as fgWasmTransformSccs does) work here? It should still catch loops formed through catch resumption, since those are explicit edges by this point. At minimum, inserting after FirstNonCatchArgNode() would avoid the GT_CATCH_ARG ordering problem. (I found this by reading the code; I haven't reproduced it.)

Note

This comment was generated with GitHub Copilot assistance.

assert(dfsTree->Contains(target));
if (dfsTree->IsAncestor(target, source))
{
BitVecOps::AddElemD(&traits, samplepointBlocks, target->bbPostorderNum);
}

return BasicBlockVisit::Continue;
});
}

BitVecOps::VisitBits(&traits, samplepointBlocks, [&](unsigned postorderNum) {
insertSamplepoint(dfsTree->GetPostOrder(postorderNum));
samplepointsAdded++;
return true;
});

JITDUMP("Added %u Wasm profiler samplepoint(s)\n", samplepointsAdded);
return (samplepointsAdded > 0) ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING;
}
Comment thread
pavelsavara marked this conversation as resolved.

//-----------------------------------------------------------------------------
// fgWasmVirtualIP: set up virtual IP mapping for EH and calls
//
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,9 @@ CONFIG_INTEGER(JitDispIns, "JitDispIns", 0)
CONFIG_STRING(JitR2RUnsupportedRange, "JitR2RUnsupportedRange")
// Enable processing methods with funclets. Set to 0 to bail to R2R unsupported before codegen.
RELEASE_CONFIG_INTEGER(JitWasmFunclets, "JitWasmFunclets", 1)
// Method filter for WASM performance instrumentation profiler. Uses standard MethodSet pattern format.
// Same key as the interpreter's InterpConfig.WasmPerformanceInstrumentation so both engines share it.
RELEASE_CONFIG_METHODSET(WasmPerformanceInstrumentation, "WasmPerformanceInstrumentation")
#endif // defined(TARGET_WASM)

// Allow to enregister locals with struct type.
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,11 @@ void HelperCallProperties::init()
exceptions = ExceptionSetFlags::None;
break;

case CORINFO_HELP_WASM_PROF_SAMPLEPOINT:
isNoGC = true;
exceptions = ExceptionSetFlags::None;
break;

case CORINFO_HELP_TAILCALL: // Never present on stack at the time of GC.
case CORINFO_HELP_STACK_PROBE:
case CORINFO_HELP_CHECK_OBJ:
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct ReadyToRunHeaderConstants
static const uint32_t Signature = 0x00525452; // 'RTR'

static const uint32_t CurrentMajorVersion = 32;
static const uint32_t CurrentMinorVersion = 0;
static const uint32_t CurrentMinorVersion = 1;
};

struct ReadyToRunHeader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal struct ReadyToRunHeaderConstants
public const uint Signature = 0x00525452; // 'RTR'

public const ushort CurrentMajorVersion = 32;
public const ushort CurrentMinorVersion = 0;
public const ushort CurrentMinorVersion = 1;
}
#if READYTORUN
#pragma warning disable 0169
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ public enum ReadyToRunHelper
InitClass = 0x116,
InitInstClass = 0x117,
R2RToInterpreter = 0x118,
WasmProfSamplepoint = 0x119,

// **********************************************************************************************
//
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ which is the right helper to use to allocate an object of a given type. */
CORINFO_HELP_ALLOC_CONTINUATION_METHOD,
CORINFO_HELP_ALLOC_CONTINUATION_CLASS,

CORINFO_HELP_WASM_PROF_SAMPLEPOINT, // WASM only: cooperative EventPipe CPU-sampling samplepoint

CORINFO_HELP_COUNT,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,10 @@ private ISymbolNode GetHelperFtnUncached(CorInfoHelpFunc ftnNum, out MethodDesc
id = ReadyToRunHelper.GCPoll;
break;

case CorInfoHelpFunc.CORINFO_HELP_WASM_PROF_SAMPLEPOINT:
id = ReadyToRunHelper.WasmProfSamplepoint;
break;

case CorInfoHelpFunc.CORINFO_HELP_GETCURRENTMANAGEDTHREADID:
id = ReadyToRunHelper.GetCurrentManagedThreadId;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1814,6 +1814,10 @@ private void ParseHelper(StringBuilder builder)
builder.Append("GCPOLL");
break;

case ReadyToRunHelper.WasmProfSamplepoint:
builder.Append("WASM_PROF_SAMPLEPOINT");
break;

case ReadyToRunHelper.GetCurrentManagedThreadId:
builder.Append("GET_CURRENT_MANAGED_THREAD_ID");
break;
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/ceeload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName)
m_pNativeImage = NULL;
if ((m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker)) != NULL)
{
#ifdef TARGET_WASM
// Direct R2R calls can execute before assembly activation. Register virtual IPs as soon as
// the R2R info is installed so stack walks can resolve those frames.
m_pReadyToRunInfo->RegisterVirtualIPRange(this);
#endif
if (m_pReadyToRunInfo->SkipTypeValidation())
m_dwPersistedFlags = m_dwPersistedFlags | SKIP_TYPE_VALIDATION; // Skip type validation on System

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ void ep_rt_coreclr_sample_profiler_disabled(void)
s_skipsPerPeriod = 1;
}

// True only while an EventPipe CPU-sampling session is active. R2R samplepoints use this to
// skip the InlinedCallFrame anchor push on the overwhelmingly common no-session path.
extern "C" bool SamplingProfiler_IsActive()
{
LIMITED_METHOD_CONTRACT;
return s_currentSamplingEvent != nullptr && s_currentSamplingThread != nullptr;
}

// Called from the interpreter's INTOP_PROF_SAMPLEPOINT handler.
// On single-threaded WASM this is the cooperative sampling entry point.
// On multi-threaded platforms the opcode is never emitted.
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ EXTERN_C FCDECL1(PCODE, JIT_PatchpointForced, int ilOffset);

EXTERN_C FCDECL0(void, JIT_PollGC);

#ifdef TARGET_WASM
// WASM EventPipe CPU-sampling samplepoint helper (defined in vm/wasm/helpers.cpp).
EXTERN_C void JIT_WasmProfSamplepoint(uintptr_t callersStackPointer, PCODE portableEntryPointContext);
#endif // TARGET_WASM

#ifndef JIT_GetGCStaticBaseNoCtor
#define JIT_GetGCStaticBaseNoCtor JIT_GetGCStaticBaseNoCtor_Portable
#endif
Expand Down
39 changes: 39 additions & 0 deletions src/coreclr/vm/wasm/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,45 @@ EXTERN_C __attribute__((naked)) void F_CALL_CONV JIT_PollGC(uintptr_t callersSta
[JIT_PollGCRarePath] "i" (JIT_PollGCRarePath));
}

// EventPipe CPU-sampling samplepoint helper for R2R (native wasm) code on single-threaded WASM.
// Emitted by the JIT at method entry and loop back-edges when a method matches the
// WasmPerformanceInstrumentation filter. Cooperative throughout; on an active sampling session it
// anchors a managed stack walk with an InlinedCallFrame derived from the caller's shadow SP, then
// delegates to the shared SamplingProfiler_OnSamplepoint (which owns the adaptive skip counter).
#if defined(FEATURE_PERFTRACING) && defined(PERFTRACING_DISABLE_THREADS)
EXTERN_C bool SamplingProfiler_IsActive();
EXTERN_C void SamplingProfiler_OnSamplepoint();
#endif

HCIMPL0(void, JIT_WasmProfSamplepoint)
{
FCALL_CONTRACT;

#if defined(FEATURE_PERFTRACING) && defined(PERFTRACING_DISABLE_THREADS)
if (!SamplingProfiler_IsActive())
return;

Thread* pThread = GetThread();

// Anchor the walk with a cooperative InlinedCallFrame (JIT_PInvokeBeginImpl's setup minus the
// preemptive transition): StackWalkFrames starts from a zeroed context and walks the Frame chain.
InlinedCallFrame inlinedCallFrame;
::new ((void*)&inlinedCallFrame) InlinedCallFrame();
inlinedCallFrame.m_pCallSiteSP = (void*)callersStackPointer;
inlinedCallFrame.m_pCallerReturnAddress = INLINED_PINVOKE_FROM_R2R;
inlinedCallFrame.m_pCalleeSavedFP = 0;
inlinedCallFrame.m_pThread = pThread;
inlinedCallFrame.Push();

SamplingProfiler_OnSamplepoint();

inlinedCallFrame.Pop();
#else
UNREFERENCED_PARAMETER(callersStackPointer);
#endif // FEATURE_PERFTRACING && PERFTRACING_DISABLE_THREADS
}
HCIMPLEND

void InitJITHelpers1()
{
/* no-op WASM-TODO do we need to do anything for the interpreter? */
Expand Down
Loading
Loading