#if COR_JIT_EE_VERSION > 460
// Update this one
-SELECTANY const GUID JITEEVersionIdentifier = { /* f7be09f3-9ca7-42fd-b0ca-f97c0499f5a3 */
- 0xf7be09f3,
- 0x9ca7,
- 0x42fd,
- {0xb0, 0xca, 0xf9, 0x7c, 0x04, 0x99, 0xf5, 0xa3}
+SELECTANY const GUID JITEEVersionIdentifier = { /* b26841f8-74d6-4fc9-9d81-6500cd662549 */
+ 0xb26841f8,
+ 0x74d6,
+ 0x4fc9,
+ { 0x9d, 0x81, 0x65, 0x00, 0xcd, 0x66, 0x25, 0x49 }
};
#else
#if COR_JIT_EE_VERSION > 460
CORINFO_HELP_THROW_ARGUMENTEXCEPTION, // throw ArgumentException
CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, // throw ArgumentOutOfRangeException
+
+ CORINFO_HELP_JIT_PINVOKE_BEGIN, // Transition to preemptive mode before a P/Invoke, frame is the first argument
+ CORINFO_HELP_JIT_PINVOKE_END, // Transition to cooperative mode after a P/Invoke, frame is the first argument
#endif
CORINFO_HELP_COUNT,
CORINFO_METHOD_HANDLE context
) = 0;
+ // NOTE: the two methods below--getPInvokeUnmanagedTarget and getAddressOfPInvokeFixup--are
+ // deprecated. New code (i.e. anything that can depend on COR_JIT_EE_VERSION being
+ // greater than 460) should instead use getAddressOfPInvokeTarget, which subsumes the
+ // functionality of these methods.
+
// return the unmanaged target *if method has already been prelinked.*
virtual void* getPInvokeUnmanagedTarget(
CORINFO_METHOD_HANDLE method,
void **ppIndirection = NULL
) = 0;
+#if COR_JIT_EE_VERSION > 460
+ // return the address of the PInvoke target. May be a fixup area in the
+ // case of late-bound PInvoke calls.
+ virtual void getAddressOfPInvokeTarget(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_CONST_LOOKUP *pLookup
+ ) = 0;
+#endif
+
// Generate a cookie based on the signature that would needs to be passed
// to CORINFO_HELP_PINVOKE_CALLI
virtual LPVOID GetCookieForPInvokeCalliSig(
CORJIT_FLG_ALIGN_LOOPS = 0x20000000, // add NOPs before loops to align them at 16 byte boundaries
CORJIT_FLG_PUBLISH_SECRET_PARAM= 0x40000000, // JIT must place stub secret param into local 0. (used by IL stubs)
CORJIT_FLG_GCPOLL_INLINE = 0x80000000, // JIT must inline calls to GCPoll when possible
+
+#if COR_JIT_EE_VERSION > 460
+ CORJIT_FLG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a
+ // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags().
+#endif
};
enum CorJitFlag2
{
-#ifdef FEATURE_STACK_SAMPLING
- CORJIT_FLG2_SAMPLING_JIT_BACKGROUND
- = 0x00000001, // JIT is being invoked as a result of stack sampling for hot methods in the background
+ CORJIT_FLG2_SAMPLING_JIT_BACKGROUND = 0x00000001, // JIT is being invoked as a result of stack sampling for hot methods in the background
+#if COR_JIT_EE_VERSION > 460
+ CORJIT_FLG2_USE_PINVOKE_HELPERS = 0x00000002, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions
#endif
};
+struct CORJIT_FLAGS
+{
+ unsigned corJitFlags; // Values are from CorJitFlag
+ unsigned corJitFlags2; // Values are from CorJitFlag2
+};
+
/*****************************************************************************
Here is how CORJIT_FLG_SKIP_VERIFICATION should be interepreted.
Note that even if any method is inlined, it need not be verified.
// different value than if it was compiling for the host architecture.
//
virtual DWORD getExpectedTargetArchitecture() = 0;
+
+#if COR_JIT_EE_VERSION > 460
+ // Fetches extended flags for a particular compilation instance. Returns
+ // the number of bytes written to the provided buffer.
+ virtual DWORD getJitFlags(
+ CORJIT_FLAGS* flags, /* IN: Points to a buffer that will hold the extended flags. */
+ DWORD sizeInBytes /* IN: The size of the buffer. Note that this is effectively a
+ version number for the CORJIT_FLAGS value. */
+ ) = 0;
+#endif
};
/**********************************************************************************/
JITHELPER1(CORINFO_HELP_THROW_ARGUMENTEXCEPTION, JIT_ThrowArgumentException, CORINFO_HELP_SIG_REG_ONLY, MDIL_HELP_UNDEF)
JITHELPER1(CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, JIT_ThrowArgumentOutOfRangeException, CORINFO_HELP_SIG_REG_ONLY, MDIL_HELP_UNDEF)
+ JITHELPER1(CORINFO_HELP_JIT_PINVOKE_BEGIN, NULL, CORINFO_HELP_SIG_UNDEF, MDIL_HELP_UNDEF)
+ JITHELPER1(CORINFO_HELP_JIT_PINVOKE_END, NULL, CORINFO_HELP_SIG_UNDEF, MDIL_HELP_UNDEF)
+
#endif // COR_JIT_EE_VERSION
#undef JITHELPER1
}
inline
-void Compiler::compInitOptions(unsigned compileFlags)
+void Compiler::compInitOptions(CORJIT_FLAGS* jitFlags)
{
#ifdef UNIX_AMD64_ABI
opts.compNeedToAlignFrame = false;
#endif // UNIX_AMD64_ABI
memset(&opts, 0, sizeof(opts));
+ unsigned compileFlags = jitFlags->corJitFlags;
+
if (compIsForInlining())
{
assert((compileFlags & CORJIT_FLG_LOST_WHEN_INLINING) == 0);
assert(compileFlags & CORJIT_FLG_SKIP_VERIFICATION);
}
-
+
+ opts.jitFlags = jitFlags;
opts.eeFlags = compileFlags;
opts.compFlags = CLFLG_MAXOPT; // Default value is for full optimization
//
void Compiler::compCompile(void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags)
+ CORJIT_FLAGS * compileFlags)
{
hashBv::Init(this);
fgRemoveEH();
#endif // !FEATURE_EH
- if (compileFlags & CORJIT_FLG_BBINSTR)
+ if (compileFlags->corJitFlags & CORJIT_FLG_BBINSTR)
{
fgInstrumentMethod();
}
CORINFO_METHOD_INFO * methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags)
+ CORJIT_FLAGS * compileFlags)
{
#ifdef FEATURE_JIT_METHOD_PERF
static bool checkedForJitTimeLog = false;
// Set this before the first 'BADCODE'
// Skip verification where possible
- tiVerificationNeeded = ((compileFlags & CORJIT_FLG_SKIP_VERIFICATION) == 0);
+ tiVerificationNeeded = (compileFlags->corJitFlags & CORJIT_FLG_SKIP_VERIFICATION) == 0;
assert(!compIsForInlining() || !tiVerificationNeeded); // Inlinees must have been verified.
CORINFO_METHOD_INFO * methodInfo;
void * * methodCodePtr;
ULONG * methodCodeSize;
- unsigned compileFlags;
+ CORJIT_FLAGS * compileFlags;
CorInfoInstantiationVerification instVerInfo;
int result;
CORINFO_METHOD_INFO * methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags,
+ CORJIT_FLAGS * compileFlags,
CorInfoInstantiationVerification instVerInfo)
{
CORINFO_METHOD_HANDLE methodHnd = info.compMethodHnd;
CORINFO_METHOD_INFO* methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags,
+ CORJIT_FLAGS * compileFlags,
void * inlineInfoPtr
)
{
CORINFO_METHOD_INFO* methodInfo;
void * * methodCodePtr;
ULONG * methodCodeSize;
- unsigned compileFlags;
+ CORJIT_FLAGS * compileFlags;
InlineInfo * inlineInfo;
int result;
jitFallbackCompile = true;
// Update the flags for 'safer' code generation.
- compileFlags |= CORJIT_FLG_MIN_OPT;
- compileFlags &= ~(CORJIT_FLG_SIZE_OPT | CORJIT_FLG_SPEED_OPT);
+ compileFlags->corJitFlags |= CORJIT_FLG_MIN_OPT;
+ compileFlags->corJitFlags &= ~(CORJIT_FLG_SIZE_OPT | CORJIT_FLG_SPEED_OPT);
goto START;
}
struct Options
{
- unsigned eeFlags; // flags passed from the EE
+ CORJIT_FLAGS* jitFlags; // all flags passed from the EE
+ unsigned eeFlags; // CorJitFlag flags passed from the EE
unsigned compFlags; // method attributes
codeOptimize compCodeOpt; // what type of code optimizations
CORINFO_METHOD_INFO * methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags);
+ CORJIT_FLAGS * compileFlags);
void compCompileFinish();
int compCompileHelper (CORINFO_MODULE_HANDLE classPtr,
COMP_HANDLE compHnd,
CORINFO_METHOD_INFO * methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags,
+ CORJIT_FLAGS * compileFlags,
CorInfoInstantiationVerification instVerInfo);
norls_allocator * compGetAllocator();
unsigned compMaxUncheckedOffsetForNullObject;
- void compInitOptions (unsigned compileFlags);
+ void compInitOptions (CORJIT_FLAGS* compileFlags);
void compSetProcessor();
void compInitDebuggingInfo();
#endif
void compCompile (void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags);
+ CORJIT_FLAGS * compileFlags);
// Data required for generating profiler Enter/Leave/TailCall hooks
#ifdef PROFILING_SUPPORTED
return g_realJitCompiler->compileMethod(compHnd, methodInfo, flags, entryAddress, nativeSizeOfCode);
}
+ CORJIT_FLAGS jitFlags = { 0 };
+
+ DWORD jitFlagsSize = 0;
+#if COR_JIT_EE_VERSION > 460
+ if (flags == CORJIT_FLG_CALL_GETJITFLAGS)
+ {
+ jitFlagsSize = compHnd->getJitFlags(&jitFlags, sizeof(jitFlags));
+ }
+#endif
+
+ assert(jitFlagsSize <= sizeof(jitFlags));
+ if (jitFlagsSize == 0)
+ {
+ jitFlags.corJitFlags = flags;
+ }
+
int result;
void * methodCodePtr = NULL;
CORINFO_METHOD_HANDLE methodHandle = methodInfo->ftn;
methodInfo,
&methodCodePtr,
nativeSizeOfCode,
- flags,
+ &jitFlags,
NULL);
if (result == CORJIT_OK)
pParam->pThis->eeGetMethodFullName(pParam->fncHandle),
pParam->pThis->dspPtr(pParam->inlineInfo->tokenLookupContextHandle)));
- unsigned compileFlagsForInlinee = (pParam->pThis->opts.eeFlags & ~CORJIT_FLG_LOST_WHEN_INLINING)
- | CORJIT_FLG_SKIP_VERIFICATION;
+ CORJIT_FLAGS compileFlagsForInlinee;
+ memcpy(&compileFlagsForInlinee, pParam->pThis->opts.jitFlags, sizeof(compileFlagsForInlinee));
+ compileFlagsForInlinee.corJitFlags &= ~CORJIT_FLG_LOST_WHEN_INLINING;
+ compileFlagsForInlinee.corJitFlags |= CORJIT_FLG_SKIP_VERIFICATION;
#ifdef DEBUG
if (pParam->pThis->verbose)
&pParam->inlineCandidateInfo->methInfo,
(void**)pParam->inlineInfo,
NULL,
- compileFlagsForInlinee,
+ &compileFlagsForInlinee,
pParam->inlineInfo);
if (result != CORJIT_OK)
CORINFO_METHOD_INFO * methodInfo,
void * * methodCodePtr,
ULONG * methodCodeSize,
- unsigned compileFlags,
+ CORJIT_FLAGS * compileFlags,
void * inlineInfoPtr
);
if (call->gtCallType != CT_INDIRECT)
{
- GenTree* indir = nullptr;
-
noway_assert(call->gtCallType == CT_USER_FUNC);
CORINFO_METHOD_HANDLE methHnd = call->gtCallMethHnd;
- void* pAddr;
- addr = comp->info.compCompHnd->getAddressOfPInvokeFixup(methHnd, (void**)&pAddr);
-
- if (addr != nullptr)
+ CORINFO_CONST_LOOKUP lookup;
+#if COR_JIT_EE_VERSION > 460
+ comp->info.compCompHnd->getAddressOfPInvokeTarget(methHnd, &lookup);
+#else
+ void* pIndirection;
+ lookup.accessType = IAT_PVALUE;
+ lookup.addr = comp->info.compCompHnd->getAddressOfPInvokeFixup(methHnd, &pIndirection);
+ if (lookup.addr == nullptr)
{
- indir = Ind(AddrGen(addr));
+ lookup.accessType = IAT_PPVALUE;
+ lookup.addr = pIndirection;
}
- else
+#endif
+
+ GenTree* address = AddrGen(lookup.addr);
+ switch (lookup.accessType)
{
- // double indirection
- indir = Ind(Ind(AddrGen(pAddr)));
+ case IAT_VALUE:
+ result = address;
+ break;
+
+ case IAT_PVALUE:
+ result = Ind(address);
+ break;
+
+ case IAT_PPVALUE:
+ result = Ind(Ind(address));
+ break;
}
- result = indir;
}
+
InsertPInvokeCallEpilog(call);
return result;
return result;
}
+/*********************************************************************/
+ // return address of fixup area for late-bound N/Direct calls.
+void CEEInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method,
+ CORINFO_CONST_LOOKUP *pLookup)
+{
+ WRAPPER_NO_CONTRACT;
+
+ void *pIndirection;
+ pLookup->accessType = IAT_PVALUE;
+ pLookup->addr = getAddressOfPInvokeFixup(method, &pIndirection);
+ _ASSERTE(pIndirection == NULL);
+}
/*********************************************************************/
CORINFO_JUST_MY_CODE_HANDLE CEEInfo::getJustMyCodeHandle(
return handle;
}
+/*********************************************************************/
+DWORD CEEInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
+{
+ CONTRACTL {
+ SO_TOLERANT;
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_PREEMPTIVE;
+ } CONTRACTL_END;
+
+ JIT_TO_EE_TRANSITION_LEAF();
+
+ EE_TO_JIT_TRANSITION_LEAF();
+
+ return 0;
+}
+
/*********************************************************************/
IEEMemoryManager* CEEInfo::getMemoryManager()
{
bool canGetVarArgsHandle(CORINFO_SIG_INFO *sig);
void* getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void **ppIndirection);
void* getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, void **ppIndirection);
+ void getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup);
CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle(CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE **ppIndirection);
void GetProfilingHandle(
// Performs any work JIT-related work that should be performed at process shutdown.
void JitProcessShutdownWork();
+ DWORD getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes);
+
private:
// Shrinking these buffers drastically reduces the amount of stack space
// required for each instance of the interpreter, and thereby reduces SOs.
offsetof(CORCOMPILE_EE_INFO_TABLE, gsCookie));
}
+DWORD ZapInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
+{
+ _ASSERTE(jitFlags != NULL);
+
+ return 0;
+}
+
IEEMemoryManager* ZapInfo::getMemoryManager()
{
return GetEEMemoryManager();
return NULL;
}
+void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup)
+{
+ _ASSERTE(pLookup != NULL);
+
+ void * pIndirection;
+ void * pResult = getAddressOfPInvokeFixup(method, &pIndirection);
+ if (pResult != NULL)
+ {
+ pLookup->accessType = IAT_PVALUE;
+ pLookup->addr = pResult;
+ return;
+ }
+
+ pLookup->accessType = IAT_PPVALUE;
+ pLookup->addr = pIndirection;
+}
+
CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle(
CORINFO_METHOD_HANDLE method,
CORINFO_JUST_MY_CODE_HANDLE **ppIndirection)
ICorJitInfo::ProfileBuffer ** profileBuffer,
ULONG * numRuns);
+ DWORD getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes);
+
// ICorDynamicInfo
DWORD getThreadTLSIndex(void **ppIndirection);
void **ppIndirection);
void * getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,
void **ppIndirection);
+ void getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method,
+ CORINFO_CONST_LOOKUP *pLookup);
CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle(
CORINFO_METHOD_HANDLE method,
CORINFO_JUST_MY_CODE_HANDLE **ppIndirection);