Skip to content

[main] Source code updates from dotnet/runtime #1495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 15, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
[runtime] Source update 9c0555e → ede442a
  • Loading branch information
dotnet-maestro[bot] committed Jul 15, 2025
commit b8d5ef7de1ab5fdcb774d70a6073f1fdf98392e5
14 changes: 7 additions & 7 deletions src/runtime/docs/area-owners.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions src/runtime/src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1712,6 +1712,15 @@ enum CorInfoContinuationFlags
// OSR method saved in the beginning of 'Data', or -1 if the continuation
// belongs to a tier 0 method.
CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA = 4,
// If this bit is set the continuation should continue on the thread
// pool.
CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL = 8,
// If this bit is set the continuation has a SynchronizationContext
// that we should continue on.
CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_SYNCHRONIZATION_CONTEXT = 16,
// If this bit is set the continuation has a TaskScheduler
// that we should continue on.
CORINFO_CONTINUATION_CONTINUE_ON_CAPTURED_TASK_SCHEDULER = 32,
};

struct CORINFO_ASYNC_INFO
Expand All @@ -1737,6 +1746,7 @@ struct CORINFO_ASYNC_INFO
CORINFO_METHOD_HANDLE captureExecutionContextMethHnd;
// Method handle for AsyncHelpers.RestoreExecutionContext
CORINFO_METHOD_HANDLE restoreExecutionContextMethHnd;
CORINFO_METHOD_HANDLE captureContinuationContextMethHnd;
};

// Flags passed from JIT to runtime.
Expand Down
57 changes: 56 additions & 1 deletion src/runtime/src/coreclr/jit/async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,13 @@ ContinuationLayout AsyncTransformation::LayOutContinuation(BasicBlock*
block->getTryIndex(), layout.ExceptionGCDataIndex);
}

if (call->GetAsyncInfo().ContinuationContextHandling == ContinuationContextHandling::ContinueOnCapturedContext)
{
layout.ContinuationContextGCDataIndex = layout.GCRefsCount++;
JITDUMP(" Continuation continues on captured context; context will be at GC@+%02u in GC data\n",
layout.ContinuationContextGCDataIndex);
}

if (call->GetAsyncInfo().ExecutionContextHandling == ExecutionContextHandling::AsyncSaveAndRestore)
{
layout.ExecContextGCDataIndex = layout.GCRefsCount++;
Expand Down Expand Up @@ -1200,13 +1207,16 @@ BasicBlock* AsyncTransformation::CreateSuspension(
LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_comp, storeState));

// Fill in 'flags'
unsigned continuationFlags = 0;
const AsyncCallInfo& callInfo = call->GetAsyncInfo();
unsigned continuationFlags = 0;
if (layout.ReturnInGCData)
continuationFlags |= CORINFO_CONTINUATION_RESULT_IN_GCDATA;
if (block->hasTryIndex())
continuationFlags |= CORINFO_CONTINUATION_NEEDS_EXCEPTION;
if (m_comp->doesMethodHavePatchpoints() || m_comp->opts.IsOSR())
continuationFlags |= CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA;
if (callInfo.ContinuationContextHandling == ContinuationContextHandling::ContinueOnThreadPool)
continuationFlags |= CORINFO_CONTINUATION_CONTINUE_ON_THREAD_POOL;

newContinuation = m_comp->gtNewLclvNode(m_newContinuationVar, TYP_REF);
unsigned flagsOffset = m_comp->info.compCompHnd->getFieldOffset(m_asyncInfo->continuationFlagsFldHnd);
Expand Down Expand Up @@ -1386,6 +1396,51 @@ void AsyncTransformation::FillInGCPointersOnSuspension(const ContinuationLayout&
}
}

if (layout.ContinuationContextGCDataIndex != UINT_MAX)
{
// Insert call AsyncHelpers.CaptureContinuationContext(ref
// newContinuation.GCData[ContinuationContextGCDataIndex], ref newContinuation.Flags).
GenTree* contextElementPlaceholder = m_comp->gtNewZeroConNode(TYP_BYREF);
GenTree* flagsPlaceholder = m_comp->gtNewZeroConNode(TYP_BYREF);
GenTreeCall* captureCall =
m_comp->gtNewCallNode(CT_USER_FUNC, m_asyncInfo->captureContinuationContextMethHnd, TYP_VOID);

captureCall->gtArgs.PushFront(m_comp, NewCallArg::Primitive(flagsPlaceholder));
captureCall->gtArgs.PushFront(m_comp, NewCallArg::Primitive(contextElementPlaceholder));

m_comp->compCurBB = suspendBB;
m_comp->fgMorphTree(captureCall);

LIR::AsRange(suspendBB).InsertAtEnd(LIR::SeqTree(m_comp, captureCall));

// Now replace contextElementPlaceholder with actual address of the context element
LIR::Use use;
bool gotUse = LIR::AsRange(suspendBB).TryGetUse(contextElementPlaceholder, &use);
assert(gotUse);

GenTree* objectArr = m_comp->gtNewLclvNode(objectArrLclNum, TYP_REF);
unsigned offset = OFFSETOF__CORINFO_Array__data + (layout.ContinuationContextGCDataIndex * TARGET_POINTER_SIZE);
GenTree* contextElementOffset =
m_comp->gtNewOperNode(GT_ADD, TYP_BYREF, objectArr, m_comp->gtNewIconNode((ssize_t)offset, TYP_I_IMPL));

LIR::AsRange(suspendBB).InsertBefore(contextElementPlaceholder, LIR::SeqTree(m_comp, contextElementOffset));
use.ReplaceWith(contextElementOffset);
LIR::AsRange(suspendBB).Remove(contextElementPlaceholder);

// And now replace flagsPlaceholder with actual address of the flags
gotUse = LIR::AsRange(suspendBB).TryGetUse(flagsPlaceholder, &use);
assert(gotUse);

newContinuation = m_comp->gtNewLclvNode(m_newContinuationVar, TYP_REF);
unsigned flagsOffset = m_comp->info.compCompHnd->getFieldOffset(m_asyncInfo->continuationFlagsFldHnd);
GenTree* flagsOffsetNode = m_comp->gtNewOperNode(GT_ADD, TYP_BYREF, newContinuation,
m_comp->gtNewIconNode((ssize_t)flagsOffset, TYP_I_IMPL));

LIR::AsRange(suspendBB).InsertBefore(flagsPlaceholder, LIR::SeqTree(m_comp, flagsOffsetNode));
use.ReplaceWith(flagsOffsetNode);
LIR::AsRange(suspendBB).Remove(flagsPlaceholder);
}

if (layout.ExecContextGCDataIndex != UINT_MAX)
{
GenTreeCall* captureExecContext =
Expand Down
17 changes: 9 additions & 8 deletions src/runtime/src/coreclr/jit/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ struct LiveLocalInfo

struct ContinuationLayout
{
unsigned DataSize = 0;
unsigned GCRefsCount = 0;
ClassLayout* ReturnStructLayout = nullptr;
unsigned ReturnSize = 0;
bool ReturnInGCData = false;
unsigned ReturnValDataOffset = UINT_MAX;
unsigned ExceptionGCDataIndex = UINT_MAX;
unsigned ExecContextGCDataIndex = UINT_MAX;
unsigned DataSize = 0;
unsigned GCRefsCount = 0;
ClassLayout* ReturnStructLayout = nullptr;
unsigned ReturnSize = 0;
bool ReturnInGCData = false;
unsigned ReturnValDataOffset = UINT_MAX;
unsigned ExceptionGCDataIndex = UINT_MAX;
unsigned ExecContextGCDataIndex = UINT_MAX;
unsigned ContinuationContextGCDataIndex = UINT_MAX;
const jitstd::vector<LiveLocalInfo>& Locals;

explicit ContinuationLayout(const jitstd::vector<LiveLocalInfo>& locals)
Expand Down
3 changes: 0 additions & 3 deletions src/runtime/src/coreclr/jit/block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,8 @@ void BasicBlock::dspFlags() const
{BBF_HAS_CALL, "hascall"},
{BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY, "xentry"},
{BBF_GC_SAFE_POINT, "gcsafe"},
{BBF_HAS_IDX_LEN, "idxlen"},
{BBF_HAS_MD_IDX_LEN, "mdidxlen"},
{BBF_HAS_NEWOBJ, "newobj"},
{BBF_HAS_NEWARR, "newarr"},
{BBF_HAS_NULLCHECK, "nullcheck"},
{BBF_BACKWARD_JUMP, "bwd"},
{BBF_BACKWARD_JUMP_TARGET, "bwd-target"},
{BBF_BACKWARD_JUMP_SOURCE, "bwd-src"},
Expand Down
75 changes: 36 additions & 39 deletions src/runtime/src/coreclr/jit/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,48 +428,45 @@ enum BasicBlockFlags : uint64_t
BBF_NEEDS_GCPOLL = MAKE_BBFLAG( 6), // BB may need a GC poll because it uses the slow tail call helper
BBF_CLONED_FINALLY_BEGIN = MAKE_BBFLAG( 7), // First block of a cloned finally region
BBF_CLONED_FINALLY_END = MAKE_BBFLAG( 8), // Last block of a cloned finally region
BBF_HAS_NULLCHECK = MAKE_BBFLAG( 9), // BB contains a null check
BBF_HAS_SUPPRESSGC_CALL = MAKE_BBFLAG(10), // BB contains a call to a method with SuppressGCTransitionAttribute
BBF_RUN_RARELY = MAKE_BBFLAG(11), // BB is rarely run (catch clauses, blocks with throws etc)
BBF_HAS_LABEL = MAKE_BBFLAG(12), // BB needs a label
BBF_LOOP_ALIGN = MAKE_BBFLAG(13), // Block is lexically the first block in a loop we intend to align.
BBF_HAS_ALIGN = MAKE_BBFLAG(14), // BB ends with 'align' instruction
BBF_HAS_JMP = MAKE_BBFLAG(15), // BB executes a JMP instruction (instead of return)
BBF_GC_SAFE_POINT = MAKE_BBFLAG(16), // BB has a GC safe point (e.g. a call)
BBF_HAS_IDX_LEN = MAKE_BBFLAG(17), // BB contains simple index or length expressions on an SD array local var.
BBF_HAS_MD_IDX_LEN = MAKE_BBFLAG(18), // BB contains simple index, length, or lower bound expressions on an MD array local var.
BBF_HAS_MDARRAYREF = MAKE_BBFLAG(19), // Block has a multi-dimensional array reference
BBF_HAS_NEWOBJ = MAKE_BBFLAG(20), // BB contains 'new' of an object type.

BBF_RETLESS_CALL = MAKE_BBFLAG(21), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired
BBF_HAS_SUPPRESSGC_CALL = MAKE_BBFLAG( 9), // BB contains a call to a method with SuppressGCTransitionAttribute
BBF_RUN_RARELY = MAKE_BBFLAG(10), // BB is rarely run (catch clauses, blocks with throws etc)
BBF_HAS_LABEL = MAKE_BBFLAG(11), // BB needs a label
BBF_LOOP_ALIGN = MAKE_BBFLAG(12), // Block is lexically the first block in a loop we intend to align.
BBF_HAS_ALIGN = MAKE_BBFLAG(13), // BB ends with 'align' instruction
BBF_HAS_JMP = MAKE_BBFLAG(14), // BB executes a JMP instruction (instead of return)
BBF_GC_SAFE_POINT = MAKE_BBFLAG(15), // BB has a GC safe point (e.g. a call)
BBF_HAS_MDARRAYREF = MAKE_BBFLAG(16), // Block has a multi-dimensional array reference
BBF_HAS_NEWOBJ = MAKE_BBFLAG(17), // BB contains 'new' of an object type.

BBF_RETLESS_CALL = MAKE_BBFLAG(18), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired
// BBJ_CALLFINALLYRET); see isBBCallFinallyPair().
BBF_COLD = MAKE_BBFLAG(22), // BB is cold
BBF_PROF_WEIGHT = MAKE_BBFLAG(23), // BB weight is computed from profile data
BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(24), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind
BBF_COLD = MAKE_BBFLAG(19), // BB is cold
BBF_PROF_WEIGHT = MAKE_BBFLAG(20), // BB weight is computed from profile data
BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(21), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind
// as BBJ_ALWAYS. Used on x86 for the final step block out of a finally.
BBF_HAS_CALL = MAKE_BBFLAG(25), // BB contains a call
BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY = MAKE_BBFLAG(26), // Block is dominated by exceptional entry.
BBF_BACKWARD_JUMP = MAKE_BBFLAG(27), // BB is surrounded by a backward jump/switch arc
BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(28), // Block is a source of a backward jump
BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(29), // Block is a target of a backward jump
BBF_PATCHPOINT = MAKE_BBFLAG(30), // Block is a patchpoint
BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(31), // Block is a partial compilation patchpoint
BBF_HAS_HISTOGRAM_PROFILE = MAKE_BBFLAG(32), // BB contains a call needing a histogram profile
BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(33), // BB has pred that has potential tail call
BBF_RECURSIVE_TAILCALL = MAKE_BBFLAG(34), // Block has recursive tailcall that may turn into a loop
BBF_NO_CSE_IN = MAKE_BBFLAG(35), // Block should kill off any incoming CSE
BBF_CAN_ADD_PRED = MAKE_BBFLAG(36), // Ok to add pred edge to this block, even when "safe" edge creation disabled
BBF_HAS_VALUE_PROFILE = MAKE_BBFLAG(37), // Block has a node that needs a value probing
BBF_HAS_NEWARR = MAKE_BBFLAG(38), // BB contains 'new' of an array type.
BBF_MAY_HAVE_BOUNDS_CHECKS = MAKE_BBFLAG(39), // BB *likely* has a bounds check (after rangecheck phase).
BBF_ASYNC_RESUMPTION = MAKE_BBFLAG(40), // Block is a resumption block in an async method
BBF_HAS_CALL = MAKE_BBFLAG(22), // BB contains a call
BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY = MAKE_BBFLAG(23), // Block is dominated by exceptional entry.
BBF_BACKWARD_JUMP = MAKE_BBFLAG(24), // BB is surrounded by a backward jump/switch arc
BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(25), // Block is a source of a backward jump
BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(26), // Block is a target of a backward jump
BBF_PATCHPOINT = MAKE_BBFLAG(27), // Block is a patchpoint
BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(28), // Block is a partial compilation patchpoint
BBF_HAS_HISTOGRAM_PROFILE = MAKE_BBFLAG(29), // BB contains a call needing a histogram profile
BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(30), // BB has pred that has potential tail call
BBF_RECURSIVE_TAILCALL = MAKE_BBFLAG(31), // Block has recursive tailcall that may turn into a loop
BBF_NO_CSE_IN = MAKE_BBFLAG(32), // Block should kill off any incoming CSE
BBF_CAN_ADD_PRED = MAKE_BBFLAG(33), // Ok to add pred edge to this block, even when "safe" edge creation disabled
BBF_HAS_VALUE_PROFILE = MAKE_BBFLAG(34), // Block has a node that needs a value probing
BBF_HAS_NEWARR = MAKE_BBFLAG(35), // BB contains 'new' of an array type.
BBF_MAY_HAVE_BOUNDS_CHECKS = MAKE_BBFLAG(36), // BB *likely* has a bounds check (after rangecheck phase).
BBF_ASYNC_RESUMPTION = MAKE_BBFLAG(37), // Block is a resumption block in an async method

// The following are sets of flags.

// Flags to update when two blocks are compacted

BBF_COMPACT_UPD = BBF_GC_SAFE_POINT | BBF_NEEDS_GCPOLL | BBF_HAS_JMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_BACKWARD_JUMP | \
BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS,
BBF_COMPACT_UPD = BBF_GC_SAFE_POINT | BBF_NEEDS_GCPOLL | BBF_HAS_JMP | BBF_BACKWARD_JUMP | \
BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS,

// Flags a block should not have had before it is split.

Expand All @@ -484,18 +481,18 @@ enum BasicBlockFlags : uint64_t

// Flags gained by the bottom block when a block is split.
// Note, this is a conservative guess.
// For example, the bottom block might or might not have BBF_HAS_NULLCHECK, but we assume it has BBF_HAS_NULLCHECK.
// For example, the bottom block might or might not have BBF_HAS_NEWARR, but we assume it has BBF_HAS_NEWARR.
// TODO: Should BBF_RUN_RARELY be added to BBF_SPLIT_GAINED ?

BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_PROF_WEIGHT | BBF_HAS_NEWARR | \
BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL | BBF_MAY_HAVE_BOUNDS_CHECKS | BBF_ASYNC_RESUMPTION,
BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_PROF_WEIGHT | BBF_HAS_NEWARR | \
BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_HISTOGRAM_PROFILE | BBF_HAS_VALUE_PROFILE | BBF_HAS_MDARRAYREF | BBF_NEEDS_GCPOLL | BBF_MAY_HAVE_BOUNDS_CHECKS | BBF_ASYNC_RESUMPTION,

// Flags that must be propagated to a new block if code is copied from a block to a new block. These are flags that
// limit processing of a block if the code in question doesn't exist. This is conservative; we might not
// have actually copied one of these type of tree nodes, but if we only copy a portion of the block's statements,
// we don't know (unless we actually pay close attention during the copy).

BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_NULLCHECK | BBF_HAS_IDX_LEN | BBF_HAS_MD_IDX_LEN | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS,
BBF_COPY_PROPAGATE = BBF_HAS_NEWOBJ | BBF_HAS_NEWARR | BBF_HAS_MDARRAYREF | BBF_MAY_HAVE_BOUNDS_CHECKS,
};

FORCEINLINE
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ bool CodeGen::genInstrWithConstant(
{
case INS_add:
case INS_sub:
if (imm < 0)
{
imm = -imm;
ins = (ins == INS_add) ? INS_sub : INS_add;
}
immFitsInIns = validImmForInstr(ins, (target_ssize_t)imm, flags);
break;

Expand Down
4 changes: 1 addition & 3 deletions src/runtime/src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10506,20 +10506,18 @@ var_types Compiler::gtTypeForNullCheck(GenTree* tree)
//
// Arguments:
// tree - the node to change;
// block - basic block of the node.
//
// Notes:
// the function should not be called after lowering for platforms that do not support
// emitting NULLCHECK nodes, like arm32. Use `Lowering::TransformUnusedIndirection`
// that handles it and calls this function when appropriate.
//
void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block)
void Compiler::gtChangeOperToNullCheck(GenTree* tree)
{
assert(tree->OperIs(GT_IND, GT_BLK));
tree->ChangeOper(GT_NULLCHECK);
tree->ChangeType(gtTypeForNullCheck(tree));
tree->SetIndirExceptionFlags(this);
block->SetFlags(BBF_HAS_NULLCHECK);
optMethodFlags |= OMF_HAS_NULLCHECK;
}

Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy