Skip to content

Commit c91495e

Browse files
committed
Insert checks in a later phase
1 parent b51270d commit c91495e

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

src/coreclr/jit/compiler.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,6 +5026,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
50265026
compQuirkForPPPflag = compQuirkForPPP();
50275027
#endif
50285028

5029+
// Insert quick "is class statically initialized" checks in front of
5030+
// static init helper calls
5031+
DoPhase(this, PHASE_INSERT_STATINIT_CHECKS, &Compiler::fgInsertClsInitChecks);
5032+
50295033
// Insert GC Polls
50305034
DoPhase(this, PHASE_INSERT_GC_POLLS, &Compiler::fgInsertGCPolls);
50315035

src/coreclr/jit/compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5184,6 +5184,8 @@ class Compiler
51845184
PhaseStatus fgInsertGCPolls();
51855185
BasicBlock* fgCreateGCPoll(GCPollType pollType, BasicBlock* block);
51865186

5187+
PhaseStatus fgInsertClsInitChecks();
5188+
51875189
// Requires that "block" is a block that returns from
51885190
// a finally. Returns the number of successors (jump targets of
51895191
// of blocks in the covered "try" that did a "LEAVE".)

src/coreclr/jit/compphases.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop",
8989
#endif
9090
CompPhaseNameMacro(PHASE_OPT_UPDATE_FLOW_GRAPH, "Update flow graph opt pass", "UPD-FG-O", false, -1, false)
9191
CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)", "EDG-WGT2", false, -1, false)
92+
CompPhaseNameMacro(PHASE_INSERT_STATINIT_CHECKS, "Insert is-cls-stat-init Checks", "CLSSICHK", false, -1, true)
9293
CompPhaseNameMacro(PHASE_INSERT_GC_POLLS, "Insert GC Polls", "GC-POLLS", false, -1, true)
9394
CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true)
9495
CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false)

src/coreclr/jit/flowgraph.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,133 @@ static bool blockNeedsGCPoll(BasicBlock* block)
5252
return blockMayNeedGCPoll;
5353
}
5454

55+
//------------------------------------------------------------------------------
56+
// fgInsertClsInitChecks : Wraps static init helper calls with "is class statically initialized"
57+
// inlined checks.
58+
//
59+
// Returns:
60+
// PhaseStatus indicating what, if anything, was changed.
61+
//
62+
63+
PhaseStatus Compiler::fgInsertClsInitChecks()
64+
{
65+
66+
if (!strcmp(info.compMethodName, "Test"))
67+
{
68+
fgDispBasicBlocks(true);
69+
}
70+
71+
if (!opts.OptimizationEnabled())
72+
{
73+
return PhaseStatus::MODIFIED_NOTHING;
74+
}
75+
76+
bool modified = false;
77+
BasicBlock* block;
78+
for (block = fgFirstBB; block; block = block->bbNext)
79+
{
80+
if (!block->isRunRarely() && block->bbFlags)
81+
{
82+
for (Statement* stmt : block->Statements())
83+
{
84+
for (GenTree* tree = stmt->GetTreeList(); tree != nullptr; tree = tree->gtNext)
85+
{
86+
if (!tree->IsCall())
87+
{
88+
continue;
89+
}
90+
91+
GenTreeCall* call = tree->AsCall();
92+
if (call->gtCallType != CT_HELPER)
93+
{
94+
continue;
95+
}
96+
97+
CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
98+
if (helpFunc != CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE)
99+
{
100+
continue;
101+
}
102+
103+
GenTree* moduleIdArg = call->LateArgs().begin()->GetNode();
104+
GenTree* clsIdArg = call->LateArgs().begin()->GetNext()->GetNode();
105+
106+
if (!moduleIdArg->IsCnsIntOrI() || !clsIdArg->IsCnsIntOrI())
107+
{
108+
// Looks like moduleId or/and clsId were passed as indirect loads
109+
continue;
110+
}
111+
112+
//
113+
// * JTRUE void
114+
// \--* NE int
115+
// +--* AND int
116+
// | +--* IND ubyte
117+
// | | \--* CNS_INT long moduleIdArg + clsIdArg + dataBlobOffset
118+
// | \--* CNS_INT int isInitMask
119+
// \--* CNS_INT int 0
120+
//
121+
// * CALL help long HELPER.CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
122+
// +--* CNS_INT long moduleIdArg
123+
// \--* CNS_INT int clsIdArg
124+
//
125+
126+
BasicBlock* callInitBb = fgNewBBbefore(BBJ_NONE, block, true);
127+
fgAddRefPred(block, callInitBb);
128+
callInitBb->bbSetRunRarely();
129+
callInitBb->bbFlags |= block->bbFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_HAS_CALL);
130+
131+
GenTree* clonedHelperCall = gtCloneExprCallHelper(call);
132+
clonedHelperCall->gtFlags |= call->gtFlags;
133+
fgInsertStmtAtEnd(callInitBb, fgNewStmtFromTree(clonedHelperCall));
134+
135+
BasicBlock* isInitedBb = fgNewBBbefore(BBJ_COND, callInitBb, true);
136+
fgAddRefPred(callInitBb, isInitedBb);
137+
fgAddRefPred(block, isInitedBb);
138+
isInitedBb->inheritWeight(block);
139+
isInitedBb->bbFlags |= block->bbFlags & (BBF_SPLIT_GAINED | BBF_IMPORTED | BBF_HAS_CALL);
140+
141+
// TODO: ask VM for these constants:
142+
const int dataBlobOffset = 48;
143+
const int isInitMask = 1;
144+
145+
size_t address = moduleIdArg->AsIntCon()->IconValue() + dataBlobOffset + clsIdArg->AsIntCon()->IconValue();
146+
GenTree* indir = gtNewIndir(TYP_UBYTE, gtNewIconNode(address, TYP_I_IMPL));
147+
indir->gtFlags = (GTF_IND_NONFAULTING | GTF_IND_INVARIANT);
148+
149+
GenTree* isInitedMask = gtNewOperNode(GT_AND, TYP_INT, indir, gtNewIconNode(isInitMask));
150+
GenTree* isInitedCmp = gtNewOperNode(GT_NE, TYP_INT, isInitedMask, gtNewIconNode(0));
151+
152+
fgInsertStmtAtEnd(isInitedBb, fgNewStmtFromTree(gtNewOperNode(GT_JTRUE, TYP_VOID, isInitedCmp)));
153+
isInitedBb->bbJumpDest = block;
154+
gtReplaceTree(stmt, call, gtNewNothingNode());
155+
156+
157+
modified = true;
158+
}
159+
if (modified)
160+
{
161+
// clear GTF_CALL and GTF_EXC flags
162+
gtUpdateStmtSideEffects(stmt);
163+
}
164+
}
165+
}
166+
}
167+
168+
if (!strcmp(info.compMethodName, "Test"))
169+
{
170+
fgDispBasicBlocks(true);
171+
}
172+
173+
if (modified)
174+
{
175+
fgReorderBlocks();
176+
fgUpdateChangedFlowGraph(false);
177+
return PhaseStatus::MODIFIED_EVERYTHING;
178+
}
179+
return PhaseStatus::MODIFIED_NOTHING;
180+
}
181+
55182
//------------------------------------------------------------------------------
56183
// fgInsertGCPolls : Insert GC polls for basic blocks containing calls to methods
57184
// with SuppressGCTransitionAttribute.

0 commit comments

Comments
 (0)