Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9c6aaa5

Browse files
committed
Merge pull request #3044 from pgavlin/CoreRTPInvoke
Generate P/Invoke transitions for CoreRT.
2 parents 22be746 + 62bc76f commit 9c6aaa5

File tree

9 files changed

+276
-111
lines changed

9 files changed

+276
-111
lines changed

src/inc/corjit.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ enum CorJitFlag
8585
CORJIT_FLG_GCPOLL_CALLS = 0x00000040, // Emit calls to JIT_POLLGC for thread suspension.
8686
CORJIT_FLG_MCJIT_BACKGROUND = 0x00000080, // Calling from multicore JIT background thread, do not call JitComplete
8787

88-
#ifdef FEATURE_LEGACYNETCF
88+
#if defined(FEATURE_LEGACYNETCF)
8989

9090
CORJIT_FLG_NETCF_QUIRKS = 0x00000100, // Mimic .NetCF JIT's quirks for generated code (currently just inlining heuristics)
9191

@@ -121,27 +121,33 @@ enum CorJitFlag
121121

122122
#endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_)
123123

124-
#ifdef MDIL
124+
#if defined(MDIL)
125+
125126
CORJIT_FLG_MDIL = 0x00004000, // Generate MDIL code instead of machine code
126-
#else // MDIL
127-
CORJIT_FLG_CFI_UNWIND = 0x00004000, // Emit CFI unwind info
128-
#endif // MDIL
129127

130-
#ifdef MDIL
131128
// Safe to overlap with CORJIT_FLG_MAKEFINALCODE below. Not used by the JIT, used internally by NGen only.
132129
CORJIT_FLG_MINIMAL_MDIL = 0x00008000, // Generate MDIL code suitable for use to bind other assemblies.
133130

134131
// Safe to overlap with CORJIT_FLG_READYTORUN below. Not used by the JIT, used internally by NGen only.
135132
CORJIT_FLG_NO_MDIL = 0x00010000, // Generate an MDIL section but no code or CTL. Not used by the JIT, used internally by NGen only.
136-
#endif // MDIL
133+
134+
#else // defined(MDIL)
135+
136+
CORJIT_FLG_CFI_UNWIND = 0x00004000, // Emit CFI unwind info
137137

138138
#if defined(FEATURE_INTERPRETER)
139+
139140
CORJIT_FLG_MAKEFINALCODE = 0x00008000, // Use the final code generator, i.e., not the interpreter.
140-
#endif // FEATURE_INTERPRETER
141141

142-
#ifdef FEATURE_READYTORUN_COMPILER
142+
#endif // defined(FEATURE_INTERPRETER)
143+
144+
#if defined(FEATURE_READYTORUN_COMPILER)
145+
143146
CORJIT_FLG_READYTORUN = 0x00010000, // Use version-resilient code generation
144-
#endif
147+
148+
#endif // defined(FEATURE_READYTORUN_COMPILER)
149+
150+
#endif // !defined(MDIL)
145151

146152
CORJIT_FLG_PROF_ENTERLEAVE = 0x00020000, // Instrument prologues/epilogues
147153
CORJIT_FLG_PROF_REJIT_NOPS = 0x00040000, // Insert NOPs to ensure code is re-jitable

src/jit/codegencommon.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7558,6 +7558,7 @@ void CodeGen::genPrologPadForReJit()
75587558
regMaskTP CodeGen::genPInvokeMethodProlog(regMaskTP initRegs)
75597559
{
75607560
assert(compiler->compGeneratingProlog);
7561+
noway_assert(!compiler->opts.ShouldUsePInvokeHelpers());
75617562
noway_assert(compiler->info.compCallUnmanaged);
75627563

75637564
CORINFO_EE_INFO * pInfo = compiler->eeGetEEInfo();
@@ -7777,6 +7778,7 @@ regMaskTP CodeGen::genPInvokeMethodProlog(regMaskTP initRegs)
77777778
void CodeGen::genPInvokeMethodEpilog()
77787779
{
77797780
noway_assert(compiler->info.compCallUnmanaged);
7781+
noway_assert(!compiler->opts.ShouldUsePInvokeHelpers());
77807782
noway_assert(compiler->compCurBB == compiler->genReturnBB ||
77817783
(compiler->compTailCallUsed && (compiler->compCurBB->bbJumpKind == BBJ_THROW)) ||
77827784
(compiler->compJmpOpUsed && (compiler->compCurBB->bbFlags & BBF_HAS_JMP)));
@@ -8518,13 +8520,23 @@ void CodeGen::genFnProlog()
85188520
// since they are trashed by the jithelper call to setup the PINVOKE frame
85198521
if (compiler->info.compCallUnmanaged)
85208522
{
8521-
excludeMask |= (RBM_PINVOKE_FRAME | RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH);
8523+
excludeMask |= RBM_PINVOKE_FRAME;
85228524

8523-
// We also must exclude the register used by compLvFrameListRoot when it is enregistered
8524-
//
8525-
LclVarDsc * varDsc = &compiler->lvaTable[compiler->info.compLvFrameListRoot];
8526-
if (varDsc->lvRegister)
8527-
excludeMask |= genRegMask(varDsc->lvRegNum);
8525+
assert((!compiler->opts.ShouldUsePInvokeHelpers()) || (compiler->info.compLvFrameListRoot == BAD_VAR_NUM));
8526+
if (!compiler->opts.ShouldUsePInvokeHelpers())
8527+
{
8528+
noway_assert(compiler->info.compLvFrameListRoot < compiler->lvaCount);
8529+
8530+
excludeMask |= (RBM_PINVOKE_TCB | RBM_PINVOKE_SCRATCH);
8531+
8532+
// We also must exclude the register used by compLvFrameListRoot when it is enregistered
8533+
//
8534+
LclVarDsc * varDsc = &compiler->lvaTable[compiler->info.compLvFrameListRoot];
8535+
if (varDsc->lvRegister)
8536+
{
8537+
excludeMask |= genRegMask(varDsc->lvRegNum);
8538+
}
8539+
}
85288540
}
85298541
#endif // INLINE_NDIRECT
85308542

src/jit/compiler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7723,6 +7723,10 @@ public :
77237723
inline bool IsReadyToRun() { return false; }
77247724
#endif
77257725

7726+
// true if we should use the PINVOKE_{BEGIN,END} helpers instead of generating
7727+
// PInvoke transitions inline (e.g. when targeting CoreRT).
7728+
inline bool ShouldUsePInvokeHelpers() { return (jitFlags->corJitFlags2 & CORJIT_FLG2_USE_PINVOKE_HELPERS) != 0; }
7729+
77267730
// true if we must generate compatible code with Jit64 quirks
77277731
inline bool IsJit64Compat()
77287732
{

src/jit/flowgraph.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8215,7 +8215,12 @@ void Compiler::fgAddInternal()
82158215
#if INLINE_NDIRECT
82168216
if (info.compCallUnmanaged != 0)
82178217
{
8218-
info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8218+
// The P/Invoke helpers only require a frame variable, so only allocate the
8219+
// TCB variable if we're not using them.
8220+
if (!opts.ShouldUsePInvokeHelpers())
8221+
{
8222+
info.compLvFrameListRoot = lvaGrabTemp(false DEBUGARG("Pinvoke FrameListRoot"));
8223+
}
82198224

82208225
lvaInlinedPInvokeFrameVar = lvaGrabTempWithImplicitUse(false DEBUGARG("Pinvoke FrameVar"));
82218226

@@ -8226,8 +8231,9 @@ void Compiler::fgAddInternal()
82268231
varDsc->lvExactSize = eeGetEEInfo()->inlinedCallFrameInfo.size;
82278232
#if FEATURE_FIXED_OUT_ARGS
82288233
// Grab and reserve space for TCB, Frame regs used in PInvoke epilog to pop the inlined frame.
8229-
// See genPInvokeMethodEpilog() for use of the grabbed var.
8230-
if (compJmpOpUsed)
8234+
// See genPInvokeMethodEpilog() for use of the grabbed var. This is only necessary if we are
8235+
// not using the P/Invoke helpers.
8236+
if (!opts.ShouldUsePInvokeHelpers() && compJmpOpUsed)
82318237
{
82328238
lvaPInvokeFrameRegSaveVar = lvaGrabTempWithImplicitUse(false DEBUGARG("PInvokeFrameRegSave Var"));
82338239
varDsc = &lvaTable[lvaPInvokeFrameRegSaveVar];

src/jit/gentree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,7 @@ struct GenTreeLclVar: public GenTreeLclVarCommon
21072107
DEBUG_ARG(largeNode)),
21082108
gtLclILoffs(ilOffs)
21092109
{
2110-
assert(OperIsLocal(oper));
2110+
assert(OperIsLocal(oper) || OperIsLocalAddr(oper));
21112111
}
21122112

21132113
#if DEBUGGABLE_GENTREE

src/jit/lclvars.cpp

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,17 +2170,21 @@ void Compiler::lvaDecRefCnts(GenTreePtr tree)
21702170

21712171
if ((tree->gtOper == GT_CALL) && (tree->gtFlags & GTF_CALL_UNMANAGED))
21722172
{
2173-
/* Get the special variable descriptor */
2173+
assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
2174+
if (!opts.ShouldUsePInvokeHelpers())
2175+
{
2176+
/* Get the special variable descriptor */
21742177

2175-
lclNum = info.compLvFrameListRoot;
2176-
2177-
noway_assert(lclNum <= lvaCount);
2178-
varDsc = lvaTable + lclNum;
2179-
2180-
/* Decrement the reference counts twice */
2178+
lclNum = info.compLvFrameListRoot;
21812179

2182-
varDsc->decRefCnts(compCurBB->getBBWeight(this), this);
2183-
varDsc->decRefCnts(compCurBB->getBBWeight(this), this);
2180+
noway_assert(lclNum <= lvaCount);
2181+
varDsc = lvaTable + lclNum;
2182+
2183+
/* Decrement the reference counts twice */
2184+
2185+
varDsc->decRefCnts(compCurBB->getBBWeight(this), this);
2186+
varDsc->decRefCnts(compCurBB->getBBWeight(this), this);
2187+
}
21842188
}
21852189
else
21862190
{
@@ -2225,17 +2229,21 @@ void Compiler::lvaIncRefCnts(GenTreePtr tree)
22252229

22262230
if ((tree->gtOper == GT_CALL) && (tree->gtFlags & GTF_CALL_UNMANAGED))
22272231
{
2228-
/* Get the special variable descriptor */
2232+
assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
2233+
if (!opts.ShouldUsePInvokeHelpers())
2234+
{
2235+
/* Get the special variable descriptor */
22292236

2230-
lclNum = info.compLvFrameListRoot;
2231-
2232-
noway_assert(lclNum <= lvaCount);
2233-
varDsc = lvaTable + lclNum;
2234-
2235-
/* Increment the reference counts twice */
2237+
lclNum = info.compLvFrameListRoot;
22362238

2237-
varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
2238-
varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
2239+
noway_assert(lclNum <= lvaCount);
2240+
varDsc = lvaTable + lclNum;
2241+
2242+
/* Increment the reference counts twice */
2243+
2244+
varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
2245+
varDsc->incRefCnts(compCurBB->getBBWeight(this), this);
2246+
}
22392247
}
22402248
else
22412249
{
@@ -2811,16 +2819,20 @@ void Compiler::lvaMarkLclRefs(GenTreePtr tree)
28112819
/* Is this a call to unmanaged code ? */
28122820
if (tree->gtOper == GT_CALL && tree->gtFlags & GTF_CALL_UNMANAGED)
28132821
{
2814-
/* Get the special variable descriptor */
2822+
assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
2823+
if (!opts.ShouldUsePInvokeHelpers())
2824+
{
2825+
/* Get the special variable descriptor */
28152826

2816-
unsigned lclNum = info.compLvFrameListRoot;
2817-
2818-
noway_assert(lclNum <= lvaCount);
2819-
LclVarDsc * varDsc = lvaTable + lclNum;
2827+
unsigned lclNum = info.compLvFrameListRoot;
2828+
2829+
noway_assert(lclNum <= lvaCount);
2830+
LclVarDsc * varDsc = lvaTable + lclNum;
28202831

2821-
/* Increment the ref counts twice */
2822-
varDsc->incRefCnts(lvaMarkRefsWeight, this);
2823-
varDsc->incRefCnts(lvaMarkRefsWeight, this);
2832+
/* Increment the ref counts twice */
2833+
varDsc->incRefCnts(lvaMarkRefsWeight, this);
2834+
varDsc->incRefCnts(lvaMarkRefsWeight, this);
2835+
}
28242836
}
28252837
#endif
28262838

@@ -3177,15 +3189,19 @@ void Compiler::lvaMarkLocalVars()
31773189

31783190
if (info.compCallUnmanaged != 0)
31793191
{
3180-
noway_assert(info.compLvFrameListRoot >= info.compLocalsCount &&
3181-
info.compLvFrameListRoot < lvaCount);
3192+
assert((!opts.ShouldUsePInvokeHelpers()) || (info.compLvFrameListRoot == BAD_VAR_NUM));
3193+
if (!opts.ShouldUsePInvokeHelpers())
3194+
{
3195+
noway_assert(info.compLvFrameListRoot >= info.compLocalsCount &&
3196+
info.compLvFrameListRoot < lvaCount);
31823197

3183-
lvaTable[info.compLvFrameListRoot].lvType = TYP_I_IMPL;
3198+
lvaTable[info.compLvFrameListRoot].lvType = TYP_I_IMPL;
31843199

3185-
/* Set the refCnt, it is used in the prolog and return block(s) */
3200+
/* Set the refCnt, it is used in the prolog and return block(s) */
31863201

3187-
lvaTable[info.compLvFrameListRoot].lvRefCnt = 2;
3188-
lvaTable[info.compLvFrameListRoot].lvRefCntWtd = 2 * BB_UNITY_WEIGHT;
3202+
lvaTable[info.compLvFrameListRoot].lvRefCnt = 2;
3203+
lvaTable[info.compLvFrameListRoot].lvRefCntWtd = 2 * BB_UNITY_WEIGHT;
3204+
}
31893205
}
31903206
#endif
31913207

0 commit comments

Comments
 (0)